« Heizung, Lüftung, Klima  |

DIY Alternative zu Nibe Modbus Modul

Teilen: facebook    whatsapp    email
 
 1  2 ... 3 ... 20  21  22  23 ... 24 ... 49  50  51 
  •  chrismo
  •   Gold-Award
29.1.2019 - 25.4.2024
1.009 Antworten | 62 Autoren 1009
127
1136
Weil es hier immer wieder zu Diskussionen zum Thema Modbus-Anbindung der Nibe kommt, wollte ich hier mal kurz meine Erfahrungen mit dem Nachbau einer DiY Lösung, auf Basis von im Netz vorhandener Infos, teilen. Für mich war es eine Spielerei und Zeitvertreib der letzten Tage. Der Post dient vor allem als Speicherort für meine gesammelten Infos und evt. dem Austausch von Leuten, die das so oder so ähnlich bei sich installiert haben. Ich kann und will hier keine Empfehlung abgeben, sowas selbst zu machen!

Die Lösung basiert im Wesentlichen auf den Nibe Bindings von openHAB (https://www.openhab.org/addons/bindings/nibeheatpump/), das eine Umsetzung Modbus auf UDP macht. Infos zur Funktionsweise findet man auf der openHAB Seite bzw. dem entsprechenden github Repo.

Die grobe Vorgangsweise war folgend:
1) Auf einen Arduino mit Ethernet Shield und RS485 Adapter die NibeGW Software (Teil des Bindings) installieren. Der Ardunio Code muss dabei an die eigenen Netzwerkeinstellungen angepasst werden. 

2) Den Arduino an die Wärmepumpe und ans LAN anschließen.

3) Die Nibe Modbus Manager Software auf einem Rechner installieren und bis zu 20 Register auswählen, die periodisch von der Wärmepumpe exportiert werden sollen. Diese Konfig muss gespeichert und per USB-Stick auf die WPWP [Wärmepumpe] übertragen werden.

4) Das Modbus Modul in der WPWP [Wärmepumpe] aktivieren. Wenn alles geklappt hat, bleibt die Wärmepumpe im Normalbetrieb. Falls irgendwas bei der Kommunikation mit dem Arduino schief geht, wird eine Fehlermeldung am Display ausgegeben und die WPWP [Wärmepumpe] geht in einen Alarmmodus.

5) Das nibeopenhab Binding in openHAB installieren und konfigurieren.

zu 1) Man könnte dazu auch einen Raspberry Pi mit RS485 Adapter verwenden, auf dem dann auch openHAB selbst läuft. Das finde ich aber nicht optimal. Ein Pi wäre mir da nicht robust genug. Selbst ein einfacher Neustart des Pis würde zu einem Fehler der WPWP [Wärmepumpe] führen und ein SD-Kartenfehler wäre sowieso ungemütlich.

zu 5) Da ich derzeit noch nicht weiß ob es openHAB oder was anderes wird - über Erfahrungen bzw. Empfehlungen würde ich mich freuen(!) - habe ich das Binding so adaptiert, das es ohne openHAB läuft. Derzeit verwende ich die Log-Dateien dieses "Stand-Alone Bindings" zur Speicherung der Werte. Eine Erweiterung für "richtige" Ausgabeformate bzw. Kanäle (Umsetzung auf KNX wurde hier mal in einem anderen Thread diskutiert) wäre aber von hier weg leicht machbar.

von energiesparhaus

  •  JanRi
  •   Gold-Award
4.6.2020  (#421)

zitat..
Becker schrieb:  definitiv nicht!


Getestet hatte ich das nicht, von daher kann meine Aussage falsch sein.

zitat..
nibepi schrieb: I'm having some problem keeping up with the translating here.


I guess the main question is how NodeRed triggers requests and how it deals with registers from LOG.SET. The former arrive as type 106 message and the other as 104 (I refer to them in this way now).

Is it right that every register from type 104 message is immediately available in NodeRed? They are updated every two seconds and are therefore very fresh.

With respect to type 106 messages, they need to be requested. So I guess the main point for Becker is how to trigger this from NodeRed.

Is there any difference in handling? I guess registers from LOG.SET (which are contained in type 104 messages) are NOT requested, right? The others are requested (at least this is the way I do it).


zitat..
nibepi schrieb: I thought I had made it right, but my values in the heatpump are not that long that it's stored in more than the 16 bit part.


As I have currently no NibePi installation because I'm very happy with my UDP-solution and I do not have time to search: Can you point (link to git or similar) me directly to the file containing the decoding part (in 1.0.6 this was method decodeMessage? Or, just post the function here. Then I could check it based on the experiences with my decoder. This way, we can make sure that is is correct.




1
  •  nibepi
4.6.2020  (#422)

zitat..
JanRi schrieb: Then I could check it based on the experiences with my decoder. This way, we can make sure that is is correct.


Thank you Jan, decodeMessage starts at line 747 in this link https://github.com/anerdins/nibepi/blob/master/index.js
104 messages have one way and 106 ( else statement ), I guess only the s32 and u32 registers are of interest here.

zitat..
JanRi schrieb: Is it right that every register from type 104 message is immediately available in NodeRed? They are updated every two seconds and are therefore very fresh.

Yes they are, the 80 byte message is cut up and sent out in pieces on MQTT and to NodeRED, but you need a node with that register id to catch it in nodered, or have a unnamed node which catches every message.

zitat..
JanRi schrieb: With respect to type 106 messages, they need to be requested. So I guess the main point for Becker is how to trigger this from NodeRed.

NodeRed does this with a node, when Becker adds a input node and name a register there, that register is either collected from log.set message or added to a queue list that loops around and gets requested every 2,1 sec. (This is why he dont need to do anything in nodered when he has set the log.set in the WPWP [Wärmepumpe], the node will get what it want from the log.set message directly and it will be taken away from the "slow" queue list. So it does not take a number in the queue.
There is also a request node, that get the value in top of the queue and gets the value you want without waiting for the loop. Nice to have for registers you dont want to get every 2,1-10 second or so, like language, setpoints, etc.

The main point with NibePi is that it should just work, no need to think about 104 or 106 registers, just getting the data the fast way or the slow way. If you do nothing, it will be the slow way. But it will work and is very user friendly.


1
  •  JanRi
  •   Gold-Award
4.6.2020  (#423)
Thank you for the link. Here are my comments:

line 772 to 778: The order of bytes is wrong here. Type 106 messages are LSB order, so line 773 should read:

data = buf[i + 2] | buf[i + 3] <<8 | buf[i + 4] <<16 | buf[i + 5] <<24;

The implementations on "s8" and "u8" look strange... just consider buf[i+2] and ignore the rest. This way, you stay within 8 bit without any effort.

Line 803 on u32 in type 106 is also wrong byte order. This should be LSB too:

data = (buf[i + 2] & 0xFF) | (buf[i + 3] & 0xFF) << 8 | (buf[i + 4] & 0xFF) << 16 | (buf[i + 5] & 0xFF) << 24;

I read u32 values such as heat meter in LSB and get correct values. My decoding line for u32 is

data=buf[i+2]+256*buf[i+3]+256*256*buf[i+4]+256*256*256*buf[i+5];

...which is the same as

data = (buf[i + 2] & 0xFF) | (buf[i + 3] & 0xFF) << 8 | (buf[i + 4] & 0xFF) << 16 | (buf[i + 5] & 0xFF) << 24;

1
  •  nibepi
4.6.2020  (#424)

zitat..
JanRi schrieb: line 772 to 778: The order of bytes is wrong here. Type 106 messages are LSB order, so line 773 should read:

data = buf[i + 2] | buf[i + 3] <<8 | buf[i + 4] <<16 | buf[i + 5] <<24;

zitat..
JanRi schrieb: Line 803 on u32 in type 106 is also wrong byte order. This should be LSB too:

data = (buf[i + 2] & 0xFF) | (buf[i + 3] & 0xFF) << 8 | (buf[i + 4] & 0xFF) << 16 | (buf[i + 5] & 0xFF) << 24;

I'm getting corrupt values now after that. Do you have word swap enabled?




1
  •  JanRi
  •   Gold-Award
5.6.2020  (#425)

zitat..
nibepi schrieb: I'm getting corrupt values now after that. Do you have word swap enabled?

? Since I'm no expert in Node.js or Javascript, I have not set anything that is not standard. However, I run the appropriate code on a Linux PC, not a RPi. This should not matter since it is Javascript and both architectures (ARM as well as x86_64) are LSB.

How can I check this word swap feature? Or do you mean a feature of the heat pump?

I just go through the data I get from UDP (send by nibegw). Lets take a heatmeter as example.

I request register 44300 and get answer 5c 00 20 6a 06 0c ad ee e9 02 00 e8 00 (this is the dump of the buffer I got from UDP (I dump the message using toString('hex')). As nibegw just forwards the data, this should be the data sent by the heatpump - nibegw does not do any sorting.

6a is type 106. 06 is payload length (+7 is message length). 0c ad is 12+173*256=44300 which is the register we requested.

The data itself is ee e9 02 00. After this, we have the checksum.
ee = 238
e9 = 233
02 = 2
00 = 0

If I put it together, we have 238+233*256+2*65536=190958 (evaluation in LSB order with no swapping).

The divider is 10, therefore, the value of the heatmeter is 19095,8 which is correct according to heatpump display.

Can you do a similar debug output of a (known) unsigned 32 bit register (such as heatmeter) by dumping the content of the message?

Please note that this applies to type 106. For type 104, your code and mine are equal and use LSB order. However, currently I have no 32 bit register in LOG.SET so I cannot test this with actual data.

1
  •  Becker
  •   Gold-Award
5.6.2020  (#426)
ich versteh zwar nur Bahnhof aber nach einem Neustart des RPi funktionierten gestern Abend jedenfalls wieder die WW WW [Warmwasser] Sensoren, dauert jedoch 1min bis die aktualisiert werden.
Verdichterleistung muss ich heute schauen.

1
  •  JanRi
  •   Gold-Award
5.6.2020  (#427)
Regarding word swap:

I figured out that register 48852 is responsible for that (just looked into the json-file). It reads 1 in my case but I never configured that in any direction.

Have you set this to 0 explicitly or do you also rely on the default setting?

The explaination in F1155.json tells:

"If set; swapping the words in 32-bit variables when value requested via ''read holding register'' command"

I interpret that this applies to type 106 messages only.

Therefore, my code relies on 1 here and yours on 0.

I just tested this with register 44300 and my code (little endian, so byte0 | byte1<<8 | byte2 << 16 | byte 3 << 24) gave the correct value of 19095.8 for wordswap == 1 and it gave 392468889.8 for wordswap==0.

3924688898 is 2 + 0*2^8 + 238*2^16 + 233*2^24

Therefore, reading it as byte2 | byte3<<8 | byte0 << 16 | byte 1 << 24 (e.g., your code) is perfectly correct.

Therefore, word swap is really the key.

The first conclusion is: The code should request this register and set in in accordance to the decoder. So my code has to make sure it is 1 and your code has to make sure that it is 0.

At least this is a solution as long as we do not have other devices such as RMU40 on the bus. With such devices, we have to use their setting. 

Therefore, the second and better conclusion is: Our decoder should read that register and decode in the corresponding way - so your way for 0 and my way for 1. This way, we are completely independent from this setting on the heat pump.

1
  •  JanRi
  •   Gold-Award
5.6.2020  (#428)

zitat..
Becker schrieb: ich versteh zwar nur Bahnhof aber nach einem Neustart des RPi funktionierten gestern Abend jedenfalls wieder die WW WW [Warmwasser] Sensoren, dauert jedoch 1min bis die aktualisiert werden.

 Das ist klar. Wenn du 30 Werte abfragst, dann ist die Aktualisierungsrate etwa 1 pro Minute. Das ist ja gerade der Trick mit den LOG.SET-Registern.

Ich habe das so gemacht, dass alles, wo ich schnelle Änderungen sehen will, in LOG.SET steht und der Rest "normal" gemacht wird. Bei mir muss ich das explizit abfragen, aber nibepi macht das ja automatisch.


1
  •  chrismo
  •   Gold-Award
5.6.2020  (#429)

zitat..
JanRi schrieb: I figured out that register 48852 is responsible for that (just looked into the json-file). It reads 1 in my case but I never configured that in any direction.

I'd just like to confirm that word swap=1 is the default option. You could change it in the advanced settings menu (5.3.11 "Enable Word Swap") or via the mentioned register but actually it would be better to keep it as it is and decode messages accordingly.


1
  •  nibepi
5.6.2020  (#430)

zitat..
JanRi schrieb: The first conclusion is: The code should request this register and set in in accordance to the decoder. So my code has to make sure it is 1 and your code has to make sure that it is 0.

 Then I understand the situation, because I have Word swap at 0.
Actually NibePi backend.js send an 0 message to that register at startup. In your version it was probably not implemented yet. But Becker should have it. Just to make sure the user has a known Word swap setting. 
Anyhow anyone running the NibePi 1.1 clean image should not have any issues with the data translation.
The best way as you say would probably be to check the Word swap setting and then decode accordingly to that. 


1
  •  JanRi
  •   Gold-Award
5.6.2020  (#431)

zitat..
nibepi schrieb: Anyhow anyone running the NibePi 1.1 clean image should not have any issues with the data translation.

 Except there is some other accessory that demands 1.


zitat..
nibepi schrieb: The best way as you say would probably be to check the Word swap setting and then decode accordingly to that. 


Yes. Therefore, I will adapt my code that way. At the moment it is for me only, but who knows and there is always the risk of just forgetting this issue...


zitat..
nibepi schrieb: In your version it was probably not implemented yet.


Thats true because I analyzed all write accesses in order to understand how it works. My current UDP-MQTT adapter only implements the very basic features. It even skips the range check for certain registers (that is very useful for minimum heat medium pump speed as this can be set lower than 50%).




1
  •  nibepi
6.6.2020  (#432)

zitat..
JanRi schrieb: Except there is some other accessory that demands 1.

 What other accessory? My understanding was that this was a modbus setting. 


1
  •  JanRi
  •   Gold-Award
6.6.2020  (#433)

zitat..
Becker schrieb: 43375",compr. in power mean","info":"Mean power delivered from the inverter to the compressor. Mean is calculated every 10 seconds."
Durchschnittliche Leistung ?

Jedenfalls ist der letzte Wert immer höher und passt ganz gut zu dem gemessenen Wert von meinen Eltako Zähler.

Ich teste das gerade beim WW WW [Warmwasser]-Machen.

Der gelieferte Wert scheint in 10W-Schritten zu sein - kannst du das bestätigen?

Mein Smartmeter sagt 662,8W, das Register sagt 65 - das spricht sehr für Faktor 10.


1
  •  Becker
  •   Gold-Award
6.6.2020  (#434)
genau *10. Damit kommt man auf einen eingermaßen genauen, minimal verbesserten live COP.
Der Phasenstrom hat den Faktor /1000.

Was hat es eigentlich mit dem word swap auf sich? Versteh nur Bahnhof.

Alle Werte werden wieder angezeigt bei mir (nach einem Neustart des Pi).

1
  •  Brombaer
  •   Silber-Award
6.6.2020  (#435)

zitat..
Becker schrieb: Was hat es eigentlich mit dem word swap auf sich? Versteh nur Bahnhof.

Das ist technische Computerinterna, musst Dich nicht drum kümmern.


1
  •  JanRi
  •   Gold-Award
6.6.2020  (#436)

zitat..
Becker schrieb: Was hat es eigentlich mit dem word swap auf sich? Versteh nur Bahnhof.

Die Frage ist, wie man in der Antwort auf eine Einzelanfrage einen 32-Bit-Wert überträgt. Ein 32-Bit-Wert besteht aus 4 Byte, die man als A B C D lesen könnte. Da steckt dann eine 32bittige Zahl drin, wobei A das höchstwertige Stück ist und D das niederwertigste. Im Dezimalsystem könnte man sagen, dass A die Tausender sind, B die Hunderter usw.

Um sowas zu übertragen, gibt es Big Endian und Little Endian. Big Endian übertragt A B C D. Little Endian überträgt D C B A.

Um die Sache noch mehr zu verwirren: Nibe setzt hier auf ein 16-Bit-Konzept, was die Sache noch mehr vermischt. Die Sammelwerte (LOG.SET) senden sie Little Endian, aber bei den Einzelantworten (alles andere) gibt es zwei Optionen:

Word Swap auf 0:

B A D C

Word Swap auf 1:

D C B A

Es vertauscht quasi die beiden 16 Bit-Hälften, auch als "Wort" bezeichnet.

Da NibePi das selbst korrekt einstellt, führt es nur zu Problemen, wenn du bei laufenden NibePi "Word Swap" an der WPWP [Wärmepumpe] auf 1 stellst. NibePi erwartet 0, mein Code erwartet 1, aber ich werde noch so umbauen, dass der Code abfragt und dann das richtige macht.


1
  •  Yogi43
7.6.2020  (#437)
NibeGW  benötigt auch WordSwap = 1. Ich konnte es gestern beobachten, nachdem ich alle sich langsam verändernden Werte wie z.B. Energie und Starts aus der LOG.SET rausgenommen habe. Danach hatte ich sehr große Werte die sich durch das o.g. Verhalten erklären lassen. Mit Word Swap = 1 waren die Werte wieder korrekt. Nibepi setzt standardmäßig WordSwap =0 über Register 48852.

1
  •  JanRi
  •   Gold-Award
7.6.2020  (#438)

zitat..
Yogi43 schrieb: NibeGW  benötigt auch WordSwap = 1

Nein. NibeGW braucht gar nichts an der Stelle. NibeGW schickt einfach nur die bekommenen Pakete 1:1 per UDP weiter. NibeGW dekodiert sie dabei in keiner Weise.


zitat..
Yogi43 schrieb: Danach hatte ich sehr große Werte die sich durch das o.g. Verhalten erklären lassen.


Genau... weil OpenHAB oder was auch immer die UDP-Pakete von NibeGW bekommt, WordSwap=1 voraussetzt. Das scheint auch der Standard zu sein bei Nibe.

Ist bei mir genauso: Mit Wordswap=1 funktioniert alles, mit WordSwap=0 nicht mehr. Wenn ich den Dekoder aber entsprechend anpasse, dann geht es natürlich wieder. Darum ja der Vorschlag, dass der dekodierende Teil (bei NibePi ist der eingebaut, bei allen Konstruktionen, die auf NibeGW aufsetzen, ist es nicht NibeGW, sondern die "andere" Seite) das Word-Swap-Register abfragt und den Dekoder dann passend konfiguriert. Ist letztlich an zwei Stellen ein If mehr + die Abfrage. Dann ist es vollkommen egal, wie das auf Seiten der WPWP [Wärmepumpe] eingestellt ist.

Die Werte, die per LOG.SET kommen, sind grundsätzlich LSB. Mit Word-Swap = 1 dekodiert man also die selbst angefragten Register (fast) genauso wie die aus LOG.SET, mit WordSwap=0 muss man in der anderen Reihenfolge auswerten.


1
  •  Yogi43
7.6.2020  (#439)

zitat..
JanRi schrieb: Nein. NibeGW braucht gar nichts an der Stelle. NibeGW schickt einfach nur die bekommenen Pakete 1:1 per UDP weiter. NibeGW dekodiert sie dabei in keiner Weise.


Klar, Du hast Recht - die Auswertung findet natürlich im Binding von openHAB statt.

1
  •  Yogi43
10.6.2020  (#440)
So, endlich habe ich den Prodino MKR bekommen. Vielen Dank noch einmal an @­chrismo für die Bereitstellung des an den Prodíno MKR angepassten Codes. Parameter im Code angepasst - aufgespielt - läuft!
 

2020/2020061092277.jpg

1
  •  nibepi
12.7.2020  (#441)
Right now I'm adapting the code to work with Nibe S series and also make it compatible with NibeGW, making it more adaptable. 
My goal is to release one or two docker images. One with a very simple nibepi image just forwarding to mqtt. With one config file for all settings.
And another image with the whole nibepi setup, backend and frontend.

Both of them compatible with S series and NibeGW.

2


Beitrag schreiben oder Werbung ausblenden?
Einloggen

 Kostenlos registrieren [Mehr Infos]


next