Openhab GPIO setzten

Moderatoren: seppy, udo1toni

Antworten
hansi001
Beiträge: 6
Registriert: 4. Nov 2020 12:17

Openhab GPIO setzten

Beitrag von hansi001 »

Hallo zusammen,

ich habe mir eine Holztrocknungsanlage gebaut, die an einer Biogas Anlage angeschlossen ist.
Um die Temperatur und Luftfeuchtigkeit zu überwachen, habe ich einen Raspberry pi 3B mit Openhab und einem DHT22 Sensor ausgestattet.
Jetzt möchte ich gerne, sobald die Luftfeuchtigkeit im Container über den Wert X steigt für die Zeit X eine Pumpe zur Berieselung aktivieren und das einfach über ein Relais, dass am GPIO angeschlossen ist.
Ich tue mich noch schwer mit dem Programmieren, da bis jetzt immer alles was ich brauchte aus Anleitungen übernehmen konnte.

Hier mal das was funktuoniert:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
 
import Adafruit_DHT
import sys, time
 
# constants
DHT_PIN = 23                    # GPIO nr
DHT_SENSOR = Adafruit_DHT.DHT22     
 
if __name__ == '__main__':
    if len(sys.argv) > 1:
        call = sys.argv[1].lower()
 
        if call == 'temperature':
            temperature = None
            while temperature == None:
               _, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
               if temperature == None:
                   time.sleep(1.5)
            print(temperature)
 
        elif call == 'humidity':
            humidity = None
            while humidity == None:
               humidity, _ = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
               if humidity == None:
                   time.sleep(1.5)
           print(humidity)

Code: Alles auswählen

Thing exec:command:weatherstation_temperature "Temperatur"    [command="/etc/openhab2/scripts/weatherstation.py temperature$
Thing exec:command:weatherstation_humidity "Luftfeuchtigkeit" [command="/etc/openhab2/scripts/weatherstation.py humidity", $

Code: Alles auswählen

Group  Weatherstation_Chart (System, Charts)
Number Weatherstation_Chart_Period "Periode" (System)
Number Weatherstation_Temperature "Temperatur [%.1f °C]" <temperature> (Weatherstation_Chart)
Number Weatherstation_Humidity    "Luftfeuchtigkeit [%.1f %%]" <humidity> (Weatherstation_Chart)


String temperature_out { channel="exec:command:weatherstation_temperature:output" }
String humidity_out    { channel="exec:command:weatherstation_humidity:output" }


Code: Alles auswählen

Strategies {
    // for rrd charts, we need a cron strategy, every Minute is a must have.
    everyMinute : "0 * * * * ?"
    // get the data reduced for older values to keep database small
    everyHour : "0 0 * * * ?"
    everyDay : "0 0 0 * * ?"

    default = everyChange
}

Items {
    // additionally persist Items
    Weatherstation_Chart* : strategy = everyUpdate, everyMinute
}



Code: Alles auswählen


rule "Weatherstation Temperature"
  when
     Item temperature_out received update
  then
      Weatherstation_Temperature.postUpdate(
          ( ( Float::parseFloat(temperature_out.state.toString) as Number ) * 10 ) / 10
      )

end

rule "Weatherstation Humidity"
  when
     Item humidity_out received update
  then
      Weatherstation_Humidity.postUpdate(
          ( ( Float::parseFloat(humidity_out.state.toString) as Number ) * 10 ) / 10
      )
end

Code: Alles auswählen


// Name of file and name of sitemap has to be the same
sitemap weatherstation label="Raspberry Pi Wetterstation"
{
        Frame label="Innentemperatur" {
            Text item=Weatherstation_Temperature
            Text item=Weatherstation_Humidity
        }
        Frame {
            Switch item=Weatherstation_Chart_Period mappings=[0="1h", 1="4h", 2="8h", 3="12h", 4="24h"]
            Chart  item=Weatherstation_Chart period=h   refresh=60000 visibility=[Weatherstation_Chart_Period==0, Weatherst$
            Chart  item=Weatherstation_Chart period=4h  refresh=60000 visibility=[Weatherstation_Chart_Period==1]
            Chart  item=Weatherstation_Chart period=8h  refresh=60000 visibility=[Weatherstation_Chart_Period==2]
            Chart  item=Weatherstation_Chart period=12h refresh=60000 visibility=[Weatherstation_Chart_Period==3]
            Chart  item=Weatherstation_Chart period=D   refresh=60000 visibility=[Weatherstation_Chart_Period==4]
        }
}
Und hier mein Versuch das Relais zu schalten :lol:

Code: Alles auswählen

rule "Relais"
when
    Item humidity_out <= 50
then
     channe22.sendCommand (ON)


    end

Wäre super, wenn mir jemand weiter helfen könnte.

Gruß
Hansi

Benutzeravatar
udo1toni
Beiträge: 13864
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Openhab GPIO setzten

Beitrag von udo1toni »

Was mir erst mal auffällt: Das hier:

Code: Alles auswählen

rule "Weatherstation Temperature"
  when
     Item temperature_out received update
  then
      Weatherstation_Temperature.postUpdate(
          ( ( Float::parseFloat(temperature_out.state.toString) as Number ) * 10 ) / 10
      )

end
ist etwas seltsam.
Das "as Number" ist in diesem Fall unnötig, da parseFloat per Definition immer eine Zahl liefert. Die Zahl mit 10 zu multiplizieren und anschließend wieder durch 10 zu teilen hat hier auch keinen Effekt. Anders sähe es aus, wenn Du noch den Integer nutztest, dann hättest Du damit alle bis auf eine Nachkommastelle abgeschnitten. Das ist allerdings unnötig. Diese Rule wäre also ausreichend:

Code: Alles auswählen

rule "Weatherstation Temperature"
when
    Item temperature_out changed
then
    Weatherstation_Temperature.postUpdate(Float::parseFloat(temperature_out.state.toString))
end
Man bemerke auch den geänderten Trigger. Die Rule muss lediglich triggern, wenn sich der Wert geändert hat. Das Gleiche gilt natürlich auch für den anderen Messwert.
Dein Versuch, das Relais zu schalten zeigt, dass Du die Rules noch nicht vollständig verinnerlicht hast ;)
Im when-Teil der Rule werden Trigger aufgeführt. Trigger sind Ereignisse. Das kann also ein Update oder ein Change sein, nicht aber ein Zustand (Item <= 50 ist ein Zustand).
Die Rule kann und darf nur triggern, wenn sich der Wert geändert hat. Da es nicht möglich ist, hier Wertebereiche anzugeben, muss der Trigger also

Code: Alles auswählen

Item Weatherstation_Humidity changed
lauten. Der Trigger auf humidity_out ist zwar möglich, aber dann musst Du nochmal auf den Zahlenwert umrechnen, denn wir wollen ja Zahlen vergleichen.
Nachdem die Rule getriggert hat (also bei Wertänderung) können wir in der Folge innerhalb der Rule Vergleiche anstellen, und zwar mittels if().
Das sieht dann so aus:

Code: Alles auswählen

rule "Relais steuern"
when
    Item Weatherstation_Temperature changed
then
    if(!(Weatherstation_Temperature.state instanceof Number))    // Keine gültige Zahl, also
        return;                                                  // Abbruch der Rule
    var relay = NULL                                             // Variable mit Wert NULL definieren
    if((Weatherstation_Temperature.state as Number) <= 50)       // falls Feuchtigkeit unter 50
        relay = ON                                               // Soll = Einschalten
    else if((Weatherstation_Temperature.state as Number) >= 55)  // falls Feuchtigkeit über 55
        relay = OFF                                              // Soll = Auschalten
    if(relay != NULL)                                            // falls Soll nicht NULL prüfen ob
        if(channe22.state != relay)                              // falls aktueller Status vom Soll abweicht
            channe22.sendCommand(relay)                          // Relais auf Soll schalten
end
Der erste Vergleich in der Rule prüft, ob überhaupt ein gültiger Wert geliefert wird. Ist das nicht der Fall (das ist das !), wird die Rule abgebrochen, da es sonst in der Folge zu einer NullPointerException kommt.
Nun wird eine Variable definiert, die mit NULL vorbelegt wird.
Der zweite Vergleich prüft, ob die Zahl kleiner oder gleich 50 ist (unterer Grenzwert). Ist das der Fall, muss die Berieselung eingeschaltet werden, also wird die Variable auf ON geändert.
Der dritte Vergleich kommt zum Zug, falls der zweite Vergleich nicht erfüllt war. Hier wird geprüft, ob die Zahl größer oder gleich 55 ist (oberer Grenzwert) Ist das der Fall, muss die Berieselung beendet werden und entsprechend wird die Variable auf OFF geändert.
Der vierte Vergleich prüft nun, ob die Variable ungleich dem Wert NULL ist. Ist das der Fall, prüft der letzte Vergleich, ob der Ist-Zustand des Relais vom Soll abweicht.. Ist das der Fall, wird der Steuerbefehl gesendet.

Die Rule sieht auf den ersten Blick unnötig kompliziert aus :) jedoch ist die Vorgehensweise sinnvoll. Der Punkt: es werden nur dann Steuerbefehle gesendet, wenn dies auch wirklich notwendig ist. Es wird verhindert, dass das Relais unnötig oft umgesteuert wird (<=50 -> ON, >50 -> OFF).
Durch den Einsatz der Variablen sind die Vergleiche simpel und es wird nur einmal innerhalb der Rule auf den Status des Items channe22 zugegriffen. Auch der Steuerbefehl wird nur einmal verwendet.
Man könnte den Ausdruck (Weatherstation_Temperature.state as Number) ebenfalls in einer Variablen hinterlegen, um hier noch ein paar Taktzyklen zu optimieren, aber vermutlich ist das eher "Overengineering" :)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

hansi001
Beiträge: 6
Registriert: 4. Nov 2020 12:17

Re: Openhab GPIO setzten

Beitrag von hansi001 »

Hallo udo1toni,

vielen Dank für die schnelle Rückmeldung.
Wenn ich heute Abend zuhause bin, werde ich das gleich mal testen und mich dann zurück melden.

Gruß

hansi001
Beiträge: 6
Registriert: 4. Nov 2020 12:17

Re: Openhab GPIO setzten

Beitrag von hansi001 »

Hallo,

ich habe die Rule geändert bekomme aber im Log immer wieder diesen Fehler

Code: Alles auswählen

2020-11-04 16:14:32.522 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Relais steuern': The name 'channel22' cannot be resolved to an item or type; line 13, column 12, length 8
Anscheinend kann der GPIO22 nicht angesteuert werden. Hast du eine Idee woran das liegen kann?

hansi001
Beiträge: 6
Registriert: 4. Nov 2020 12:17

Re: Openhab GPIO setzten

Beitrag von hansi001 »

Hallo,
habe noch mal etwas rumgespielt.

habe den Code etwas geändert, jetzt funktioniert es erstmal.

Code: Alles auswählen

var Timer tDelay = null

rule "Relais steuern"

when
    Item Weatherstation_Humidity changed
then
    if(!(Weatherstation_Humidity.state instanceof Number))    // Keine gültige Zahl, also
        return;                                                  // Abbruch der Rule
    var relay = NULL                                             // Variable mit Wert NULL definieren
    if((Weatherstation_Humidity.state as Number) <= 60)       // falls Feuchtigkeit unter 50
       channel22.sendCommand(ON)                               // Relais an
tDelay = createTimer(now.plusSeconds(30), [ |                // Timer 30 sec
            channel22.sendCommand(OFF)                         //Relais ausschalten
        ])
end

Code: Alles auswählen

Switch channel22  { gpio="pin:22 activelow:yes initialValue:high" }
Es hatte das Item für das GPIO gefehlt, aber dein Code hatte so trotzdem nicht funktioniert.

Benutzeravatar
peter-pan
Beiträge: 2564
Registriert: 28. Nov 2018 12:03
Answers: 25
Wohnort: Schwäbisch Gmünd

Re: Openhab GPIO setzten

Beitrag von peter-pan »

Ja dann gibt es das Item "channel22" nicht. Das hast du ja aber selber in deiner Regel

Code: Alles auswählen

rule "Relais"
when
    Item humidity_out <= 50
then
     channe22.sendCommand (ON)
 end
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.1.1 openhabian

hansi001
Beiträge: 6
Registriert: 4. Nov 2020 12:17

Re: Openhab GPIO setzten

Beitrag von hansi001 »

Hi,

vielen Dank für eure Unterstützung.
Ich werde mich bestimmt noch einmal melden, sollte mal wieder Probleme geben :D

Gruß

Antworten