FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: Oliver Vallant am 19 Februar 2017, 14:33:08

Titel: Abbildung eines Stromstoßrelais
Beitrag von: Oliver Vallant am 19 Februar 2017, 14:33:08
Hallo liebe Freunde der Hausautomatisierung,

für lange eingeschaltete und Lasten bei 2kW bietet sich ein 16A Stromstoßrelais an, sowie weil man dieses auch zur Not manuell im Verteilerschank schalten kann. Den Nachteil, dass das Relais mit einem Impuls ein- sowie ausgeschalten wird und FHEM damit den Zustand wechseln kann, aber den aktuellen Schaltzustand nicht kennt, habe ich durch ein zweikanaliges Finder Stromstroßrelais gelöst, sodass am ersten Kanal über einen Input der Zustand abgefragt wird und am zweiten Kanal die eigentliche Last geschalten wird.
Gesteuern/Ausgelesen wird über 1-wire und zweier DS2408. Dh. mit dem ersten DS2408 (Sensor) frage ich den Zustand des Relais mit sensed.0 ab und am zweiten DS2408 (Relais) sende ich einen Schaltimpuls auf PIO.0 zum Wechsel von on auf off und umgekehrt.

Und jetzt stehe ich an. Mit welchen Elemente (zB. readingsProxy, dummy) kann man jetzt die beiden Einzelkanäle elegant zu einem schaltbaren Element zusammenfassen.
Folgendes habe ich mittels eines readingsProxy versucht:
DEF Sensor:sensed.0
attr setFn {
my $cur = ReadingsVal("Sensor","sensed.0",0);
if ((($CMD eq "on") && ($cur == 1)) || (($CMD eq "off") && ($cur == 0))) {
  fhem("set Relais PIO.0 11");
  sleep 1 ;
  fhem("set Relais PIO.0 10"); }
}

..funktioniert aber leider nicht.
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 19 Februar 2017, 15:55:26
Zitat von: vallant am 19 Februar 2017, 14:33:08

..funktioniert aber leider nicht.

Kannst Du uns erhellen, was nicht funktioniert?


Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Oliver Vallant am 19 Februar 2017, 16:12:36
Ich bekomme die Fehlermeldung:

"Unknown argument on, choose one of interval LCD_H/clear LCD_H/home LCD_H/message LCD_H/onoff LCD_H/screen LCD_H/screenyc LCD_M/clear LCD_M/home LCD_M/message LCD_M/onoff LCD_M/screen LCD_M/screenyc PIO.0 PIO.1 PIO.2 PIO.3 PIO.4 PIO.5 PIO.6 PIO.7 PIO.ALL PIO.BYTE latch.0 latch.1 latch.2 latch.3 latch.4 latch.5 latch.6 latch.7 latch.ALL latch.BYTE por set_alarm strobe"

Danke viegener für deine Unterstützung!

Es scheint das grundsätzliche Problem zu sein, dass der Steuerkanal eben nicht on oder off ist, sondern ständig off, bis auf die eine Sekunde on des Zustandswechsels. Gibt es ein verwendbares Element/Modul welches diese T-Flipflop-Charakteristik abbildet?  Im Ergebnis wäre ein Element, welches on:off verstehen würde optimal.
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 19 Februar 2017, 16:38:44
Annahme 1 - ich nehme an setList hast Du gesetzt? - Korrekt?

Generell müsste ja das Ergebnis Deiner setFn ein Ausdruck sein, der an das target device (also Sensor) weitergeleitet wird. Das passiert in Deiner setFn schonmal nicht. Dann wird wahrscheinlich der Originalwert weitergeleitet (Vermutung !).

Annahme 2: Du hast zwei 1-Wire devices einer heisst Sensor (gibt den Schlatzustand wieder) und einer heisst Rellais (mit dem wird das Relais geschaltet) - so entnehme ich das den verschiedenen Codes hier. - Korrekt ?

Weitere Annahme (3) - Du hast die Befehle set Relais PIO.0 11 etc ausprobiert und sie schalten das Relais? - Korrekt?

Anmerkung - Deinn Sleep hält das gesamte FHEm an (der ist blocking) und damit ein grundsätzliches Probelm

Problem 2 - Du musst in der setFn ja einen Befehl an Dein One-wire-Sensor-Device weitergeben, der braucht aber eigentlich gar keinen set-Befehl?

Was passiert denn wenn Du folgendes machst:

attr setFn {
my $cur = ReadingsVal("Sensor","sensed.0",0);
if ((($CMD eq "on") && ($cur == 1)) || (($CMD eq "off") && ($cur == 0))) {
  fhem("set Relais PIO.0 11; sleep 1; set Relais PIO.0 10");
}
}
return "interval 10"


Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Oliver Vallant am 19 Februar 2017, 17:09:13
ad A1: setList = "on off"
ad A2/3: ja genau so
ad Anmerkung) Gibt es da eine Alternative? Ist die Funktion "on-for-time 1" blocking
ad P2) Würde der notwendige set-Befehl mit einem (Device-unabhängigen) Dummy-Element entfallen? Kann man sonst irgendwie geräteunabhängig ein on,sleep,off absetzen?
ad Code) Liefert leider die idente Meldung:
"Unknown argument on, choose one of interval LCD_H/clear LCD_H/home LCD_H/message LCD_H/onoff LCD_H/screen LCD_H/screenyc LCD_M/clear LCD_M/home LCD_M/message LCD_M/onoff LCD_M/screen LCD_M/screenyc PIO.0 PIO.1 PIO.2 PIO.3 PIO.4 PIO.5 PIO.6 PIO.7 PIO.ALL PIO.BYTE latch.0 latch.1 latch.2 latch.3 latch.4 latch.5 latch.6 latch.7 latch.ALL latch.BYTE por set_alarm strobe"
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Thorsten Pferdekaemper am 19 Februar 2017, 17:28:48
Hi,
mir ist das hier alles etwas kompliziert. Kann man denn nicht einfach das Device "Relais" zum Schalten nehmen und an das Device "Sensor" ein notify hängen, dass mit setreading ein neues Reading ins Device "Relais" setzt, das den tatsächlichen Schaltzustand anzeigt?
Also in etwa so:

define blabla notify Sensor:sensed.* setreading Relais schaltzustand $EVENT

Gruß,
  Thorsten
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 19 Februar 2017, 18:04:24
Zitat von: vallant am 19 Februar 2017, 17:09:13
ad A1: setList = "on off"
ad A2/3: ja genau so
ad Anmerkung) Gibt es da eine Alternative? Ist die Funktion "on-for-time 1" blocking
ad P2) Würde der notwendige set-Befehl mit einem (Device-unabhängigen) Dummy-Element entfallen? Kann man sonst irgendwie geräteunabhängig ein on,sleep,off absetzen?
ad Code) Liefert leider die idente Meldung:
"Unknown argument on, choose one of interval LCD_H/clear LCD_H/home LCD_H/message LCD_H/onoff LCD_H/screen LCD_H/screenyc LCD_M/clear LCD_M/home LCD_M/message LCD_M/onoff LCD_M/screen LCD_M/screenyc PIO.0 PIO.1 PIO.2 PIO.3 PIO.4 PIO.5 PIO.6 PIO.7 PIO.ALL PIO.BYTE latch.0 latch.1 latch.2 latch.3 latch.4 latch.5 latch.6 latch.7 latch.ALL latch.BYTE por set_alarm strobe"

Irgendwas ist mit Deinen settings so nicht in Ordnung. Generell sollte der Ansatz so ja funktionieren, denn Dein Readingsproxy sollte ja korrekt den Schaltzustand wiedergeben und die Befehle sollten nur an das Relais durchgereicht werden.

kannst Du mal einen "list" von Deinem Readingsproxy machen und das Ergebnis in code tags hier posten.

Ausserdem wäre es vielleicht mal interessant zu schauen, ob da noch was anderes im log auftaucht, wenn die am Readingsproxy und an den anderen beiden Devices mal verbose auf 5 setzt.

Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 19 Februar 2017, 18:06:57
Zitat von: Thorsten Pferdekaemper am 19 Februar 2017, 17:28:48
Hi,
mir ist das hier alles etwas kompliziert. Kann man denn nicht einfach das Device "Relais" zum Schalten nehmen und an das Device "Sensor" ein notify hängen, dass mit setreading ein neues Reading ins Device "Relais" setzt, das den tatsächlichen Schaltzustand anzeigt?
Also in etwa so:

define blabla notify Sensor:sensed.* setreading Relais schaltzustand $EVENT

Gruß,
  Thorsten

Das Problem ist ja nicht den Schaltzustand zu erkennen das erfolgt ja im Sensor, sondern dass Einschalten des Stroms heisst das Relais erst auf on und dann sofort wieder auf off zu setzen (also sozusagen einen Taster zu simulieren). Das ginge auch mit einem Befehl "on-for-timer" aber das eigentliche Problem ist ja, dass hier die setFn nicht richtig läuft..
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Thorsten Pferdekaemper am 19 Februar 2017, 20:19:03
Ach so...
Ja dann dürfte das ursprüngliche Problem daran liegen, dass die setFn einen Rückgabewert haben muss, der ein erlaubtes "set"-Kommando ergibt.
Müsste es dann nicht in etwa so gehen (unter der Annahme, dass das readingsProxy zum Relais gehört):

attr setFn {
my $cur = ReadingsVal("Sensor","sensed.0",0);
if ((($CMD eq "on") && ($cur == 1)) || (($CMD eq "off") && ($cur == 0))) {
  fhem("set Relais PIO.0 11; sleep 1");
}
}
return "PIO.0 10";

...oder aber ein notify auf Relais.PIO.0 (wenn das geht), das ein at erzeugt, dass das Ding nach 1 Sekunde oder so wieder abschaltet.

Gruß,
   Thorsten
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 19 Februar 2017, 21:20:46
@Thorsten: Ja so ähnlich, deshalb hatte ich den zweiten Ansatz gepostet, der am Ende:
return "interval 10" sendet.

Allerdings kommt danach immer noch "Unknown argument on... das passt nicht, denn es wird ja eigentlich kein "on" mehr weitergeleitet, deshalb hatte ich vermutet, dass etwas anderes gerade nicht passt
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Oliver Vallant am 19 Februar 2017, 22:18:53
Hallo viegener,

Klammerfehler, das "return()" war bereits außerhalb des "}"-Blocks, ich bekomme jetzt: "new interval is equal to old interval.", dh das Kommando wird an das Device darunter durchgereicht. Habe jetzt eines gefunden - hoffentlich ohne Auswirkungen: por (power on reset) ist true bei Neustart und meldet sich dann bei einem full-bus-scan und sollte dann auf false gehen und bleiben. Weist du noch eine Lösung für das blocking beim sleep? Habe einfach den Impuls mal auf ein min reduziert auf 300ms, ist aber keine Lösung des Problems.

Gesamtlösung funktioniert jetzt wie folgt:

Erster DS2408 "Relais" für 12V Relais-Output:

Internals:
   DEF        29.D61909000000 1
   IODev      iBUS
   NAME       Relais
   STATE      sensed.0: 1  sensed.1: 1  sensed.2: 1  sensed.3: 1  sensed.4: 1  sensed.5: 1  sensed.6: 1  sensed.7: 1  alarm: 0
   TYPE       OWDevice
   Fhem:
     address    29.D61909000000
     alerting   1
     bus        bus.0
     interfaces state
     interval   1
Attributes:
   IODev      iBUS
   group      Relais
   model      DS2408
   polls      sensed.0,sensed.1,sensed.2,sensed.3,sensed.4,sensed.5,sensed.6,sensed.7


Zweiter DS2408 "Sensor" für Rückkanal am Stromstoßrelais:

Internals:
   DEF        29.B73009000000 1
   IODev      iBUS
   NAME       Sensor
   STATE      sensed.0: 1  sensed.1: 0  sensed.2: n/a  sensed.3: n/a  sensed.4: n/a  sensed.5: n/a  sensed.6: n/a  sensed.7: n/a  alarm: 0
   TYPE       OWDevice
   Fhem:
     address    29.B73009000000
     alerting   1
     bus        bus.0
     interfaces state
     interval   1
Attributes:
   IODev      iBUS
   group      Relais
   model      DS2408
   polls      latch.4,sensed.0,sensed.1


Device für das Stromstoßrelais am PIO.0:

Internals:
   DEF        Sensor:sensed.0
   DEVICE     Sensor
   NAME       Licht0
   READING    sensed.0
   STATE      on
   TYPE       readingsProxy
   Content:
     Sensor     1
Attributes:
   setFn      {
       my $cur = ReadingsVal("Sensor","sensed.0",0);
       if ((($CMD eq "on") && ($cur == 0)) || (($CMD eq "off") && ($cur == 1)) || ($CMD eq "toggle") ) {
           fhem("set Relais PIO.0 11");
           sleep 0.3 ;
           fhem("set Relais PIO.0 10");
      }
      return "por 0"
}
   setList    on off toggle
   valueFn    {($VALUE == 1)?"on":"off"}
   webCmd     on:off:toggle


Damit ist das SSRelais mit on, off und toggle bedienbar.
Will man es mit einem Taster an der Wand (ebenfalls am Sensor Kanal 4) toggeln fügt man folgendes hinzu:

Device für den Taster "White" am Kanal 4 des Sensor:
Das Gerät muss latch.4 abfragen und nicht sensed.4, da der Taster nur wenige ms am DS2408 durch das Drücken des Tasters das sensed.4 auf high gibt. Hierfür hat DalSemi das Alarming für die einzelnen Kanäle einführt und durch kurzes high-tasten geht latch.4 high und bleibt bis zum bewussten low-setzen (set senWhite reset) dort, dh. wenn das Stromstoßrelais fertig geschalten hat.


Internals:
   DEF        Sensor:latch.4
   DEVICE     Sensor
   NAME       senWhite
   NR         42
   NTFY_ORDER 50-senWhite
   READING    latch.4
   STATE      off
   TYPE       readingsProxy
Attributes:
   group      Sensors
   room       Büro
   setFn      { if ($CMD eq "reset") { "latch.4 10" } }
   setList    reset
   valueFn    {($VALUE == 0)?"off":"on"}
   webCmd     reset


Notify verbindet senWhite mit Licht0:
Wird der Taster gedrückt geht Sensor:latch.0 auf 1, löst das Notify aus, dieses toggelt das SSRelais und resetet das Sensor:latch.4 auf 0. Auch wenn viele Taster im Haus gleichzeitig gedrückt werden, wird damit kein Event "vergessen".

Internals:
   CFGFN
   DEF        senWhite.on set Licht0 toggle ; set senWhite reset
   NAME       onWhite
   REGEXP     senWhite.on
   TYPE       notify
Attributes:
   group      Sensors


Bleibt nur zu hoffen, dass meine 80 Stk. DS2408 (für Taster) im Haus vom darunter liegenden OWFS in unter 1sek ausgelesen werden können. Länger warten auf das Licht bei betreten eines Raumes wäre mau.

Danke nochmals viegener!
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Oliver Vallant am 19 Februar 2017, 22:33:18
@Thorsten:
readingProxy Licht0 hängt auf Sensor um den Status des Rückkanals abfragen zu können. Aber das return("PIO.0 10") ist die saubere Lösung statt por, da am Sensor der Steuerausgang bei Beschaltung als Eingang naturgemäß ohnedies 0 sein muss. Das mit "at" schaue ich mir genauer an, ob es etwas 300ms schalten kann. Das SSRelais nimmt etwa 90mA vom Bus wenn der Magnet anzieht, die Zeit ist demnach bei vielen Geräten schon relevant - ist aber die Lösung für das Blocking des sleep().
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Thorsten Pferdekaemper am 19 Februar 2017, 22:48:54
Hi,
das at kann wahrscheinlich nur minimal 1 Sekunde. Es gibt aber noch die Funktion InternalTimer, die Du vielleicht verwenden kannst. Die kann auch Millisekunden.
Gruß,
   Thorsten
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 19 Februar 2017, 23:05:05
@vallant: Die Lösung beim sleep ist eigentlich ganz einfach, wie oben bereits im ersten Vorschlag:

Zitatfhem("set Relais PIO.0 11; sleep 1; set Relais PIO.0 10");

Wenn der sleep in einer FHEM-Befehlssequenz auftaucht, wird er das System nicht blockieren.
Dann ist es ein FHEM-Sleep und kein perl-sleep -> das findest Du auch in der commandref



Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Thorsten Pferdekaemper am 20 Februar 2017, 07:39:09
...außerdem geht mit sleep auch 300ms:
Zitat
The unit is seconds, with millisecond accuracy, as you can specify decimal places.
Ich glaube, dass am Ende "return undef" das richtige wäre. Die setFn handelt ja schon alles ab und laut Commandref scheint mir das zu sagen "tue (ansonsten) nichts".
Gruß,
   Thorsten
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 20 Februar 2017, 09:14:44
Zitat von: Thorsten Pferdekaemper am 20 Februar 2017, 07:39:09
...außerdem geht mit sleep auch 300ms:Ich glaube, dass am Ende "return undef" das richtige wäre. Die setFn handelt ja schon alles ab und laut Commandref scheint mir das zu sagen "tue (ansonsten) nichts".
Gruß,
   Thorsten

Ja das ist auch im Modulcode so implementiert, mich hatte nur verwundert, dass es ohne return nicht funktioniert. Ich hätte angenommen, dass das einem "return undef" entspricht.

Also soillte die setfn eigentlich so aussehen


setFn      {
       my $cur = ReadingsVal("Sensor","sensed.0",0);
       if ((($CMD eq "on") && ($cur == 0)) || (($CMD eq "off") && ($cur == 1)) || ($CMD eq "toggle") ) {
           fhem("set Relais PIO.0 11; sleep 1; set Relais PIO.0 10");
      }
      return undef;
}

Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Thorsten Pferdekaemper am 20 Februar 2017, 09:35:16
Hi,
aus http://perldoc.perl.org/functions/return.html:
Zitat
(In the absence of an explicit return, a subroutine, eval, or do FILE  automatically returns the value of the last expression evaluated.)
Gruß,
   Thorsten
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 20 Februar 2017, 09:36:07
Zitat von: Thorsten Pferdekaemper am 20 Februar 2017, 09:35:16
Hi,
aus http://perldoc.perl.org/functions/return.html:Gruß,
   Thorsten

Danke! Ich sags ja ich werde nie ein perl-Experte  :D
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Oliver Vallant am 20 Februar 2017, 14:10:09
Hallo viegener und Thorsten,

mit "return undef" funktioniert's perfekt. Ich werde den eigentlichen Umschaltimpuls noch in eine Schleife packen, falls die Stromstoßrelais beim ersten Impuls nicht umsetzen (kann sein, wenn länger nicht benutzt kleben diese leicht fest).
Gibt es eine Möglichkeit in fhem den Code in eine Funktion zu abstrahieren, sodass bei einem weiteren Gerät nur mehr der Sensor-Kanal und Relais-Kanal angegeben werden muss, sowie bei Änderungen am Code, diese für alle Geräte durchschlagen?

Vielen vielen Dank für eure Hilfe!!
LG Oliver
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: viegener am 20 Februar 2017, 15:02:50
Zitat von: Oliver Vallant am 20 Februar 2017, 14:10:09
Hallo viegener und Thorsten,

mit "return undef" funktioniert's perfekt. Ich werde den eigentlichen Umschaltimpuls noch in eine Schleife packen, falls die Stromstoßrelais beim ersten Impuls nicht umsetzen (kann sein, wenn länger nicht benutzt kleben diese leicht fest).
Gibt es eine Möglichkeit in fhem den Code in eine Funktion zu abstrahieren, sodass bei einem weiteren Gerät nur mehr der Sensor-Kanal und Relais-Kanal angegeben werden muss, sowie bei Änderungen am Code, diese für alle Geräte durchschlagen?

Vielen vielen Dank für eure Hilfe!!
LG Oliver


Schön das es geht.
Um den Code wiederverwendbar zu machen setze ich meist Subroutinen in 99_myUtils.pm ein (https://wiki.fhem.de/wiki/99_myUtils_anlegen (https://wiki.fhem.de/wiki/99_myUtils_anlegen)) und dann kannst Du eine sub definieren, die als Parameter den Wert von $CMD, etc annimmt.
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Thorsten Pferdekaemper am 20 Februar 2017, 15:05:47
Zitat von: Oliver Vallant am 20 Februar 2017, 14:10:09Ich werde den eigentlichen Umschaltimpuls noch in eine Schleife packen, falls die Stromstoßrelais beim ersten Impuls nicht umsetzen
Das ist aber u.U. gar nicht so einfach. Das Konstrukt fhem("tuwas;sleep 1;tuwasanderes") kommt ja zurück, bevor es ganz abgearbeitet ist. Da wirst Du Dir was einfallen lassen müssen.

Zitat
Gibt es eine Möglichkeit in fhem den Code in eine Funktion zu abstrahieren, sodass bei einem weiteren Gerät nur mehr der Sensor-Kanal und Relais-Kanal angegeben werden muss, sowie bei Änderungen am Code, diese für alle Geräte durchschlagen?
Klar, Unterprogramm (Funktion) schreiben und in die 99_myUtils.pm packen.

Gruß,
   Thorsten
Titel: Antw:Abbildung eines Stromstoßrelais
Beitrag von: Oliver Vallant am 20 Februar 2017, 20:27:24
Falls jemand die Funktionen benötigt:

Für normale Spulen/Thyrister/MosFET-Relais:

DEF=<Relais DS2408>:sensed.<Channel 0..7>
TYPE=readingsProxy
setFn={switchRelais($CMD, $READING)}


Funktion in der 99:myUtils.pm

sub switchRelais($$) {
   my ($cmd, $relCh) = @_;
   $relCh = (split(/\./, $relCh))[1];
   $cmd = ($cmd eq "on")?owON:owOFF;
   return ("PIO." . $relCh . " " . $cmd);
}


Für 2-Kanal-Stromstoß-Relais (1xRückmeldung,1xLast):
Zusätzliches globales userattr angelegt: "relaisDevCh"

DEF=<Sensor DS2408>:sensed.<Channel 0..7>
TYPE=readingsProxy
setFn={switchSSRelais($CMD, $DEVICE, $READING, AttrVal($name,"relaisDevCh",undef) )}
relaisDevCh=<Relais DS2408> PIO.<Channel 0..7>


Funktion in der 99:myUtils.pm

sub switchSSRelais($$$$) {
   my ($CMD, $senDev, $senCh, $relDevCh) = @_;
   my $cur = ReadingsVal($senDev,$senCh,0);
   if ((($CMD eq "on") && ($cur == 1)) || (($CMD eq "off") && ($cur == 0)) || ($CMD eq "toggle") ) {
    fhem("set " . $relDevCh . " " . owON . "; sleep 0.2; set " . $relDevCh . " " . owOFF); }
return undef
}


Taster am Sensor:


DEF=<Sensor DS2408>:latch.<channel 0..7>
TYPE=readingsProxy
setFn={ if ($CMD eq "reset") { "$READING 10" } }
setList=reset



Das Notify für den Taster, sowie rücksetzen des Alarming:

DEF=<TasterDevice>.on set <Relais oder SSRelais> toggle ; set <TasterDevice> reset
TYPE=notify


@Thorsten: Dein Bedenken ist korrekt. Das wird dann wohl ohne "at" nicht funktionieren.