Homematic Wired - Homebrew Devices

Begonnen von Thorsten Pferdekaemper, 27 April 2014, 00:13:17

Vorheriges Thema - Nächstes Thema

Thorsten Pferdekaemper

Zitat von: Shortie am 18 März 2018, 16:19:45
Genial wäre jetzt noch eine universelle Hardware Basis, so in der Art wie es für die Funk-Variante hier im Forum entwickelt wurde.
Hier gibt es etwas in der Richtung:
https://forum.fhem.de/index.php/topic,84827.msg771453.html#msg771453
Vielleicht kannst Du Dich da mit reinhängen.
Ich selbst bin eher in der Software zuhause und bisher hat es für mich gereicht, einen Nano mit einem MAX487 zusammenzustöpseln.

ZitatIch denke da an eine kleine Platine in SMD ähnlich wie ein Arduino Nano, aber mit Schaltregler und max485 onboard. Alles rausgeführt auf Pinleisten damit man variabel bleibt und so, das es in eine UP Dose passt.
Max485 ist nicht so doll, da man damit glaube ich maximal 32 Geräte am Bus haben kann. Max487 (oder ähnlich) ist besser.
Gruß,
   Thorsten
FUIP

loetmeister

#436
Hi,

Zum Entwickeln, reicht z.B. einen Arduino + Spannungsversorgung + RS485 Baustein (Bspw. MAX487CSA), oder auch was hier als Universalsensor beschrieben ist: https://wiki.fhem.de/wiki/Universalsensor#RS485-Version_mit_1-Wire_Temperatursensoren

ZitatIch denke da an eine kleine Platine in SMD ähnlich wie ein Arduino Nano, aber mit Schaltregler und max485 onboard. Alles rausgeführt auf Pinleisten damit man variabel bleibt und so, das es in eine UP Dose passt.
Verm. wird das relativ eng, in einer tiefen UP Dose könnte man zwei Platinen stapeln. Ich würde aber etwas für den passenden Anwendungsfall bauen und die ganzen Steckkontakte weglassen, wo nicht absolut nötig.

Ich habe Platinen für 6 TE Hutschienengehäuse erstellt, da hat die Kontrollerplatine die gleiche Basis, die Relaisplatinen variiert dann (Schaltaktor, Rolladenaktor). Ich müsste noch eine Variante für 4 TE Gehäuse erstellen... 6TE ist für manches etwas groß...

Gruß,
Thomas

loetmeister

#437
Hallo,

ich versuche grade den Homematic Homebrew Switch mit einem erweiterten direkten peering zu ergänzen, bei denen man die Ein- und Ausschaltverzögerung einstellen kann. (siehe Screenshot)

Da ich aktuell kein "echtes" Homematic Gerät zum testen habe: Frage an Homematic Benutzer und die Besitzer von HMW-LC-Sw2-DR, o.ä., sind meine Annahmen richtig;D

Ich habe mal am Beispiel eines kurzen Tastendrucks (short_*) die Funktionen aufgeführt. Bis auf "long_multiexecute" ist das peering für short und long gleich. Wenn jemand long_multiexecute erklären kann wär das auch hilfreich :)
--> long_multiexecute: Wiederholte lange Tastendrücke beachten. ja/nein. Bei nein wird nur der erste lange Tastendruck ausgewertet.

  • short_on_time_mode   
  • short_off_time_mode   
--> On/Off Zeiten können durch ein neuen Befehl verlängert werden (MINIMAL): Die neue Zeit muss länger als die aktuell verbleibende Restzeit sein! "ABSOLUTE" setzt den timer immer neu, egal welcher timer vorher lief.
(Gilt wohl nur für 'on_time'/'off_time' - nicht für 'ondelay_time'/'offdelay_time')
  • short_toggle_use   
--> Auswahl: DONT_USE, DIRECT oder INVERTED.
DONT_USE ist klar. DIRECT toggelt den Ausgang, aber INVERTED ist mir nicht ganz klar... toggle kann ich irgendwie schlecht invertieren...
Es gibt bei anderen Geräten TOGGLE_TO_COUNTER / TOGGLE_INVERSE_TO_COUNTER, eventuell ist das die selbe Funktion.
  • short_action_type   
--> Active oder Inactive: Gilt für alle short_* Einstellungen dieses peering. Auch short_toggle_use?

Dem besseren Verständnis würde ich folgende Implementierung bevorzugen (ist beim original Dimmer so ähnlich der Fall, wohl nicht für Schaltaktoren) - ersetzt auch "short_toggle_use"
short_ACTION_TYPE
- INACTIVE
- JUMP_TO_TARGET --> zur Sprungliste short_jt_* wechseln
- TOGGLE_TO_COUNTER
- TOGGLE_INVERS_TO_COUNTER
- TOGGLE

  • short_ondelay_time   
--> Zeit, bevor der Sprungpunkt 'jt_ondelay' angesprungen wird, z.B. der Ausgang nach EIN geschaltet wird.
  • short_on_time   
--> Zeit die der Ausgang auf EIN bleibt. Danach wechsel über short_jt_on?
  • short_offdelay_time   
--> Zeit, bevor der Sprungpunkt 'jt_offdelay' angesprungen wird, z.B. der Ausgang nach AUS geschaltet wird.
  • short_off_time   
--> Zeit die der Ausgang auf AUS bleibt. Danach wechsel über short_jt_off?
  • short_jt_ondelay   
  • short_jt_on   
  • short_jt_offdelay   
  • short_jt_off
--> Sprungziele (Jump Target):
Die Auswahl gilt ausgehend vom aktuellen Status, wenn z.B. der Ausgang AUS ist, gilt die Auswahl von 'short_jt_off'.


Erste Version: https://github.com/loetmeister/HBWired/tree/430a7e13e325a17fd9dc1fdbd37d2ec8132833c5/HBW-LC-Sw-12
(Grundsätzlich funktionieren der Standard Wechsel off->ondelay->on->offdelay->off... Zeit ist aktuell 0-255 Sekunden, nicht Minuten :) )


PS: Neue Erkenntnisse eingearbeitet..

-->Details im ELVjournal: https://forum.fhem.de/index.php?action=dlattach;topic=22952.0;attach=99026

Gruß,
Thomas

Ralf9

Zitatich versuche grade den Homematic Homebrew Switch mit einem erweiterten direkten peering zu ergänzen, bei denen man die Ein- und Ausschaltverzögerung einstellen kann.

Da hast Du Dir aber einiges vorgenommen.
Daß Du kein "echtes" Homematic Gerät zum testen hast, macht es noch schwieriger.

Das  direkte peering und die Statemaschine sind recht komplex. Du wirst wahrscheinlich noch auf einige details stossen die das ganze recht aufwendig machen.
Daß Teile der sendFrame Routine momentan noch blocking sind, kann evtl die Zeiten der Statemaschine beeinflussen.
Hast Du Dir schon gedanken gemacht wie Du das mit den broadcast Meldungen machen willst?
Es gibt außer on/off auch noch das stateflag working.
Wenn Z.B. bei 2 switche gleichzeitig der ontime timer abläuft und gleichzeitig 2 event gesendet werden, oder wenn bei einem event gerade der Bus nicht frei ist.
Eine Möglichkeit wäre eine Sendewarteschlange einzubauen.


Mit den events habe ich es bei mir so gemacht:

// state aenderungen beim peering
void HMWModule::broadcastPeeringEvent(byte channel, byte timeState) {
   hmwrs485->txFrameDataLength = 0x04;       // Length
   hmwrs485->txFrameData[0] = 0x69;          // 'i'
   hmwrs485->txFrameData[1] = channel;       // Sensornummer
   if (timeState < 2) {
      hmwrs485->txFrameData[2] = 0x00;       // off
   } else {
      hmwrs485->txFrameData[2] = 0xC8;       // on
   }
   if (timeState == 0 || timeState == 12) { 
      hmwrs485->txFrameData[3] = 0x00;       // stateflag, working off
   } else {
      hmwrs485->txFrameData[3] = 0x40;       // stateflag, working on
   }
   ...


Dabei ist time_state: 0 = off, 1 = ondelay, 2 = ontime, 12 = dauer on


Da es mir zu heftig war das komplette direkte peering einzubauen habe ich bei mir nur ein vereinfachtes direktes peering realisiert.
Ich verwende noch die alte Libary die ich modifiziert habe und habe folgendes eingebaut:

ondelay_time
on_time
short_action_type
long_action_type
shortOnJmpTo
longOnJmpTo
shortOffJmpTo   
longOffJmpTo


Das Problem mit der fehlenden Sendewarteschlange habe ich bei mir auch noch nicht gelöst.

Gruß Ralf
FHEM auf Cubietruck mit Igor-Image, SSD und  hmland + HM-CFG-USB-2,  HMUARTLGW Lan,   HM-LC-Bl1PBU-FM, HM-CC-RT-DN, HM-SEC-SC-2, HM-MOD-Re-8, HM-MOD-Em-8
HM-Wired:  HMW_IO_12_FM, HMW_Sen_SC_12_DR, Selbstbau IO-Module HBW_IO_SW
Maple-SIGNALduino, WH3080,  Hideki, Id 7

loetmeister

Zitat von: Ralf9 am 25 März 2018, 13:15:50
Da hast Du Dir aber einiges vorgenommen.
Manchmal ist es gut, nicht zu wissen auf was man sich einlässt...  ::)
Ich würde auch erstmal eine vereinfachte Version bauen.  ;)
Schon mal vorab danke für die Details.

Zitat
Hast Du Dir schon gedanken gemacht wie Du das mit den broadcast Meldungen machen willst?
Es gibt außer on/off auch noch das stateflag working.
Wenn Z.B. bei 2 switche gleichzeitig der ontime timer abläuft und gleichzeitig 2 event gesendet werden, oder wenn bei einem event gerade der Bus nicht frei ist.
Eine Möglichkeit wäre eine Sendewarteschlange einzubauen.
Das "stateflag working" habe ich bisher erst mal ignoriert...
Die keyEvents werden ganz normal Bestätigt (ACK), dann schicke ich logging/notify events, mit "sendInfoMessage" - wenn logging für den channel aktiv ist. Dabei gibt einen einfachen retry Mechanismus, falls der Bus belegt war. Den Code habe ich einfach übernommen.

Die Behandlung der Timer (on/off, on-/offdelay) läuft im device loop(). Dort werden alle channels der reihe nach geprüft. Hoffe das alle logging/notify events rausgehen...
Ein nofity event wird auch gesendet, wenn z.B. der Ausgangspegel sich wegen eines abgelaufenen Timers geändert hat.


Eine Sende und Empfangs Warteschlange wäre natürlich noch eine super Sache... nicht nur für peering/info Nachrichten. Ich backe erst mal kleinere Brötchen.  ;)


Gruß,
Thomas

Ralf9

#440
ZitatHoffe das alle logging/notify events rausgehen...
Das wäre mir zu wenig, es sollte schon einigermaßen zuverlässig funktionieren.
Wenn ich mir sowas selber baue, dann sollen die events zuverlässiger ankommen als bei meinem HMW_IO_12_FM.
Wenn Du auch noch einbaust, daß mit einem Taster 2 Ausgänge getriggert werden können, dann kannst Du es damit testen.

ZitatDabei gibt einen einfachen retry Mechanismus, falls der Bus belegt war.
Dies bedeutet dann, daß Du während dem retry eine Blockierung hast. Inwieweit dies z.B. auf die Abfrage und Verarbeitung der Eingänge auswirkt, kann ich nicht abschätzen.

Es wäre schön, wenn die Sende- und Empfangsroutinen das retry selbstständig und blockierungfrei erledigen könnten.
Ich habe zwar eine Idee wie man das machen könnte, aber zum Testen habe ich auf meinem Bus zuwenig Module.

Ich habe mir dies ungefähr so vorgestellt:

Die sendframe Routine erledigt nur das Senden:
Nach dem Senden wird der Status auf waitForAck und die Wartezeit gesetzt.
Bei einem busbusy wird Status auf busbusy gesetzt.

In der  HBWDevice::loop() wird dann nach einem receive geprüft ob ein ack empfangen wurde.
Ein evtl retry bei fehlendem ack müsste dann auch hier erfolgen.
Und bei einem busbusy müsste dann nach einer Wartezeit das sendframe erneut aufgerufen werden.

Der nächste Schritt wäre dann der Einbau einer Sendewarteschlange.

Bei meinem selbstbau I/O verwende ich momentan einen Arduino Micro und einen MCP23017, damit sind dann 16 Eingänge und 8 Ausgänge möglich.

Gruß Ralf
FHEM auf Cubietruck mit Igor-Image, SSD und  hmland + HM-CFG-USB-2,  HMUARTLGW Lan,   HM-LC-Bl1PBU-FM, HM-CC-RT-DN, HM-SEC-SC-2, HM-MOD-Re-8, HM-MOD-Em-8
HM-Wired:  HMW_IO_12_FM, HMW_Sen_SC_12_DR, Selbstbau IO-Module HBW_IO_SW
Maple-SIGNALduino, WH3080,  Hideki, Id 7

Thorsten Pferdekaemper

Hi,
so ähnliche Gedanken habe ich mir auch schon gemacht, aber wegen ausbleibender Probleme bisher verworfen. Oder anders gesagt: Es gab erst einmal wichtigeres zu tun. Die "alte" Library war meiner Meinung nach nicht wirklich verwendbar, da wollte ich erst einmal umstrukturieren.
Das Thema "Sendewarteschlange" ist meiner Meinung nach auf einem Arduino etwas schwierig, da man begrenzten Speicherplatz zur Verfügung hat. Irgendwann muss man dann doch anfangen zu blockieren oder Nachrichten zu verwerfen. So ein richtig gutes Konzept dafür ist mir bisher noch nicht eingefallen.
Gruß,
    Thorsten
FUIP

loetmeister

Hi Ralf,

ich nutzte ja die aktuelle Arduino HBWired lib, ist da das Verhalten beim Senden nicht schon ähnlich deiner Beschreibung?

Zitat von: Ralf9 am 25 März 2018, 19:48:03
Wenn Du auch noch einbaust, daß mit einem Taster 2 Ausgänge getriggert werden können, dann kannst Du es damit testen.
Dies bedeutet dann, daß Du während dem retry eine Blockierung hast. Inwieweit dies z.B. auf die Abfrage und Verarbeitung der Eingänge auswirkt, kann ich nicht abschätzen.
Ich habe mal 4 Ausgänge mit einem Taster verknüpft, das scheint ohne Probleme zu funktionieren. Die Ausgänge werden sofort gesetzt, zwei Sekunden später (logging_time ist auf 2 Sek. gestellt) rauschen dann 4 notify events rein und bei FHEM gehen die Lampen an.

Wenn ich ein paar mehr Geräte haben, teste ich das Verhalten weiter...


Gruß,
Thomas

Thorsten Pferdekaemper

Zitat von: loetmeister am 25 März 2018, 23:53:26
ich nutzte ja die aktuelle Arduino HBWired lib, ist da das Verhalten beim Senden nicht schon ähnlich deiner Beschreibung?
(Das "deiner" bezieht dich auf Ralf9.)
Leider nicht wirklich. Er bezieht sich wahrscheinlich auf HBWDevice::sendFrame. Da kann es tatsächlich passieren, dass wenn die "Gegenstelle" nicht antwortet, das ganze etwa 600ms lang blockiert. Selbst wenn alles gut läuft, dann dauert es immerhin ein paar Millisekunden, bis das ganze gesendet ist und das ACK zurück kommt. Wenn man mehrere Peerings (zu anderen Devices, nicht nur intern) hat, dann kann sich das aufaddieren. Im Prinzip können dann weitere Tastendrücke verloren gehen oder sich auch zeitgesteuerte Sachen entsprechend verzögern.

Zitat
Ich habe mal 4 Ausgänge mit einem Taster verknüpft, das scheint ohne Probleme zu funktionieren. Die Ausgänge werden sofort gesetzt, zwei Sekunden später (logging_time ist auf 2 Sek. gestellt) rauschen dann 4 notify events rein und bei FHEM gehen die Lampen an.
Ich nehme mal an, dass das interne Peerings waren. Aber auch bei externen: Wenn alles gut läuft, dann dauert das ganze ja nur ein paar Millisekunden. Für einen Menschen ist das "sofort".

Gruß,
   Thorsten
FUIP

Ralf9

ZitatIch habe mal 4 Ausgänge mit einem Taster verknüpft, das scheint ohne Probleme zu funktionieren. Die Ausgänge werden sofort gesetzt, zwei Sekunden später (logging_time ist auf 2 Sek. gestellt) rauschen dann 4 notify events rein und bei FHEM gehen die Lampen an.

Wenn der Bus frei ist, was bei wenigen Modulen wahrscheinlich normalerweise fast immer der Fall sein wird, wird dies wahrscheinlich problemlos funktionieren.

Zitatdann schicke ich logging/notify events, mit "sendInfoMessage" - wenn logging für den channel aktiv ist. Dabei gibt einen einfachen retry Mechanismus, falls der Bus belegt war. Den Code habe ich einfach übernommen.

Mich würde interessieren wie Du das mit dem einfachen retry Mechanismus bei den logging/notify events realisiert hast.

Gruß Ralf
FHEM auf Cubietruck mit Igor-Image, SSD und  hmland + HM-CFG-USB-2,  HMUARTLGW Lan,   HM-LC-Bl1PBU-FM, HM-CC-RT-DN, HM-SEC-SC-2, HM-MOD-Re-8, HM-MOD-Em-8
HM-Wired:  HMW_IO_12_FM, HMW_Sen_SC_12_DR, Selbstbau IO-Module HBW_IO_SW
Maple-SIGNALduino, WH3080,  Hideki, Id 7

Thorsten Pferdekaemper

Zitat von: Ralf9 am 26 März 2018, 19:05:34Mich würde interessieren wie Du das mit dem einfachen retry Mechanismus bei den logging/notify events realisiert hast.
Hi,
bei "sendInfoMessage" wird überhaupt nur gesendet, wenn der Bus frei ist. Wenn gesendet wird, dann wird bei einem ausbleibenden ACK nur dann 3x "probiert", wenn der Bus tatsächlich die ganze Zeit ruhig war.
Es wird dem Aufrufer dann signalisiert, wenn das Senden nicht erfolgreich war, so dass man es nochmal versuchen kann.
Siehe z.B. Methode HBWSwitch::loop.
Gruß,
   Thorsten
FUIP

loetmeister

#446
Hi,

das peering war extern. Ich schau mal das ich mehr action auf den Bus bekomme :)


Danke Thorsten für die Erklärung zu HBWDevice::sendFrame und sendInfoMessage.
Somit mildert eine Art queue, bzw. retry counter für logging/notify events in jedem channel das Problem etwas ab, verhindert es aber nicht das irgendwann events verloren gehen können.

(der Code ist von Dirk, Markus, Thorsten... oder allen zusammen :) )
HBWChannelSw::set() {
//... set IO, dann setze lastFeedbackTime:

  // logging
  if(!nextFeedbackDelay && config->logging) {
    lastFeedbackTime = millis();
    nextFeedbackDelay = device->getLoggingTime() * 100;
  }
}

HBWChannelSw::loop() {
//...

  if(!nextFeedbackDelay)  // feedback trigger set?
    return;
  if (now - lastFeedbackTime < nextFeedbackDelay)
    return;
  lastFeedbackTime = now;  // at least last time of trying
  // sendInfoMessage returns 0 on success, 1 if bus busy, 2 if failed
  // we know that the level has only 1 byte here
  uint8_t level;
  get(&level);
  uint8_t errcode = device->sendInfoMessage(channel, 1, &level);   
  if (errcode == 1)  // bus busy
  // try again later, but insert a small delay
    nextFeedbackDelay = 250;
  else
    nextFeedbackDelay = 0;
}



Hab den post oben ergänzt, (z.B. --> long_multiexecute: Wiederholte lange Tastendrücke beachten. ja/nein. Bei nein wird nur der erste lange Tastendruck ausgewertet.)

Das bringt mich zum nächsten Problem... um das zu erkennen brauche ich den key press counter im set() bzw. receiveKeyEvent()...   ::)
Für LONG_MULTIEXECUTE und ein toggel was sich am Zähler "synchronisiert".
TOGGLE_TO_COUNTER / TOGGLE_INVERSE_TO_COUNTER


Ich bastel erst mal weiter... baue grade on/off time ABSOLUTE/MINIMAL ein.


Gruß,
Thomas

Langerrenner

Hallo Thomas,
in der ELV war vor Jahren ein Bericht zu den Aktoren und deren Aktionsprofile. Kennst Du das, wenn nicht habe ich den File angehängt.
Ich finde Eure Arbeit toll und ich werde auf jeden Fall von diesen Modulen welche einsetzen.
Meine Homematic Anlage läuft seid über 10 Jahren. Nun möchte ich sie etwas umbauen und Zukunftssicherer machen. Leider wird ja die RS485 Schnittstelle im Homematic Bereich in Zukunft wohl auslaufen. Es gibt wohl was neues.
Seid Anfang des Jahres laufen schon einige Module auf meinem Bastel Tisch. In den nächsten Monaten möchte ich mir die eine oder andere Funktion noch hinzu bauen. Wenn ich Zeit habe.
Gruß Willi

Thorsten Pferdekaemper

Zitat von: Langerrenner am 27 März 2018, 10:52:08Leider wird ja die RS485 Schnittstelle im Homematic Bereich in Zukunft wohl auslaufen. Es gibt wohl was neues.
Ja, da hängt jetzt auch ein "IP" dran. Allerdings wird momentan sogar noch FS20 verkauft, da muss man mal abwarten, ob das wirklich ausläuft. Natürlich sind keine Neuentwicklungen zu erwarten.
Ich selbst werde wahrscheinlich bezüglich "HMW-IP" nichts tun. Soweit ich das verstehe, ist das wohl proprietär und nicht zu entschlüsseln, also kommt es für mich nicht in Frage.
Wenn ich da (irgend wann einmal) auf ein inkompatibles (zu HMW) System wechseln muss, dann wird das wohl nicht HMW-IP sein, sondern eher EnOcean.
Gruß,
   Thorsten
FUIP

Ralf9

Zitatbei "sendInfoMessage" wird überhaupt nur gesendet, wenn der Bus frei ist. Wenn gesendet wird, dann wird bei einem ausbleibenden ACK nur dann 3x "probiert", wenn der Bus tatsächlich die ganze Zeit ruhig war.

ZitatDanke Thorsten für die Erklärung zu HBWDevice::sendFrame und sendInfoMessage.
Somit mildert eine Art queue, bzw. retry counter für logging/notify events in jedem channel das Problem etwas ab, verhindert es aber nicht das irgendwann events verloren gehen können.

Danke für die Erklärungen und Infos ich habe es mir mal in den libs angeschaut.
Demnach können logging/notify events nur verloren gehen, wenn bei einem ausbleibenden ACK und ruhigen Bus  3x erfolglos "probiert" wurde.
Wenn ich das richtig überblicke, dann wird bei key events per broadcast und ohne auf ack zu warten gesendet. Das retry wird hier auf denjenigen der den Taster drückt verlagert.

@loetmeister Du kannst mal testen wie es sich verhält, wenn der HM485d.pl nicht läuft.


Das ganze gefällt mir nicht so richtig.Ich möchte die Blockierungen beim Senden wegbekommen. Ich weiß inzwischen wie ich es besser hinbekomme.
Es ist dazu keine Sendewarteschlange notwendig.
Es müsste funktionieren, wenn ich die logging/notify events und die key events in jeweils einem eigenen Bitpuffer speichere. Die zugehörigen Infos werden in einem separaten Array gespeichert,
Bei z.B. 16 Eingängen sind es 16 Bit, also 2 byte.
In der loop wird dann, falls der puffer ungleich 0 ist, in einer Schleife geschaut welche Bits im Puffer gesetzt sind. Den gesetzen Bits entsprechenden Eingänge werden dann gesendet.

@loetmeister
Du verwendest, damit Du mehr Ausgänge bekommst, als Shiftregister 74HC595.
Die geht mit dem MCP23017 einfacher, es gibt dafür eine Lib
Damit sind z.B. 16 Eingänge möglich.
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp;
mcp.begin();
mcp.pinMode(i, INPUT);
mcp.pullUp(i, HIGH);
x = mcp.readGPIO(0);


Gruß Ralf
FHEM auf Cubietruck mit Igor-Image, SSD und  hmland + HM-CFG-USB-2,  HMUARTLGW Lan,   HM-LC-Bl1PBU-FM, HM-CC-RT-DN, HM-SEC-SC-2, HM-MOD-Re-8, HM-MOD-Em-8
HM-Wired:  HMW_IO_12_FM, HMW_Sen_SC_12_DR, Selbstbau IO-Module HBW_IO_SW
Maple-SIGNALduino, WH3080,  Hideki, Id 7