Homematic Wired - Homebrew Devices

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

Vorheriges Thema - Nächstes Thema

loetmeister

#420
Hallo,

Direktes Peering funktioniert nun auch für HBW-LC-BL-4. Mögliche Befehle: open (100%), close (0%), toggle & stop, für lange oder kurze Tastendrücke.
Die lib "HBWLinkBlindSimple" liegt erst mal noch nicht im richtigen "libraries" Verzeichnis... ich muss noch schauen ob mir die so gefällt  ;)

Beide "Nachbauten" in GitHub:
HBW-LC-Sw-8
https://github.com/loetmeister/HBWired/tree/master/HBW-LC-Sw-8
HBW-LC-BL-4
https://github.com/loetmeister/HBWired/tree/master/HBW-LC-BL-4

Der Rest (Sw-12 und BL-8) ist noch nicht fertig....
--> ein paar weitere Updates sind in GitHub hochgeladen. Finale Tests aber erst wenn die Hardware Fertig ist ;)

Gruß,
Thomas

loetmeister

Hallo,

hatte die Tage noch ein paar kleine Änderungen für HBW-LC-Sw-8 ins Git gepusht.

Peering für lange Tastendrücke ging nicht und die Pin Init Funktion (initConfigPins()) wollte nicht so recht...
Ich hatte sie in der selben Schleife in der auch das HBWSwitch/Channel Objekt/Array befüllt wird... aber der Funktionsaufruf klappte aber nicht.


HBWSwitch* switches[NUM_CHANNELS];
...
void setup()...
  for(uint8_t i = 0; i < NUM_CHANNELS; i++){
     switches[i] = new HBWSwitch(pins[i], &(hbwconfig.switchcfg[i]));

//--> geht nicht?!
     switches[i]->initConfigPins();
  };



Für die geänderte HBWSwitch muss nun (ähnlich zu "device->setConfigPins();") jeder Kanal mit initConfigPins(); initialisiert werden. Das setzt dann die Ausgangspins passenden zum im EEPROM gespeicherten Wert (inverted: ja/nein).
Nach dem Erzeugen des "HBSwDevice" klappt auch der initConfigPins() Aufruf....  ???


  for(uint8_t i = 0; i < NUM_CHANNELS; i++){
     switches[i]->initConfigPins();
  };


https://github.com/loetmeister/HBWired/tree/master/HBW-LC-Sw-8

Gruß,
Thomas

Thorsten Pferdekaemper

Hi,
ich habe mal angefangen mir Deinen Pull-Request zu betrachten. Du hast da ja ganz schön viel gebastelt. Es wäre einfacher, das in kleinen Stückchen zu integrieren, aber sehen wir mal. Mir wäre es lieber, das hier zu diskutieren statt im Git, da es hier für mich einfacher ist. Ich denke auch, dass wir das Stück für Stück machen.
Als erstes zu den initConfigPins. Das ist kein Wunder, dass es nicht geklappt hat, da die Konfiguration erst im HBWDevice-Konstruktor aus dem EEPROM gelesen wird. Vorher ist es mehr oder weniger Zufall, was in hbwconfig steht. Deine Lösung funktioniert erstmal, gefällt mir aber trotzdem nicht so ganz. Es bleibt z.B. das Problem, dass nach einer Änderung der Konfiguration das Device durchgestartet werden muss. Das soll nicht so sein. Für solche Sachen ist der "afterReadConfig"-Mechanismus da. Leider hat der auch zwei Problemchen:
1. Der Aufruf virtueller Funktionen im Konstruktor funktioniert nicht. Das ist der Grund, warum das Ding in Subklassen von HBWDevice immer explizit aufgerufen werden muss.
2. Kanäle haben kein afterReadConfig.
Mir wäre es viel lieber, wenn wir das korrigieren (und dann verwenden) könnten anstatt etwas neues zu bauen. Leider habe ich derzeit keine Testumgebung für den ganzen Kram, daher wäre es schön, wenn Du das machen könntest. Ich stelle mir Folgendes vor:

Zu Punkt 1:
In HBWDevice::readConfig wird afterReadConfig nicht direkt aufgerufen, sondern nur ein Flag gesetzt (in etwa "afterReadConfigPending") Am Ende von HBWDevice::loop wird dann afterReadConfig aufgerufen, wenn das Flag gesetzt ist.
Dann kann man sich wahrscheinlich auch die explizite Definition des Konstruktors für Subklassen von HBWDevice sparen.

Zu Punkt 2:
HBWChannel sollte genauso ein afterReadConfig haben wie HBWDevice. D.h. virtual, aber mit leerer Implementierung. Da wo in HBWDevice::loop das afterReadConfig für HBWDevice selbst aufgerufen wird (s.o.) sollte es dann auch für alle channels aufgerufen werden.
In HBWSwitch sollte dann afterReadConfig redefiniert werden mit dem Inhalt "Deines" initConfigPins.

Gruß,
  Thorsten
FUIP

Thorsten Pferdekaemper

Hi,
hier ist der nächste Punkt. Das mit dem useAnalogConfigPin passt mir nicht wirklich. Ich glaube, dass das nur gebraucht wird, weil Du da eine etwas spezielle Beschaltung hast. Normalerweise verwendet mal die Analog-Pins genauso wie die Digital-Pins, wenn man sie als Digital-Pin verwenden will. D.h. INPUT_PULLUP funktioniert und digitalRead ebenfalls. Meiner Meinung nach ist das ein Spezialfall für Deine Hardware und deshalb würde ich Dich bitten, was wieder auszubauen. (...und einfach Deine Widerstände abknipsen.)
Gruß,
   Thorsten
FUIP

loetmeister

#424
Hi Thorsten,

vielen Dank für das super feedback. So richtig glücklich war ich mit dem "initConfigPins" Konstrukt auch nicht. Dein Vorschlag klingt deutlich eleganter. Habe das ganze mal mit "HBW-LC-Sw-8" umgesetzt. Hoffe das ist ok.. es funktioniert jedenfalls schon mal.  ::)

afterReadConfigPending wird nun als flag initial in HBWDevice::HBWDevice und aus afterReadConfig() gesetzt.
Im HBWDevice loop have ich das mal an den Anfang gesetzt, damit bei ersten Start alle Werte und IOs richtig gesetzt sind. (statt am ende vom loop)

@@ -801,6 +803,15 @@ uint8_t HBWDevice::get(uint8_t channel, uint8_t* data) {  // returns length
// The loop function is called in an endless loop
void HBWDevice::loop()
{
+  // read device and channel config, on init and if triggered by ReadConfig() // TODO test afterReadConfig
+   if (afterReadConfigPending) {
+               afterReadConfig();
+               for(uint8_t i = 0; i < numChannels; i++) {
+                      channels[i]->afterReadConfig();  // TODO test afterReadConfig
+               }
+               afterReadConfigPending = false;
+       }
// Daten empfangen und alles, was zur Kommunikationsschicht gehört
// processEvent vom Modul wird als Callback aufgerufen


>> Commit: https://github.com/loetmeister/HBWired/commit/2fe9cba85c60b312308d6e57d304b7427b0cce65#diff-804b89404ca1977353cbc9be6b56c357

Wo müsste ich den folgenden Teil unterbringen um die zusätzliche Subklasse von HBWDevice komplett los zu werden?
//    void afterReadConfig() {
//        // defaults setzen
//        if(hbwconfig.logging_time == 0xFF) hbwconfig.logging_time = 20;
//    };


Eigentlich in HBWDevice::afterReadConfig()..... aber da es Device spezifisch sein könnte nicht in HBWired.cpp...  :-[

Gruß,
Thomas

loetmeister

Hi,

zum Punkt "useAnalogConfigPin"  8)
Hab mir schon fast gedacht, das wird nicht auf Gegenliebe stoßen  ;)

Der Grund ist, die Arduinos mit einem ATmega328 (NANO, MINI) haben zwei ADC ports (ADC6 & ADC7), die nicht mit einem digital Pin kombiniert sind (Port A, B, C, usw.) . Die beiden Pins können nur ADC oder AC (Analog Comparator).
Daher wollte ich einen der beiden Pins für den Config Button nutzen, nicht nur bei 8-fach Rollo, sondern als Standard Layout. (ADC6 = configPin und ADC7 zur Messung der Busspannung)
Mit #ifdef, etc. wars auch nicht schöner...

Ich schaue mal ob ich das per Analog Comparator Interrupt hinbekomme (trigger on raising/falling edge)....

Gruß,
Thomas

Thorsten Pferdekaemper

Zitat von: loetmeister am 08 März 2018, 23:06:25
vielen Dank für das super feedback.
Ich bin froh, dass Du das so siehst. So manch anderer hätte sich über mein "Gemecker" aufgeregt...

Zitat
afterReadConfigPending wird nun als flag initial in HBWDevice::HBWDevice und aus afterReadConfig() gesetzt.
Tatsächlich sieht Dein Coding aber so aus, dass Du es im Konstruktor (HBWDevice::HBWDevice) und in readConfig setzt. Das im Konstruktor kannst Du Dir allerdings sparen, da es ja sowieso schon in readConfig gesetzt wird, was im Konstruktor aufgerufen wird.

Zitat
Im HBWDevice loop have ich das mal an den Anfang gesetzt, damit bei ersten Start alle Werte und IOs richtig gesetzt sind. (statt am ende vom loop)
Ja, das ist tatsächlich besser.
Allerdings ist im Commit noch eine überflüssige Abfrage auf  afterReadConfigPending drin, die in Deinem Forum-Beitrag anscheinend rausgeflogen ist.

Jetzt ist mir gerade noch was wichtiges aufgefallen: HBWChannel::afterReadConfig ist nirgends definiert (nur deklariert). Es kann sein, dass das klappt, wenn man in den Subklassen afterReadConfig definiert, aber wir wollen ja niemanden dazu zwingen. Könntest Du noch die Definition einfügen? (So wie bei afterReadConfig für's Device.

Zitat
Wo müsste ich den folgenden Teil unterbringen um die zusätzliche Subklasse von HBWDevice komplett los zu werden?
Ich meinte nicht, dass Du die Subklasse los wirst, sondern nur deren (expliziten) Konstruktor.

Gruß,
   Thorsten
FUIP

Thorsten Pferdekaemper

Zitat von: loetmeister am 08 März 2018, 23:42:47zum Punkt "useAnalogConfigPin"  8)
Hab mir schon fast gedacht, das wird nicht auf Gegenliebe stoßen  ;)
Der Grund ist, die Arduinos mit einem ATmega328 (NANO, MINI) haben zwei ADC ports (ADC6 & ADC7), die nicht mit einem digital Pin kombiniert sind (Port A, B, C, usw.) .
Das war mir nicht so klar. Ich habe jetzt aber nochmal genauer hingeschaut. Stimmt...

Zitat
Ich schaue mal ob ich das per Analog Comparator Interrupt hinbekomme (trigger on raising/falling edge)....
Immer langsam... Du darfst bei mir nicht so schnell aufgeben. Das was Du sagst klingt ja ganz sinnvoll, da sollten wir eine schöne Lösung finden. Im Prinzip kann man das fest einbauen. D.g. wenn der "config button" A6 oder A7 ist, dann fragt man eben nicht per digitalRead ab, sondern so wie Du das machst. D.h. über einem Schwellwert ist es 1, ansonsten 0.
Dann spart man sich das mit dem extra Flag.

Irgendwelche #ifdefs können wir immer noch einbauen, wenn andere Prozessoren unterstützt werden sollen.

Gruß,
   Thorsten
FUIP

loetmeister

#428
Hallo Thorsten,

Zitat von: Thorsten Pferdekaemper am 09 März 2018, 21:56:21
[...] im Konstruktor kannst Du Dir allerdings sparen, da es ja sowieso schon in readConfig gesetzt wird, was im Konstruktor aufgerufen wird.

[...] HBWChannel::afterReadConfig ist nirgends definiert (nur deklariert). Es kann sein, dass das klappt, wenn man in den Subklassen afterReadConfig definiert, aber wir wollen ja niemanden dazu zwingen. Könntest Du noch die Definition einfügen? (So wie bei afterReadConfig für's Device.

Danke. Ist nun aufgeräumt und hinzugefügt...  8)

ZitatIch meinte nicht, dass Du die Subklasse los wirst, sondern nur deren (expliziten) Konstruktor.
Ok, ich glaube ich habs nun richtig. Die Subklasse bleibt, um eine eigene z.B. HBSwDevice::afterReadConfig() zu definieren, alles andere kommt über die Basisklasse.


HBWDevice::setConfigPins und HBWDevice::handleConfigButton() habe ich zum größten Teil wieder zurück gebaut... und so gelöst:
+       #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
+               if (configPin == A6 || configPin == A7)
+                       pinMode(configPin,INPUT);       // no pullup for analog input
+               else
+       #endif
+               pinMode(configPin,INPUT_PULLUP);


... so würde das nur für Boards mit ATmega328 gelten. Das wäre eine art Sicherheit falls es andere Boards gibt, bei den A6, A7 als digital/analog Kombi Pin existiert. (was ich nicht weiß)


ZitatIch bin froh, dass Du das so siehst. So manch anderer hätte sich über mein "Gemecker" aufgeregt...
Mit den direkten Verbesserungsvorschlägen ist es fern ab von "Gemecker" :-)
... zumal meine C++ Kenntnisse nicht so gut sind. ::)

Gruß,
Thomas

Thorsten Pferdekaemper

Hi,
ja, sieht schon viel besser aus.
Ich schaue mir momentan nur die Dateien an, die Du geändert hast. Alles was neu dazukommt ist erstmal Dein Problem. D.h. ich werde das alles übernehmen, sobald ich mit den geänderten Sachen zufrieden bin.
Könntest Du in "Deine" Dateien irgendwo oben einen Verweis auf Dich reinschreiben? Also z.B. auf Deinen FHEM-Forum Benutzernamen, wenn Du keinen echten Namen bzw. eine Mailadresse angeben willst.

So, jetzt zu weiteren Änderungsvorschlägen:

Zum HBW-Sen-Key-12

Hier habe mich zuerst gewundert, warum Du da überhaupt etwas geändert hast. Eine der Änderungen ist klar. Die Methode HBWSenKey::afterReadConfig passt jetzt natürlich nicht mehr und der Aufruf derselben braucht jetzt auch nicht mehr explizit gemacht zu werden. Das ist ok.
Das "defaulten" der long_press_time ist auch ok.
Das mit der logging_time war allerdings absichtlich nicht in der XML-Datei. Wahrscheinlich ist es durch einen "copy&paste"-Fehler in der .ino-Datei gelandet. Bei reinen Sensor-Devices ist logging_time nicht sinnvoll. Könntest Du das aus der XML-Datei wieder rauswerfen und auch die .ino entsprechend aufräumen? Die Subklasse von HBWDevice wird vermutlich gar nicht mehr gebraucht.
Du hast in der XML außerdem DIRECT_LINK_DEACTIVATE eingefügt. Warum? Ich glaube, dass das nicht richtig ist.

HBWLinkSwitchSimple
Da hast Du wohl einen Bug gefunden und gefixt. Das ist gut. Ich hätte es nur ein ganz klein wenig anders gemacht:

if (longPress) actionType >>= 2; 
actionType &= B00000011;

Das dürfte ein paar Bytes sparen.

HBWSwitch
Ich sehe, Du hast meine TODO-Anweisung befolgt. Das ist gut. Du kannst das gelösche Coding gerne wirklich löschen. (Also nicht nur "//-en".) Ich habe nicht so gerne Coding-Museen.

HBWired
Die Lösung für A6 und A7 finde ich jetzt richtig gut. Die Sonderlocke ist für die 328er und für alles andere bleibts wie es ist.
Vielleicht nur noch eine Kleinigkeit: Die Digital-Eingänge sind normalerweise Low-aktiv, da es ja keine eingebauten Pulldowns gibt. Gibt es einen Grund, warum A6 und A7 High-aktiv sind? Man könnte doch auch hier einen Pullup an den Pin legen und per Taste nach GND kurzschließen, oder? Möglicherweise übersehe ich da aber was.

Gruß,
   Thorsten
FUIP

loetmeister

Hallo,

hab noch ein paar Änderungen gemacht... deine Vorschläge und "aufgeräumt", denke es nähert sich der "Fertigstellung".  :)
Schaltpläne mehr Infos zur Hardware würde ich später noch hinzufügen...

Zitat von: Thorsten Pferdekaemper am 10 März 2018, 21:50:50
Zum HBW-Sen-Key-12 [...] Das mit der logging_time war allerdings absichtlich nicht in der XML-Datei. Wahrscheinlich ist es durch einen "copy&paste"-Fehler in der .ino-Datei gelandet. Bei reinen Sensor-Devices ist logging_time nicht sinnvoll. Könntest Du das aus der XML-Datei wieder rauswerfen und auch die .ino entsprechend aufräumen? Die Subklasse von HBWDevice wird vermutlich gar nicht mehr gebraucht.
Ok, hatte mich auch ein wenig gewundert das logging_time im Code, aber nicht in der XML stand. Habs bei beiden nun raus genommen. Die HBWDevice Subklasse ist auch gelöscht.


ZitatDu hast in der XML außerdem DIRECT_LINK_DEACTIVATE eingefügt. Warum? Ich glaube, dass das nicht richtig ist.
Ich hatte den kompletten "DIRECT_LINK_DEACTIVATE" Block aus den XML Dateien der original HM Geräte kopiert... inkl. "enforce". Scheint der Funktion keinen Abbruch zu tun.
Wenns ok ist würde ich es drin lassen.
<parameter id="DIRECT_LINK_DEACTIVATE" hidden="true">
<logical type="boolean" default="false"/>
<physical interface="eeprom" size="0.1" type="integer">
<address index="0x0006"/>
</physical>
</parameter>
<enforce id="DIRECT_LINK_DEACTIVATE" value="true"/>



Zitat
HBWLinkSwitchSimple Da hast Du wohl einen Bug gefunden und gefixt. Das ist gut. Ich hätte es nur ein ganz klein wenig anders gemacht:

if (longPress) actionType >>= 2; 
actionType &= B00000011;

Das dürfte ein paar Bytes sparen.
Das ließt sich auf jeden Fall schön und die bitmaske ist nicht "doppelt".... aber es würde beim BL-4 zwei Bytes extra kosten. Beim Switch Sw-8 blieb es gleich, daher hab ich zu deinem Code geändert. :)

Zitat
HBWired Die Lösung für A6 und A7 finde ich jetzt richtig gut. Die Sonderlocke ist für die 328er und für alles andere bleibts wie es ist.
Vielleicht nur noch eine Kleinigkeit: Die Digital-Eingänge sind normalerweise Low-aktiv, da es ja keine eingebauten Pulldowns gibt. Gibt es einen Grund, warum A6 und A7 High-aktiv sind? Man könnte doch auch hier einen Pullup an den Pin legen und per Taste nach GND kurzschließen, oder?
Danke. :)
Es gibt eigentlich keinen Grund warum hier nicht auch Low-aktiv gilt... ich hatte einfach den Spannungsteiler im Schaltplan eingezeichnet und dann nicht weiter in Frage gestellt...
Habe es geändert. Beschaltung wäre nun ein "weak pullup" und der Taster gegen Masse.

Gruß,
Thomas

Thorsten Pferdekaemper

Hi,
Dein Pull-Request ist jetzt drin. Wie schon gesagt habe ich bisher nur die geänderten Dateien angeschaut. Alles, was neu dazugekommen ist, habe ich erst einmal ignoriert.
Ich werde jetzt noch das Wiki anpassen, so dass es auf die neuen Implementierungen verweist.
Gruß,
   Thorsten
FUIP

Thorsten Pferdekaemper

Sodele, Wiki ist jetzt auch angepasst.
FUIP

loetmeister


Shortie

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.

Ich 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.
Ich hatte sowas schonmal in Easyeda versucht zu routen, nur hat das leider nicht so richtig klappen wollen.