Homematic Wired - Homebrew Devices

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

Vorheriges Thema - Nächstes Thema

Thorsten Pferdekaemper

...warum kommt eigentlich immer alles in denselben unübersichtlichen Thread? Na egal..

HMW hat halt bei den Peerings im Prinzip nur Tasten und Schalter. Vielleicht war bei eq3 mal mehr vorgesehen, aber das wissen wir halt nicht. Wenn  Du das jetzt erweitern willst, dann wäre es wohl am Besten, irgendwo in der Basisklasse ein receiveEvent zu haben (wofür steht das "IM"?). Davon abgeleitet könnte es dann etwas spezielleres für (z.B.) Keys geben.

Das Peering selbst wäre dann erstmal ein Problem im XML. Es gibt ja nicht so etwas wie "TemperatureSender" und "TemperaturReceiver". ...und wenn man es macht, dann müsste FHEM das auch erstmal noch kennenlernen. D.h. man könnte da höchstens was mit Key/Switch faken, was aber auch etwas hässlich wäre.
Ansonsten halt mit raw-Kommandos ins EEPROM schreiben.

Nachricht 0x41 ist die Announce-Message. Das passt irgendwie gar nicht. Da sollte man eher den 0x69 (das ist "Information") oder eben 0x4B (Key) nehmen und halt ein bisschen abwandeln. Schön ist das aber alles nicht.

Ich würde da ehrlich gesagt nicht so viel Aufwand reinstecken. Besser wäre meiner Meinung nach, einen Stellwert (Prozent Ventilöffnung, Puls/Pause-Verhältnis oder so) zu schicken und die ganze Regelung FHEM zu überlassen. Man könnte noch eine Notfall-Stellung vorgeben, wenn das Ding eine bestimmte Zeit keinen Befehl empfängt, aber das wär's dann meiner Meinung nach schon.

Gruß,
    Thorsten
FUIP

loetmeister

Hi Thorsten,

Zitat
HMW hat halt bei den Peerings im Prinzip nur Tasten und Schalter. Vielleicht war bei eq3 mal mehr vorgesehen, aber das wissen wir halt nicht. Wenn  Du das jetzt erweitern willst, dann wäre es wohl am Besten, irgendwo in der Basisklasse ein receiveEvent zu haben (wofür steht das "IM"?). Davon abgeleitet könnte es dann etwas spezielleres für (z.B.) Keys geben.
"IM" steht für Info Message (0x69 bzw. 'i'). Diese Message hatte ich abgewandelt und HBWired eine Empfangsmöglichkeit hinzugefügt.
Ich versuche es mal aus einer Klasse abzuleiten...
receiveEvent
          -> receiveKeyEvent
          -> receiveIMEvent



Fände es halt schön eine Einzelraumsteuerung autonom zu haben, erst zum ändern der Zieltemperatur, Visualisierung, etc. käme FHEM ins Spiel.


Zitat
...warum kommt eigentlich immer alles in denselben unübersichtlichen Thread? Na egal..
... dachte den haben einige in den Lesezeichen ::)

Gruß,
Thomas

Thorsten Pferdekaemper

Zitat von: loetmeister am 24 April 2019, 20:39:14
"IM" steht für Info Message (0x69 bzw. 'i'). Diese Message hatte ich abgewandelt und HBWired eine Empfangsmöglichkeit hinzugefügt.
Ach so, Du verwendest gar nicht 0x41. Dann ist ja ok.

Zitat
Ich versuche es mal aus einer Klasse abzuleiten...
receiveEvent
          -> receiveKeyEvent
          -> receiveIMEvent

So unbedingt notwendig wäre das ja nicht. Ich dachte nur, da das receiveIMEvent schon sehr allgemein aussieht...

Zitat
Fände es halt schön eine Einzelraumsteuerung autonom zu haben, erst zum ändern der Zieltemperatur, Visualisierung, etc. käme FHEM ins Spiel.
Klar, schön ist das schon. Der Aufwand ist halt nur ziemlich groß. Außerdem ist es recht schwierig, das zu konfigurieren. Ich fände es z.B. gut, wenn man nicht auf eine Regelung festgelegt ist, die nur (eine) Ist- und Solltemperatur kennt. Z.B. würde bei mir noch ggf. Vorlauftemperatur und (möglicherweise vorhergesagte) Außentemperatur mit einfließen. Das sind aber nur Ideen. Ob ich das jemals so mache steht in den Sternen...

Gruß,
   Thorsten
FUIP

loetmeister

Hi Thorsten,

ich wollte mich erst mal auf die Einzelraumsteuerung beschränken, die Heizungssteuerung kümmert sich um Vorlauftemperatur und Außentemperatur.
Wie du angemerkt hast, wäre es sicher einfacher nur ein Aktor als Ventilsteller zu nehmen und FHEM den Rest zu überlassen...

Habs aber dennoch mal in HBW-CC-VD-2 eingebaut.  :D
Der PID Regler lässt sich intern (extern hab ich noch nicht getestet) mit dem 1-Wire Temperatur Sensor peeren. Der (fest verküpfte) Valve Kanal setzt dann den Wert an einem Ausgangspin um.
https://github.com/loetmeister/HBWired/tree/master/HBW-CC-VD-8

Leider ist bei zwei Sachen noch der Wurm drin.  :-\

1. In FHEM bekomme ich nicht die Option angezeigt im PID Kanal die "DESIRED_TEMP" zu setzen, obwohl set request="TEMP_SET" frame und operations write gesetzt sind. Nur "config", "inhibit" und "peer"...  ???
TEMP_GET und INFO_TEMP funktionieren im Temperatur Kanal...
<paramset type="VALUES" id="hmw_pid_ch_values">
<parameter id="DESIRED_TEMP" operations="read,write,event" control="TEMP.LEVEL">
<logical type="float" default="0.0" min="0.0" max="30.0" unit="℃"/>
<physical type="integer" interface="command" value_id="TEMP">
<set request="TEMP_SET"/>
<get request="TEMP_GET" response="INFO_TEMP"/>
<event frame="INFO_TEMP"/>
</physical>
<conversion type="float_integer_scale" factor="100"/>
</parameter>
<parameter id="INHIBIT" operations="read,write,event" control="NONE" loopback="true">
<logical type="boolean" default="false"/>
<physical type="integer" interface="command" value_id="INHIBIT">
<set request="SET_LOCK"/>
</physical>
</parameter>
</paramset>




Das zweite, noch seltsamere Problem betrifft den Arduino....
Ohne HBWLinkSender / HBWLinkReceiver im Device (also beides 'NULL') funktioniert alles soweit. Valve- und Temperaturkanäle senden ihren Status, etc. Ausgabe im Seriellen Monitor ist ok.
Wenn ich aber meine HBWLinkSender / HBWLinkReceiver dazu nehme (ohne ein peering gesetzt zu haben) startet der Arduino nach einiger zeit neu.
Bevor das passiert gab es sonderbare Effekte das im Seriellen Monitor Zeichen der debug Ausgabe verändert haben ('!' statt '%' oder nicht druckbare Zeichen) - was eigentlich statischer Text ist. Klingt als gäbe es Pointer die an die falsche Speicheradresse zeigen oder verändert werden... was ich mir aber nicht erklären kann..  :o
z.B.
T: FD:00:00:00:01:98:42:00:00:30:06:69:02:C8:70:89:46
R: FD:42:00:00:30:19:00:00:00:01:02:77:50
R: ACK
Valve ch: 2 snd: 100%

Der Fette Text sollte "send" sein... Schnöde hbwdebug Ausgabe...
hbwdebug("Valve ch: "); hbwdebug(channel); hbwdebug(" send: "); hbwdebug(level/2); hbwdebug("%\n");
... davor ein device->sendInfoMessage(channel, 2, &level);

Um den Link Kram anzuschalten wenn man ihn wirklich braucht, habe ich erst mal #define Support_HBWLink_InfoMessage in HBWired.h gesetzt. Schöner wäre es, dies über den Sketch zu steuern, was meines Wissens aber nicht geht.

Hab mal statt "IMEvent" "InfoEvent" genommen. Ist etwas weniger Generisch/Kryptisch...
HBWLinkInfoMessageActuator: receiveInfoEvent
HBWLinkInfoMessageSensor: sendInfoEvent

https://github.com/ThorstenPferdekaemper/HBWired/compare/master...loetmeister:master#diff-340d6f8cfa01a00fa61bea3db56dfddf

Gruß,
Thomas

Thorsten Pferdekaemper

Zitat von: loetmeister am 28 April 2019, 19:06:33
ich wollte mich erst mal auf die Einzelraumsteuerung beschränken, die Heizungssteuerung kümmert sich um Vorlauftemperatur und Außentemperatur.
Ich meinte ja auch gar nicht, die Vorlauftemperatur zu steuern. Ich meinte, die Vorlauftemperatur ebenfalls als Messwert für den Regler zu haben. Ich habe beispielsweise bei mir manchmal das Problem, dass die Vorlauftemperatur so zweimal am Tag sehr hoch ist, weil die Heizung heißes Wasser produziert. Währenddessen bekommen die Heizkörper kein neues warmes Wasser und machen die Ventile auf. Wenn jetzt das heiße Wasser fertig ist, dann schaltet das System um und der "heiße" Vorlauf donnert in die Heizkörper. Je nach Raum wird es dann zu warm. Das könnte man durch eine intelligentere Regelung bei den Heizkörpern vermeiden. (Natürlich könnte man das auch mit einem Mischer hinbekommen...).
Aber wie schon gesagt: Du solltest nicht auf die Idee kommen, meine "Anforderungen" umzusetzen, da ich das wahrscheinlich in absehbarer Zeit sowieso nicht umsetze.

Zitat
1. In FHEM bekomme ich nicht die Option angezeigt im PID Kanal die "DESIRED_TEMP" zu setzen, obwohl set request="TEMP_SET" frame und operations write gesetzt sind. Nur "config", "inhibit" und "peer"...  ???
Lass mal das "control"-Attribut weg.

Zitat
Das zweite, noch seltsamere Problem betrifft den Arduino....
Das klingt mir irgendwie nach Speicherüberlauf. Kann es sein, dass Du den kleinen etwas überforderst?

Gruß,
   Thorsten
FUIP

loetmeister

ZitatLass mal das "control"-Attribut weg.
Ok, das bringt mich einen Schritt weiter, danke. Jetzt kommt die Auswahl, inkl. Eingabefeld (zeigt das aktuelle Reading). Leider kommt die folgende Meldung wenn ich den Wert setzen will:
Unknown argument desired_temp, choose one of  config desired_temp inhibit:on,off peer:HBW_CC_VD2_...


Um das Problem zu finden hatte ich DESIRED_TEMP mit dem "VALVE" Kanal verglichen... der Funktioniert, nutzt aber andere Frames.

<paramset type="VALUES" id="hmw_input_ch_values">
        <parameter id="VALVE" operations="read,write,event" control="VALVE.LEVEL">
<logical type="float" default="0.0" min="0.0" max="1.0" unit="100%"/>
<physical type="integer" interface="command" value_id="STATE">
<set request="LEVEL_SET"/>
<get request="LEVEL_GET" response="INFO_LEVEL"/>
<event frame="INFO_LEVEL"/>
</physical>
<conversion type="float_integer_scale" factor="200"/>
        </parameter>



Zitat
Das klingt mir irgendwie nach Speicherüberlauf. Kann es sein, dass Du den kleinen etwas überforderst?

Der Fehler hing wohl damit zusammen in der virtual void HBWPidsValve::set() einen Aufruf zu einer nicht vituellen Funktion setPidsValve() zu haben, bzw. darin einen Pointer weiter zu reichen... nachdem sie "virtual" ist, läuft es. Mit dem code für  meine HBWLinkSender / HBWLinkReceiver hatte es nichts zu tun.

virtual uint8_t getPidsValve(uint8_t* data);  // <--- war nicht "virtual"
...

void HBWPidsValve::set(HBWDevice* device, uint8_t length, uint8_t const * const data)
{
  pid->setPidsValve(data);
}

void HBWPids::setPidsValve(uint8_t const * const data)
{
  if (*(data) == 0) {...

 

Gruß,
Thomas

Thorsten Pferdekaemper

Zitat von: loetmeister am 29 April 2019, 00:34:10
Ok, das bringt mich einen Schritt weiter, danke. Jetzt kommt die Auswahl, inkl. Eingabefeld (zeigt das aktuelle Reading). Leider kommt die folgende Meldung wenn ich den Wert setzen will:
Unknown argument desired_temp, choose one of  config desired_temp inhibit:on,off peer:HBW_CC_VD2_...
Ich bin mir nicht ganz sicher, aber versuch' mal folgendes: In Datei 10_HM485.pm, Zeile 582, steht das hier:

if($isChannel && defined($sets{$cmd})) {

Ändere mal das "defined" in "exists". Dann FHEM neu starten (ein "reload 10_HM485" könnte auch reichen) und probier's nochmal.

Zitat
Um das Problem zu finden hatte ich DESIRED_TEMP mit dem "VALVE" Kanal verglichen... der Funktioniert, nutzt aber andere Frames.
HM485 in FHEM "kennt" VALVE.LEVEL. Ich weiß nicht (mehr) warum das drin ist, da es ja nirgends in den Original-XMLs vorkommt. Jedenfalls ist es fest verdrahtet und reagiert genause wie DIMMER.LEVEL.

Zitat
Der Fehler hing wohl damit zusammen in der virtual void HBWPidsValve::set() einen Aufruf zu einer nicht vituellen Funktion setPidsValve() zu haben, bzw. darin einen Pointer weiter zu reichen... nachdem sie "virtual" ist, läuft es.
Das finde ich zwar etwas seltsam, aber wenn es jetzt geht, dann ist ja gut.

Gruß,
   Thorsten
FUIP

loetmeister

#547
Zitat

if($isChannel && defined($sets{$cmd})) {

Ändere mal das "defined" in "exists". Dann FHEM neu starten (ein "reload 10_HM485" könnte auch reichen) und probier's nochmal.
Das hat geklappt. Danke. Jetzt kann ich die "desired_temp" setzten.
Was müsste ich denn an meiner XML ändern, damit es ohne der Modifikation an 10_HM485.pm läuft? Ich kann nicht erkennen wie ich den set Befehel (TEMP_SET) anders definieren müsste...  :-[ Wenn HM485::Device::getAllowedSets() die erlaubten "set" Befehle aus der XML liest und Validiert... ist das etwas zu Kryptisch für mich...  ???


Ok, gut zu wissen das es die gibt :)
                'blind.level'   => "slider,0,1,100 on:noArg off:noArg up:noArg down:noArg",
                'blind.stop'    => "noArg",
                'dimmer.level'  => "slider,0,1,100 on:noArg off:noArg",
                'valve.level'   => "slider,0,1,100 on:noArg off:noArg",
                'button.long'   => "noArg",
                'button.short'  => "noArg",
                'digital_analog_output.frequency' => "slider,0,1,50000",



EDIT:
Hab mal https://github.com/loetmeister/HBWired/tree/master/HBW-CC-VD-8 aktualisiert. In dem PID Regler waren noch ein paar größere Schnitzer.  ::)
Läuft nun aber auch mit Cycle Zeiten größer 65 Sekunden....
Auf 8 Kanäle änder ich es, wenn ich das externe peering mit den Temperatursensoren getestet habe.


Gruß,
Thomas

Thorsten Pferdekaemper

Zitat von: loetmeister am 29 April 2019, 15:54:08
Was müsste ich denn an meiner XML ändern, damit es ohne der Modifikation an 10_HM485.pm läuft?
Da hast Du wahrscheinlich keine Chance. Das ist halt ein Bug im FHEM-Modul. Ich kann das mal fixen, aber momentan habe ich kein HM485-Testaufbau. Vielleicht finden wir dafür ja einen Freiwilligen... (Hallo Freiwillige!)
Könntest Du dazu mal einen Issue hier erfassen:
https://github.com/kc-GitHub/FHEM-HM485/issues
...am besten mit allen (beiden?) Änderungen, die Du jetzt gemacht hast. Nur damit das nicht in Vergessenheit gerät.
Gruß,
   Thorsten
FUIP

loetmeister

Hi Thorsten,

ok... danke. Habe, wie vorgeschlagen, ein "issue" festgehalten:
https://github.com/kc-GitHub/FHEM-HM485/issues/63

Gruß,
Thomas

loetmeister

Hallo,

hab noch ein Device in die aktuelle Lib übernommen: HBW-Sen-EP
Das Modul HBW-Sen-EP liest bis zu 8 angeschlossene S0-Signale ein und sendet die aktuellen Zählerstände an die Zentrale.
Über das S0-Interface können bspw. Stromzähler, Gaszähler, Wärmemengenzähler, Wasserzähler, etc. eingelesen werden.

Code ist ist von Thorsten + meine Änderungen/Ergänzungen. Bei jfische hatte ich auch mal geschaut, die Änderungen dort waren mir aber zu "speziell" für seinen Anwendungsfall ;)
Einstellungen pro Kanal:
# Deaktivierung
# Invertierung

# Minimum-Sendeintervall
# Maximum-Sendeintervall
# Abtastung (10...150ms in 10 ms Schritten)
# Zählerdifferenz

https://github.com/loetmeister/HBWired/tree/master/HBW-Sen-EP


HBW-CC-VD-8 drehe ich nochmal etwas auf Links... Ziel ist es unabhängige 'valve' Kanäle zu haben, die entweder intern über den PID oder extern von FHEM gesteuert werden können. Aus der  'valve' Kanalklasse müsste man dann auch einfach ein eigenständiges Device erstellen können.


Gruß,
Thomas

loetmeister

Hi,

habe grade noch eine kleine Änderung für HBW-Sen-EP hochgeladen.
https://github.com/loetmeister/HBWired/tree/master/HBW-Sen-EP

Mir ist reproduzierbar der Controller abgeschmiert, wenn ich den Pointer (uint8_t level) für get(&level) nicht als "static" deklariere...
Ich habe das bisher in keinem Device gemacht... meist war die Rückgabe vom get() nur 1 byte (falls das einen Unterschied macht?), aber bei HBW-1W-T10 ist sie auch 2 byte, und dort hatte ich nicht diesen Effekt. Hab ich da Glück gehabt? ::)

uint8_t HBWSenEP::get(uint8_t* data) {
  *data++ = (currentCount >> 8);
  *data = currentCount & 0xFF;
  return 2;
};

loop()
[...]
    // send
    uint8_t level;   // <--- Fehler
    //static uint8_t level;   // <--- OK!
    get(&level);

[...]
    hbwdebug(F("Ch: ")); hbwdebug(channel); hbwdebug(F(" send: ")); hbwdebug(lastSentCount); hbwdebug(F("\n"));


    
Im Serial Monitor kommt noch ein Teil der hbwdebug Ausgabe, dann die neue hbwdebug Ausgabe nach dem Neustart. Welche mit "B: 2A " beginnen sollte...
22:17:43.808 -> Ch?? 2A 1198


Gruß,
Thomas

Thorsten Pferdekaemper

Hi,
naja, uint8_t ist halt mal nur ein Byte, wenn Du dann sowas machst wie *data++ = ..., dann überschreibst Du irgendwas, was zufällig danach kommt. Wenn Du das ganze mit static deklarierst, dann steht es halt in einem anderen Speicherbereich, bei dem es zufällig nicht ganz so weh tut (oder eben erst später). Ungefähr so wäre es vermutlich richtig:

uint8_t HBWSenEP::get(uint8_t* data) {
  *data++ = (currentCount >> 8);
  *data = currentCount & 0xFF;
  return 2;
};

loop()
[...]
    // send
    uint16_t level;   
    get((uint8_t*)(&level));


Gruß,
   Thorsten
FUIP

loetmeister

Hallo,

habe HBW-CC-VD-8 "etwas" verändert. Der PID ist von seiner Funktion so geblieben, dafür gibt es neue Ventilregler (HBWValve) bei denen die Stellzeiten und Verhalten separat Konfiguriert werden kann.

HBWValve setzt im Kern auf den code von hglaser. Dazu ein paar Anpassungen für die aktuelle Lib und Ergänzungen meinerseits.
Zitat"time proportioning control" eine Art extrem langsames PWM. Bei über 50% schaltet das Ventil zuerst ein, unter 50% zuerst aus. Nach einer Änderung wird die erste Ein- oder Auszeit einmal halbiert
HBWValve kann auch in einem eigenen Device genutzt werden, als einfacher Ventilsteller.

Konfiguration:
   LOGGING
   OUTPUT_LOCKED
   INVERTED
   SEND_MAX_INTERVALL
   VALVE_ERROR_POS
   SWITCH_TIME (Zeit die zum vollständigen öffnen benötigt wird)

set the desired Valve State in Manual Mode level = 0 - 200 like a Blind or Dimmer
* Special values:
* 201 - toggle automatic/manual
* 203 - manual (set error position 1st. Then allow any level 0...100%)
* 205 - automatic (locks the channel to be controlled by linked PID channel)


https://github.com/loetmeister/HBWired/tree/master/HBW-CC-VD-8

PS: Sind noch immer keine 8 Kanäle.... bin noch am testen.. :)



Thorsten,
bzgl. der Möglichkeit das HBW Devices untereinander daten per peering auszutauschen. Ich wollte ja die "InfoMessage" (0x69) nutzen... Da aber der Frame doch anders aufgebaut ist, habe ich das in HBWLink_InfoEvent umbenannt und type 0xB4 definiert (ein mix auf Info Message und KeyEvent 0x4B).
Das ganze ist Standardmäßig inaktiv, wenn man die Funktion braucht muss man es per "define" aktivieren.
Wäre das ein gangbarer Weg?
HBWired.h
// #define Support_HBWLink_InfoEvent


https://github.com/loetmeister/HBWired/commit/6f25152bb04cb5d8ed103eda8b41dd8e84ba612c


PPS: Bzgl. dem Pointer werde ich testen und ändern... [uint16_t level;   get((uint8_t*)(&level));] Danke!

Gruß,
Thomas

stan23

Zitat von: Thorsten Pferdekaemper am 08 Mai 2019, 21:32:02
uint8_t ist halt mal nur ein Byte, wenn Du dann sowas machst wie *data++ = ..., dann überschreibst Du irgendwas, was zufällig danach kommt. Wenn Du das ganze mit static deklarierst, dann steht es halt in einem anderen Speicherbereich, bei dem es zufällig nicht ganz so weh tut (oder eben erst später).

Das ist eine funktionslokale Variable und sie liegt auf dem Stack. Weil der Stack rückwärts wächst, hast du dir damit irgendwas überschrieben, was in loop() kurz davor auf den Stack gelegt wird.

uint8_t level;


Diese Variable behält ihren Wert bis zum nächsten Funktionsaufruf und sie liegt im globalen Speicherbereich. Du hast dir damit irgendwas überschrieben was danach liegt, oder mit etwas Glück ist dort frei. Zumindest wird der Fehler nicht gleich sichtbar.

static uint8_t level;