Ultraschallsensor HC-SR04 in FHEM einbinden

Begonnen von Jogi, 24 März 2017, 17:16:24

Vorheriges Thema - Nächstes Thema

Jogi

Hallo zusammen,
ich möchte den Ultraschallsensor HC-SR04 in FHEM einbinden und habe dazu schon einige Beiträge gelesen.
Ich habe es dann so gemacht wie in dem ersten Beitrag hier:
https://forum.fhem.de/index.php?topic=19812.0

Aber leider funktioniert es nicht. Bei state steht immer nur die nächste Einlesezeit, z.B. :Next: 17:06:27
und der dummy steht auf ???

Wenn ich per SSH direkt auf den Pi gehe und es so mache:

https://tutorials-raspberrypi.de/entfernung-messen-mit-ultraschallsensor-hc-sr04/

dann funktioniert es, aber natürlich nicht mit FHEM.

Ich habe zwar einige Beiträge gelesen, in denen User das scheinbar in FHEM realisiert haben und Probleme mit unterschiedlichen Werten haben, aber in keinem dieser Beiträge ist erwähnt wie es eingebunden wurde.

Ich habe dann irgendwo gelesen, dass man FHEM noch freigeben muss
an die /etc/sudoers anhängen

fhem ALL=(ALL) NOPASSWD: ALL

damit darf user fhem alles per sudo ausführen ohne nach einem passwort zu fragen.

Das hat aber auch nicht funktioniert.

Wer hat einen Tipp?


Vielen Dank!

Thorsten Pferdekaemper

Hi,
ja, versuche mal, die einzelnen Teile alleine auszuführen. Z.B. mal auf Kommandozeilenebene (Linux) das Skript ausführen. Wenn es unter dem User pi nicht funktioniert, dann mal als root versuchen.
...und gib uns mal ein list von dem Dummy.
Gruß,
   Thorsten
FUIP

KölnSolar

Zitat...und gib uns mal ein list von dem Dummy.
und der Zeile im python-script mit dem FHEM-Aufruf, sofern nicht identisch mit dem Skript aus dem genannten Thread  ;)
Grüße Markus
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

salvadore

Hallo Jogi,

ich habe es so gelöst, wobei ich davon ausgehe, dass die Messung auf einem eigenen Raspi erfolgt und der die Ergebnisse an einen fhemServer zwecks weiterer Auswertung weitergibt:

- auf dem Mess-Raspi einen mount-Punkt erstellt z.B. Eintrag in fstab > 192.168.178.4:/opt/fhem/log /mnt/fhem-log nfs  defaults   0   0
- ein Script "ultra.py" erstellt, welches über einen Cron-Job z.B. stündlich aufgerufen wird -das Script ist nicht von mir, im Netz gefunden und angepasst-
- in fhem Log-Verzeichnis die geforderte Log-Datei erstellt
- einen Plot erstellt

Läuft so wie es soll, habe nur zusätzlich noch einen watchdog laufen sowie als Cron-Job eine Sicherung der SD-Karte des Raspi auf NAS-LW

gruss
salvadore
FHEM 5.6, APU-Board, CUNO 1.x, RFXtrx433, 8 FHT80B, diverse FS20 Aktoren, Rasperry, div. DS18x-Sensoren, KD101, AB400R, HE877, ESA2000, Beaglebone Black Rev.C, Jeelink, PCA 301, PT8005,

Jogi

Zitat von: KölnSolar am 24 März 2017, 18:58:54
und der Zeile im python-script mit dem FHEM-Aufruf, sofern nicht identisch mit dem Skript aus dem genannten Thread  ;)
Grüße Markus
Ich versuche mal alle Daten zu liefern:
Ich habe das ganze momentan auf einem Raspberry laufen, den ich nur zu Testzwecken nutze.
Die FHEM.cfg sieht wie folgt aus:
attr global userattr cmdIcon devStateIcon devStateStyle icon sortby webCmd widgetOverride
attr global autoload_undefined_devices 1
attr global backup_before_update 1
attr global latitude 51.0212081
attr global logfile ./log/fhem-%Y-%m.log
attr global longitude 6.8200973
attr global modpath .
attr global room ttr
attr global statefile ./log/fhem.save
attr global updateInBackground 1
attr global verbose 3

define telnetPort telnet 7072 global
attr telnetPort SSL 1

define WEB FHEMWEB 8083 global
attr WEB JavaScripts pgm2/clock.js
attr WEB column 1.Start:Temperatur,Status,Szenarien|Lampen,Schalter 2.Kinder:Alina|Benjamin 3.Temperatur:Wetter,Alina|Temperatur,Benjamin 4.Technik:Status,Schalter,Temperatur,Multimedia,Kamera|EG,Alina,Benjamin 7.Aussen:Status,Schalter|Lampen|LED 8.Heizung:Heizung|LED|FileLog
attr WEB editConfig 1
define allowed_WEB allowed
attr allowed_WEB basicAuth RkhFTToxODgzMDc=
attr allowed_WEB validFor WEB

define WEBphone FHEMWEB 8084 global
attr WEBphone JavaScripts pgm2/clock.js
define allowed_WEBphone allowed
attr allowed_WEBphone basicAuth RkhFTToxODgzMDc=
attr allowed_WEBphone validFor WEBphone

define WEBtablet FHEMWEB 8085 global
attr WEBtablet JavaScripts pgm2/clock.js
attr WEBtablet stylesheetPrefix touchpad
define allowed_WEBtablet allowed
attr allowed_WEBtablet basicAuth RkhFTToxODgzMDc=
attr allowed_WEBtablet validFor WEBtablet

# Fake FileLog entry, to access the fhem log from FHEMWEB
define Logfile FileLog ./log/fhem-%Y-%m-%d.log fakelog
attr Logfile nrarchive 3

define autocreate autocreate
attr autocreate disable 0
attr autocreate filelog ./log/%NAME-%Y.log
attr autocreate room 99.Programm

define eventTypes eventTypes ./log/eventTypes.txt

# Disable this to avoid looking for new USB devices on startup
define initialUsbCheck notify global:INITIALIZED usb create
define allowed_telnetPort allowed
attr allowed_telnetPort password FHEM
attr allowed_telnetPort validFor telnetPort
##
##
##
###########
##
# Ultraschall
#
define UC1 dummy
attr UC1 room Test
attr UC1 stateFormat Abstand
attr UC1 userReadings Abstand
define at_UC1 at +*00:00:03 {system 'sudo /usr/bin/python /opt/fhem/FHEM/UC1.sh &'}
attr at_UC1 room Test
attr at_UC1 verbose 0
#######

Die Python-Datei habe ich 1:1 übernommen. Ich habe nur die GPIO´s abgeändert:
GPIO.setmode(GPIO.BCM)
GPIO_TRIGGER = 18   ####  evtl. GPIO anpassen
GPIO_ECHO    = 24   ####  evtl. GPIO anpassen

Alles andere ist unverändert.
Wenn ich in SSH folgende Zeile eingebe:
sudo /usr/bin/python /opt/fhem/FHEM/UC1.sh

bekomme ich diese Meldung:
pi@raspberrypi:~ $ sudo /usr/bin/python /opt/fhem/FHEM/UC1.sh
/opt/fhem/FHEM/UC1.sh:60: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo
Use of uninitialized value in numeric gt (>) at /opt/fhem/fhem.pl line 447.


Führe ich den Befehl als root aus bekomme ich dieselbe Meldung:

pi@raspberrypi:~ $ sudo su
root@raspberrypi:/home/pi# /usr/bin/python /opt/fhem/FHEM/UC1.sh
/opt/fhem/FHEM/UC1.sh:60: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo
Use of uninitialized value in numeric gt (>) at /opt/fhem/fhem.pl line 447.
root@raspberrypi:/home/pi#


Tipps sind willkommen.
Vielen Dank!

Thorsten Pferdekaemper

Hi,
ok, Du magst kein list UC1 liefern. Warum auch immer.
Also erstmal: Das hier ist Quatsch:

attr UC1 userReadings Abstand

Ich weiß nicht genau, was das macht, aber bestimmt nichts richtiges. Wahrscheinlich löscht es das Reading Abstand sobald es gesetzt wird. Du solltest das Attribut userReadings komplett löschen.
Dann bau Dir mal in das Skript bevor das ganze an FHEM übergeben wird eine Debug-Zeile (print distanceRet oder so) ein, damit man sieht, ob da überhaupt was geht.
Die Fehlermeldung deutet darauf hin, dass Pin 24 schon für irgend etwas benutzt wird. Keine Ahnung, ob das ein Problem ist. Du solltest das aber mal prüfen.
Gruß,
   Thorsten
FUIP

Jogi

Zitat von: Thorsten Pferdekaemper am 26 März 2017, 12:50:31
Hi,
ok, Du magst kein list UC1 liefern. Warum auch immer.
Also erstmal: Das hier ist Quatsch:

attr UC1 userReadings Abstand

Ich weiß nicht genau, was das macht, aber bestimmt nichts richtiges. Wahrscheinlich löscht es das Reading Abstand sobald es gesetzt wird. Du solltest das Attribut userReadings komplett löschen.
Dann bau Dir mal in das Skript bevor das ganze an FHEM übergeben wird eine Debug-Zeile (print distanceRet oder so) ein, damit man sieht, ob da überhaupt was geht.
Die Fehlermeldung deutet darauf hin, dass Pin 24 schon für irgend etwas benutzt wird. Keine Ahnung, ob das ein Problem ist. Du solltest das aber mal prüfen.
Gruß,
   Thorsten
Ich liefere Dir sehr gerne alles, aber was meinst Du damit ein "List" liefern? Was genau soll ich machen. Ich bin hier in einem Anfängerforum und beschäftige mich erst seit ein paar Monaten mit FHEM. Ich weiß wirklich nicht, was Du meinst. Vielleicht ist es ja ganz einfach ...  Bitte eine Anweisung, was ich machen soll, dann liefere ich alles.

KölnSolar

#7
es git einen FHEM-Befehl list. näheres in der commandref.
@Thorsten: doch, das mit dem Attribut ist schon richtig. Das Skript befüllt das userreading Abstand im device UC1 mit setreading.
ZitatDie Fehlermeldung deutet darauf hin, dass Pin 24 schon für irgend etwas benutzt wird.
sehe ich ähnlich...
Edit: das ist Zeile 60
GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

Jogi

Zitat von: KölnSolar am 26 März 2017, 14:22:13
es git einen FHEM-Befehl list. näheres in der commandref.
Wenn ich
list UC1
eingebe kommt folgendes:
Internals:
   NAME       UC1
   NR         31
   STATE      ???
   TYPE       dummy
Attributes:
   room       Test
   stateFormat Abstand
   userReadings Abstand


Ich habe´die GPIO´s nun mal verändert auf andere Adressen, aber ich bekomme dieselbe Fehlermeldung:
pi@raspberrypi:/opt/fhem/FHEM $ sudo /usr/bin/python /opt/fhem/FHEM/UC1.sh
/opt/fhem/FHEM/UC1.sh:59: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(GPIO_TRIGGER,GPIO.OUT)  # Trigger
/opt/fhem/FHEM/UC1.sh:60: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo
Use of uninitialized value in numeric gt (>) at /opt/fhem/fhem.pl line 447.


Und wie schon weiter beschrieben, mache ich es direkt aus SSH wie in Post 1, dann funktioniert es.

Ich wüsste nicht, womit die GPIO anders belegt sein sollten. Wie aus meiner log-Datei hervor geht, ist es ein Test-Raspi, in dem nichts anderes definiert ist. Und aus SSh geht es ja auch, müsste es da dann nicht auch Probleme geben?



KölnSolar

#9
Zitatdann funktioniert es.
ja stimmt, wahrscheinlich ist die Meldung zu Zeile 60 nur eine uninteressante Warnung.

ich spekulier mal: das setreading funktioniert nur, wenn es das reading gibt. lt. Deinem list ist es nicht existent.
mach mal ein setreading UC1 Abstand 1 in FHEM
Edit: aber dann müsste doch eigentlich auch etwas im LOG stehen :-\
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

Thorsten Pferdekaemper

Zitat von: KölnSolar am 26 März 2017, 14:22:13@Thorsten: doch, das mit dem Attribut ist schon richtig. Das Skript befüllt das userreading Abstand im device UC1 mit setreading.sehe ich ähnlich...
Nein, das ist nicht so. userReadings sind solche, die praktisch vom Device selbst gefüllt werden. Ich bleibe dabei: Das Attribut userReading hat hier absolut nichts verloren.

Zitat von: KölnSolar am 26 März 2017, 14:58:01
ich spekulier mal: das setreading funktioniert nur, wenn es das reading gibt.
Ich spekuliere mal: Die Erde ist eine Scheibe.
"setreading" funktioniert immer. Es legt das Reading an, falls es das Reading nicht vorher schon gibt.

Zitat von: Jogi am 26 März 2017, 14:43:30Und wie schon weiter beschrieben, mache ich es direkt aus SSH wie in Post 1, dann funktioniert es.
Na dann nimm doch das funktionierende Skript und baue die fhem-Zeile sinngemäß mal nach dem print ein.

Gruß,
   Thorsten
FUIP

KölnSolar

#11
sorry Thorsten,
bevor Du tief in die Geschichtskiste greifst, solltest Du Dir ansehen, auf welche bei anderen FUNKTIONIERENDE Lösung sich der TE bezieht:
# --------------------------------------------------------
#                Rueckgabe an FHEM
# --------------------------------------------------------

distanceRet = "%.1f" % measure_average() # fuer Mittelwert Messung
#distanceRet = "%.1f" % measure()        # fuer einmalige Messung
if float(distanceRet) <= 400:
  os.system('perl /opt/fhem/fhem.pl 7072 "setreading UC1 Abstand '+str(distanceRet)+'"')
GPIO.cleanup()

define UC1 dummy
attr UC1 stateFormat Abstand
attr UC1 userReadings Abstand

Aber Du hast recht ein setrrading legt ein nicht existentes reading auch neu an.

@Jogi: Aufruf des Skripts bewirkt in FHEM nichts, oder doch ?
Edit: und wenn nicht, sicher, dass der Wert < 400 ist ? Kommentier ggfs. mal die if-Zeile zum Test.
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

Jogi

Zitat von: Thorsten Pferdekaemper am 26 März 2017, 16:59:32
Na dann nimm doch das funktionierende Skript und baue die fhem-Zeile sinngemäß mal nach dem print ein.
Ich glaube, ich habe mir zu viel vorgenommen. Jede Antwort, die ich bekomme wirft bei mir neue Fragezeichen auf.
Vielleicht bin ich noch nicht weit genug dafür.

Ich habe das jetzt mal umgebaut und es sieht jetzt so aus:
#Bibliotheken einbinden
import RPi.GPIO as GPIO
import time

#GPIO Modus (BOARD / BCM)
GPIO.setmode(GPIO.BCM)

#GPIO Pins zuweisen
GPIO_TRIGGER = 22
GPIO_ECHO = 23

#Richtung der GPIO-Pins festlegen (IN / OUT)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)

def distanz():
    # setze Trigger auf HIGH
    GPIO.output(GPIO_TRIGGER, True)

    # setze Trigger nach 0.01ms aus LOW
    time.sleep(0.00001)
    GPIO.output(GPIO_TRIGGER, False)

    StartZeit = time.time()
    StopZeit = time.time()

    # speichere Startzeit
    while GPIO.input(GPIO_ECHO) == 0:
        StartZeit = time.time()

    # speichere Ankunftszeit
    while GPIO.input(GPIO_ECHO) == 1:
        StopZeit = time.time()

    # Zeit Differenz zwischen Start und Ankunft
    TimeElapsed = StopZeit - StartZeit
    # mit der Schallgeschwindigkeit (34300 cm/s) multiplizieren
    # und durch 2 teilen, da hin und zurueck
    distanz = (TimeElapsed * 34300) / 2

    return distanz

if __name__ == '__main__':
    try:
        while True:
            abstand = distanz()
            print ("Gemessene Entfernung = %.1f cm" % abstand)
            time.sleep(1)

        # Beim Abbruch durch STRG+C resetten
    except KeyboardInterrupt:
        print("Messung vom User gestoppt")
        GPIO.cleanup()

# --------------------------------------------------------
#                Rueckgabe an FHEM
# --------------------------------------------------------
distanceRet = "%.1f" % measure_average() # fuer Mittelwert Messung
#distanceRet = "%.1f" % measure()        # fuer einmalige Messung
if float(distanceRet) <= 400:
  os.system('perl /opt/fhem/fhem.pl 7072 "setreading UC1 Abstand '+str(distanceRet)+'"')
GPIO.cleanup()

Alle vor "Rueckgabe an FHEM" ist das Script was unter SSH läuft und eine ständige Messung alle 3 Sekunden rausgibt.
Der Teil nach "Rueckgabe an FHEM" kommt aus dem ursprünglichen FHEM-Script.
ABER leider tut sich immer noch nichts.
Folgendes steht in dem at:


COMMAND
{system 'sudo /usr/bin/python /opt/fhem/FHEM/UC1.sh &'}
DEF 
+*00:00:03 {system 'sudo /usr/bin/python /opt/fhem/FHEM/UC1.sh &'}

NAME
at_UC1

NR
32

NTM
17:45:11

PERIODIC
yes

RELATIVE
yes

REP
-1

STATE
Next: 17:45:11

TIMESPEC
00:00:03

TRIGGERTIME
1490543111.38068

TRIGGERTIME_FMT
2017-03-26 17:45:11

TYPE
at

Readings
state

Next: 17:45:11
2017-03-26 17:45:08


Das dummy UC1 zeigt immer noch ? an.

Ich glaube, ich gebe es auf ...


KölnSolar

nochmal
@Jogi: Aufruf des Skripts bewirkt in FHEM nichts, oder doch ?
Edit: und wenn nicht, sicher, dass der Wert < 400 ist ? Kommentier ggfs. mal die if-Zeile zum Test.

wenn das Skript nichts bewirkt liegt das Problem hier
if float(distanceRet) <= 400:
  os.system('perl /opt/fhem/fhem.pl 7072 "setreading UC1 Abstand '+str(distanceRet)+'"')

vermutlich Berechtigungsgeschichten oder, oder, ....
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

Thorsten Pferdekaemper

Hi,
ich vermute mal, dass das Skript so gar nicht funktionieren kann. Nach dem hier...

if __name__ == '__main__':
    try:
        while True:

...geht das Ding in eine Schleife bis jemand Ctrl-C auslöst. Das macht fhem natürlich nie. Schau mal mit "ps" nach, ob noch Instanzen dieses Skripts laufen und kille sie alle.
Dann versuch's mal damit:

#Bibliotheken einbinden
import RPi.GPIO as GPIO
import time

#GPIO Modus (BOARD / BCM)
GPIO.setmode(GPIO.BCM)

#GPIO Pins zuweisen
GPIO_TRIGGER = 22
GPIO_ECHO = 23

#Richtung der GPIO-Pins festlegen (IN / OUT)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)

def distanz():
    # setze Trigger auf HIGH
    GPIO.output(GPIO_TRIGGER, True)

    # setze Trigger nach 0.01ms aus LOW
    time.sleep(0.00001)
    GPIO.output(GPIO_TRIGGER, False)

    StartZeit = time.time()
    StopZeit = time.time()

    # speichere Startzeit
    while GPIO.input(GPIO_ECHO) == 0:
        StartZeit = time.time()

    # speichere Ankunftszeit
    while GPIO.input(GPIO_ECHO) == 1:
        StopZeit = time.time()

    # Zeit Differenz zwischen Start und Ankunft
    TimeElapsed = StopZeit - StartZeit
    # mit der Schallgeschwindigkeit (34300 cm/s) multiplizieren
    # und durch 2 teilen, da hin und zurueck
    distanz = (TimeElapsed * 34300) / 2

    return distanz

if __name__ == '__main__':
    # --------------------------------------------------------
    #                Rueckgabe an FHEM
    # --------------------------------------------------------
    distanceRet = "%.1f" % measure_average() # fuer Mittelwert Messung
    #distanceRet = "%.1f" % measure()        # fuer einmalige Messung
    print ("Gemessene Entfernung = %.1f cm" % distanceRet)
    os.system('perl /opt/fhem/fhem.pl 7072 "setreading UC1 Abstand '+str(distanceRet)+'"')
    GPIO.cleanup()

Dieses Skript bitte auf der Kommandozeile (ssh) ausprobieren und noch nicht in FHEM einbinden. Was wird ausgegeben? Wie sieht danach "list UC1" aus?
Gruß,
   Thorsten
FUIP