3D-Drucker nach dem Druck stromlos schalten

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Antworten
Eleven
Beiträge: 53
Registriert: 15. Okt 2018 10:27

3D-Drucker nach dem Druck stromlos schalten

Beitrag von Eleven »

Hallo liebes Openhab Forum,

ich möchte gerne meinen 3D-Drucker nach dem Druck über eine Z-Wave Funksteckdose mit Strommessfunktion ausschalten. Hintergrund ist, das ab und an mal ein Druck erst in der Nacht fertig wird und somit der Drucker dann bis morgens im Standby läuft und dies zu unnötige Stromkosten führt.
Daher habe ich als erstes mal damit angefangen die Leistung des Druckes im Standby und Betrieb zu messen.

Standby: 7W
Betrieb: pendelt zwischen 75 und 250W

Nur zur rule.
Nun habe ich mir Gedacht das ich erstmal mit verschiedenen Zuständen des Druckers anfange, sprich wenn die Leistung <10 ist, dann ist der Drucker im Standby und bei >11 läuft ein Druck. Das Problem hier ist schon das er nach dem Druck trotz <10 immer noch "Druck läuft" anzeigt. Hinzu kommt das ich jetzt gar nicht wüsste wie ich ich die Abschaltung des Switches einbauen sollte, zumal ich gerne auch nach dem Druck bei erreichen der 7W noch einen Timer von 10 Minuten laufen lassen möchte, das sich die Lüfter ja noch eine weile weiter drehen.

hier mal das item:

Code: Alles auswählen

Switch  ZS_AZ2_Switch               "3D-Drucker"                            <poweroutlet>                                                       {channel="zwave:device:94d08eefd6:node29:switch_binary"}
Number  ZS_AZ2_Verbrauch_akt        "3D-Drucker [%.0f W]"                   <verbrauch>                                                         {channel="zwave:device:94d08eefd6:node29:meter_watts"}                                                                                        
Number  Drucker_Status              "3D-Drucker [MAP(drucker.map):%s]"
Meine aktuelle rule:

Code: Alles auswählen

val Number MODE_STANDBY = 0
val Number MODE_DRUCK = 1

//schalte Durcker nach erfolgreichem Druck aus.

rule "Beleuchtung komplett AUS" 
	when
		Item ZS_AZ2_Verbrauch_akt changed
	then
		if (ZS_AZ2_Verbrauch_akt.state <10) Drucker_Status.postUpdate(MODE_STANDBY)
        else (ZS_AZ2_Verbrauch_akt.state >11) Drucker_Status.postUpdate(MODE_DRUCK)
end 
Die map:

Code: Alles auswählen

0=Standby
1=Druck läuft
-=Error
NULL=unbekannt 
Könnt ihr mir hier weiterhelfen? Irgendwie sehe ich den Wald vor lauter Bäumen nicht.

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

Re: 3D-Drucker nach dem Druck stromlos schalten

Beitrag von udo1toni »

Erst mal ist die Formatierung Deines Codes zumindest fragwürdig ;)

Dein Problem rührt auch von der Formatierung, weil Du so nicht siehst, dass ein Schlüsselwort fehlt.

Code: Alles auswählen

val Number MODE_STANDBY = 0
val Number MODE_DRUCK = 1

//schalte Durcker nach erfolgreichem Druck aus.

rule "Beleuchtung komplett AUS" 
when
    Item ZS_AZ2_Verbrauch_akt changed
then
    if(ZS_AZ2_Verbrauch_akt.state < 10) 
        Drucker_Status.postUpdate(MODE_STANDBY)
    else if(ZS_AZ2_Verbrauch_akt.state > 11)
        Drucker_Status.postUpdate(MODE_DRUCK)
end 
Es gibt kein else (...) sondern nur ein else if(...), was eher auffällt, wenn der Code ordentlich formatiert ist.

Ein paar weitere Anmerkungen:
Zumindest, solange Du nur in dieser einen Rule auf die Konstanten zugreifst ist es witzlos das über Konstanten zu machen, schon gar über globale Konstanten.
Für den Timer bietet sich createTimer an. Sieht mit einigen Optimierungen nun so aus:

Code: Alles auswählen

// Globale Variablen und Konstanten vor der ersten Rule anlegen^!
var Timer tDrucker = null


rule "Beleuchtung komplett AUS"                                          // schalte Durcker nach erfolgreichem Druck aus.
when
    Item ZS_AZ2_Verbrauch_akt changed
then
    val Number nPower = if(ZS_AZ2_Verbrauch_akt.state instanceof Number) // falls Status eine gültige Zahl enthält
                            ZS_AZ2_Verbrauch_akt.state as Number         // nimm die Zahl
                        else                                             // ansonsten
                            0                                            // 0
    var Number nNewState = 0                                             // Default ist 0 -> Standby
    if(nPower > 11)                                                      // falls über 11
        nNewState = 1                                                    // setze auf 1 -> Druck

    if(Drucker_Status.state.toString != nNewState.toString) {            // Item nur bei Änderung setzen
        Drucker_Status.postUpdate(nNewState)                             // setze Item
        tDrucker?.cancel                                                 // lösche Timer, falls vorhanden
        if(nNewState != 1)                                               // nur falls Standby
            tDrucker = createTimer(now.plusMinutes(10), [|               // starte Timer
                ZS_AZ2_Switch.sendCommand(OFF)
            ])
    }
end 
Die Formatierung gleich des ersten Befehls ist etwas gewöhnungsbedürftig, hier ging es mir lediglich um die Dokumentation. Man könnte ebensogut auch

Code: Alles auswählen

    val Number nPower = if(newState instanceof Number) (newState as Number) else 0
schreiben, newState ist eine implizite Variable, die zur Verfügung steht, wenn die Rule über Item changed getriggert wurde. Sie enthält dann (dem Namen entsprechend) den neuen Status des triggernden Items. Den vorherigen Status (der unterscheidet sich ja, da changed...) gibt es ebenfalls implizit, mit previousState (bitte nicht mit der Persistence Methode Item.previousState verwechseln, die nur bei persistierten Items zur Verfügung steht. previousState steht bei jedem Item changed Ereignis zur Verfügung.
Im ersten Schritt errechne ich den neuen Sollstatus des Status Items. Nur falls dieser vom aktuellen Status abweicht, wird das Item überhaupt gesetzt. Du möchtest nicht alle paar Sekunden im Log sehen, dass der Status schon wieder auf Drucken gesetzt wurde.
Nur falls sich also der Status geändert hat, wird das Item auch geändert. Im nächsten Schritt wird ein eventuell laufender Timer abgebrochen. Dies ist eigentlich unnötig, aber immer sinnvoll, einfach, um eine sicher definierte Ausgangslage zu haben.
Jetzt wird noch, falls nNewState ungleich 1 ist, ein Timer erzeugt, der zehn Minuten später abläuft.
Nachdem der Timer erzeugt wurde ist die Rule am Ende angelangt und beendet.

Nach zehn Minuten wird der Scheduler den Code zur Ausführung bringen, wobei der einzige Befehl das Ausschalten des Druckers ist. Du könntest im Mapping noch ein OFF vorsehen und der Timer könnte dann zusätzlich die Anzeige noch auf OFF wechseln.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Eleven
Beiträge: 53
Registriert: 15. Okt 2018 10:27

Re: 3D-Drucker nach dem Druck stromlos schalten

Beitrag von Eleven »

Hallo Udo1toni,

erst einmal vielen vielen Dank für Deine Hilfe und die sehr ausführliche Erklärung. Ich habe die rule von Dir gerade mal getestet, funktioniert wunderbar! Deine Anmerkung bzgl. des OFF-Mappings klingt sehr gut. Setze ich ich hierfür in der rule einfach nur einen nNewState Befehl nach dem Timer oder wie implementiert man das?

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

Re: 3D-Drucker nach dem Druck stromlos schalten

Beitrag von udo1toni »

Na, Du brauchst natürlich noch einen einen zusätzlichen Eintrag in der map-Datei, damit das auch entsprechende angezeigt wird.
Und im Timer fügst Du noch ein Drucker_Status.postUpdate(<zahl>) unter der Zeile ZS_AZ2_Switch.sendCommand(OFF) ein, wobei <zahl> halt der Wert für OFF ist.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Eleven
Beiträge: 53
Registriert: 15. Okt 2018 10:27

Re: 3D-Drucker nach dem Druck stromlos schalten

Beitrag von Eleven »

Hallo zusammen,

hier ein kurzes Fazit nach ein paar Tagen an denen ich die rule ausgiebig testen konnte.
Es funktioniert einwandfrei und wie gewünscht! Ich habe zu der Konfiguration von Udo1toni noch das "Off"-mapping mit einbezogen. Zusätzlich habe ich noch einen Wartungsschalter hinzugefügt, da es ja doch ab zu mal vorkommt das man am Drucker mechanische Veränderungen vornimmt (z.B. Düsentausch). Dort sollte der Drucker dann natürlich nicht selbstständig ausgehen! Sofern der Schalter an ist läuft kein timer und es geht auch der Drucker nach 10 Minuten nicht aus.

Die Konfiguration hierzu möchte ich euch nicht vorenthalten.

drucker.items

Code: Alles auswählen

Switch  ZS_AZ2_Switch               "3D-Drucker"                            <poweroutlet>                                                       {channel="zwave:device:xxxxxxxxxx:node29:switch_binary"}
Number  ZS_AZ2_Verbrauch_akt        "3D-Drucker [%.0f W]"                   <verbrauch>                                                         {channel="zwave:device:xxxxxxxxxx:node29:meter_watts"}
Number  Drucker_Status              "3D-Drucker [MAP(drucker.map):%s]"
Switch  Dummy_Drucker               "3D-Drucker Wartung"

drucker.rules

Code: Alles auswählen

rule "Drucker nach dem Druck ausschalten"                                    // schalte Durcker nach erfolgreichem Druck aus.
when
    Item ZS_AZ2_Verbrauch_akt changed
then
    if(Dummy_Drucker.state == ON) return                                     
    else if(Dummy_Drucker.state == OFF) {
        val Number nPower = if(ZS_AZ2_Verbrauch_akt.state instanceof Number) // falls Status eine gültige Zahl enthält
                                ZS_AZ2_Verbrauch_akt.state as Number         // nimm die Zahl
                            else                                             // ansonsten
                                0                                            // 0
        var Number nNewState = 0                                             // Default ist 0 -> Standby
        if(nPower > 11)                                                      // falls über 11
            nNewState = 1                                                    // setze auf 1 -> Druck

        if(Drucker_Status.state.toString != nNewState.toString) {            // Item nur bei Änderung setzen
            Drucker_Status.postUpdate(nNewState)                             // setze Item
            tDrucker?.cancel                                                 // lösche Timer, falls vorhanden
            if(nNewState != 1)                                               // nur falls Standby
                tDrucker = createTimer(now.plusMinutes(10), [|               // starte Timer
                    ZS_AZ2_Switch.sendCommand(OFF)
                    Drucker_Status.postUpdate(2)
                ])
        }
    }
end 
drucker.map

Code: Alles auswählen

0=Standby
1=Druck läuft
2=Off
-=Error
NULL=unbekannt 
Auf diesem Weg möchte ich mich auch nochmal bei Udo1toni für den Support bedanken! Ohne Deine Hilfe wäre ich jetzt noch nicht annähernd fertig und hätte mein Vorhaben wohl aufgegeben!

Grüße Eleven

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

Re: 3D-Drucker nach dem Druck stromlos schalten

Beitrag von udo1toni »

Immer gerne!
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Antworten