« Heizung, Lüftung, Klima  |

DIY Alternative zu Nibe Modbus Modul

Teilen: facebook    whatsapp    email
 
 1  2 ... 3 ... 7  8  9  10 ... 11 ... 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

  •  chrismo
  •   Gold-Award
2.12.2019  (#161)

zitat..
nibepi schrieb: That cant be 5C. (Not sure why but that how it is).

That was apparently a design choice. I guess the Nibe designers wanted to keep complexity of the parser low. And ensuring that there is no single 5c helps here. You have to keep in mind that the only intended parser is part of the Modbus40 module.


1
  •  nibepi
2.12.2019  (#162)
Now I have updated my nibepi npm package, a working version should be 1.0.3 (Yeah it's confusing versions).
It was a huge error from my side and the nibepi has not ACKed a lot of messages so this will improve alot.

1
  •  JanRi
  •   Gold-Award
2.12.2019  (#163)
Hi,

after some problems with npm, it runs now. I put it on the two non-isolated cores without nice or taskset in order to see what happens.

As I hoped it was a drop-in replacement. Due to MQTT there was even no need to stop my client emoji

I scanned through the sources... can you give me a hint I can disable/remove the periodic alarm resetting? I have found 45171 only once in the sources but I have not spend much time on that. 

Now lets see how stable it runs...

Writing was also sucessful, even reading a value containing 5C. First, I thought writing failed but then I remembered the difference in interface... so 34,8C is 34.8 in your interface while it is 348 in mine (still not changed in my code).

Greetings,

Jan

1
  •  nibepi
2.12.2019  (#164)

zitat..
JanRi schrieb: Hi,

after some problems with npm, it runs now. I put it on the two non-isolated cores without nice or taskset in order to see what happens.

As I hoped it was a drop-in replacement. Due to MQTT there was even no need to stop my client

I scanned through the sources... can you give me a hint I can disable/remove the periodic alarm resetting? I have found 45171 only once in the sources but I have not spend much time on that. 

Now lets see how stable it runs...

Writing was also sucessful, even reading a value containing 5C. First, I thought writing failed but then I remembered the difference in interface... so 34,8C is 34.8 in your interface while it is 348 in mine (still not changed in my code).

Greetings,

Jan

Hope it works out, comment out line 259.
sendQueue.push([192,107,6,115,176,1,0,0,0,111])
 



1
  •  nibepi
2.12.2019  (#165)
Now I get a checksum error from buffer 92,0,32,106,7,89,156,215,92,92,0,95,92

(Sorry its decimal form)
The checksum is 5C (92). So I guess it's just a minor issue with the chksum check.

This is from openhab binding.
"// if checksum is 0x5C (start character), heat pump seems to send 0xC5 checksum"

But the heatpump sends 5C...
Im gonna do some testing and investigate further.

1
  •  JanRi
  •   Gold-Award
2.12.2019  (#166)
Hi,

zitat..
JanRi schrieb: can you give me a hint I can disable/remove the periodic alarm resetting?


Found it:

sendQueue.push([192,107,6,115,176,1,0,0,0,111])

I found another bug: Your 32 bit data types are still wrong:

s32 wrong in all cases. Correct is: byte1 | byte2<<8 | byte3 <<16 | byte4 <<24
If >=2^31 then substract 2^32

Your code gives negative numbers for small values ( byte 3 and 4 are zero) and completely wrong numbers for everything larger.

u32 is correct for the "else"-case (thats the only one I tested). The "then" case just adds two 16 bit numbers - this is not correct.
Here it is just byte1 | byte2<<8 | byte3 <<16 | byte4 <<24 as in "else" case.

byte1...4 are the bytes you already use.

Greetings,

Jan

1
  •  nibepi
2.12.2019  (#167)

zitat..
JanRi schrieb: Hi,
__________________
Im Beitrag zitiert von JanRi: can you give me a hint I can disable/remove the periodic alarm resetting?

Found it:

sendQueue.push([192,107,6,115,176,1,0,0,0,111])

I found another bug: Your 32 bit data types are still wrong:

s32 wrong in all cases. Correct is: byte1 | byte2<<8 | byte3 <<16 | byte4 <<24
If >=2^31 then substract 2^32

Your code gives negative numbers for small values ( byte 3 and 4 are zero) and completely wrong numbers for everything larger.

u32 is correct for the "else"-case (thats the only one I tested). The "then" case just adds two 16 bit numbers - this is not correct.
Here it is just byte1 | byte2<<8 | byte3 <<16 | byte4 <<24 as in "else" case.

byte1...4 are the bytes you already use.

Greetings,

Jan

Thank you, im gonna check it out. Still learning here.

1
  •  JanRi
  •   Gold-Award
2.12.2019  (#168)
Hi,

zitat..
nibepi schrieb: But the heatpump sends 5C...
Im gonna do some testing and investigate further.

 Hmmm... your code should accept that, right?

if((msgChecksum==calcChecksum) || (msgChecksum==0xC5 && calcChecksum==0x5C))

-> in this case the left side is true so everything should be fine. 

So there seems to be some problem some.

I let the code run until I go to bed... over night I switch back to nibegw because if I also run into such a problem without seeing it, ot could produce a large amount of alarms.

So far, everything runs fine, even the client based alarm reset at start-up.

Greetings,

Jan


1
  •  chrismo
  •   Gold-Award
2.12.2019  (#169)

zitat..
nibepi schrieb: This is from openhab binding.
"// if checksum is 0x5C (start character), heat pump seems to send 0xC5 checksum"

But the heatpump sends 5C...
Im gonna do some testing and investigate further.


I just checked the code and the openHAB binding is actually allowing both, 5c and c5 for a calculated checksum of c5.

Actually, it makes no sense to sometimes send c5 and then 5c on other occassions... but who knows what the Nibe guys wanted to do here, maybe just make it harder to reverse engineer the protocol emoji

 

1
  •  JanRi
  •   Gold-Award
2.12.2019  (#170)
Hi,

zitat..
chrismo schrieb: 5c and c5 for a calculated checksum of c5.

 The other way around: 5c or c5 for a calculated checksum of 5c.

The same does the nibepi code as posted above... if calcChecksum is 5c, it accepts 5c and c5.

Greetings,

Jan


1
  •  chrismo
  •   Gold-Award
2.12.2019  (#171)
Sorry, my fault. That's what I actually meant. Mixed up the order. Just like the Nibe heat pump sometimes emoji

1
  •  JanRi
  •   Gold-Award
2.12.2019  (#172)
Maybe this is just different for different FW versions or heat pumps? Therefore, both is possible.

With respect to the messages itself: In appr. 10000 messages type 104 and 106 that I got on UDP from nibegw there was no message the length value in the message (byte 4) differed from the real length. I will continue monitoring that.

With respect to nibegw: Until I started testing 1.1 of nibepi, it ran for 36 hours with no alarm at all. Now it runs again... nibepi will be further tested when I'm near the computer and the heat pump at least for a few hours (so tomorrow, I guess).

@NibePi: If you need a bunch of messages from F1155 for testing or analyzing, just let me know. The current count is 17000... with 10000 of them with extra information on length for easy searching. Tomorrow these numbers will be much greater as there are 1860...1866 messages per hour.

Greetings,

Jan

1
  •  JanRi
  •   Gold-Award
2.12.2019  (#173)
Hi,

regarding the checksum problem: In your de-escaping function you are going through the whole message including checksum. If the checksum contains 0x5c, it gets removed. Later, this gives a wrong length in decoding because you iterate to length-2 .

Therefore, my de-escaper stops earlier (before the checksum) and it additionally checks if there are two 0x5c one after the other (just to be safe...). For performance reasons, it starts at byte 5 - before this there cannot be 0x5c (except 0, but this you also skip).

Greetings,

Jan

1
  •  chrismo
  •   Gold-Award
2.12.2019  (#174)

zitat..
JanRi schrieb: @NibePi: If you need a bunch of messages from F1155 for testing or analyzing, just let me know.

@NibePi If you'd need some test messages I could also provide you some openHAB logs which provide the raw byte message and the decoded register information, such as:

2019-12-02 22:42:11.526 [TRACE] [internal.handler.NibeHeatPumpHandler] - Received raw data: 5C00206850449C00004F9C4400509C1B004E9CA2014D9CB801489C27014C9CFF00ADA9320080A8AE0198A9890199A90000EC9F36EFED9FFFFF0AADA5540BAD000012AD874C13AD0000889C700001A828014EA81E0082
2019-12-02 22:42:11.529 [DEBUG] [internal.handler.NibeHeatPumpHandler] - Received message: Message type = MODBUS_DATA_READ_OUT_MSG, Values: [{Coil address = 40004, Value = 0}, {Coil address = 40015, Value = 68}, {Coil address = 40016, Value = 27}, {Coil address = 40014, Value = 418}, {Coil address = 40013, Value = 440}, {Coil address = 40008, Value = 295}, {Coil address = 40012, Value = 255}, {Coil address = 43437, Value = 50}, {Coil address = 43136, Value = 430}, {Coil address = 43416, Value = 393}, {Coil address = 43417, Value = 0}, {Coil address = 40940, Value = 61238}, {Coil address = 40941, Value = 65535}, {Coil address = 44298, Value = 21669}, {Coil address = 44299, Value = 0}, {Coil address = 44306, Value = 19591}, {Coil address = 44307, Value = 0}, {Coil address = 40072, Value = 112}, {Coil address = 43009, Value = 296}, {Coil address = 43086, Value = 30}]

However, I'd need to increase the verbosity level of the logger first to collect these messages. Thus, it would take some time to have a large example set (I think the heat pump reports them every 2s, so it generates ~1800 msgs/hour).

1
  •  nibepi
2.12.2019  (#175)
Thank you for offering data, right now I dont need more than I can provide from my own.
I did some testing with my checksum error.
Original: [92,0,32,106,7,89,156,215,92,92,0,95,92]
The check sum calculation for above gives 0 as checksum.
``
msgChecksum = data[data[4]+5];
var calcChecksum = 0;
for(i = 2; i < (data[4] + 5); i++) {
calcChecksum ^= data;
}``

When decoding the data it seems like the values really are corrupted. 23767 is the calculated value. The same value as you get if the sensor is not connected. 

1
  •  nibepi
3.12.2019  (#176)

zitat..

I found another bug: Your 32 bit data types are still wrong:

 Thank you I've adjusted according to your info and it works better now.
I'm gonna check in tomorrow morning to see if there are some errors during the night.


1
  •  nibepi
3.12.2019  (#177)
I am getting some checksum errors. Seems to happend when it changes from hotwater to heat and vice versa.

Error: Checksum Error: 92,0,32,106,7,89,156,212,92,92,0,197,92
The checksum calculation is wrong, and the values decoded are wrong too. I think it's a correct checksum error because of cabling/interference.
Since I send a NACK the heatpump gets the correct answer and should not go into alarm mode, so I guess this is normal error handling.

1
  •  nibepi
3.12.2019  (#178)
Some more errors during the night.
Error: Checksum Error: 92,0,32,104,81,147,156,33,92,92,0,255,255,0,0,143,156,23,0,255,255,0,0,201,175,184,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,224,92,0,32,238,0,206,92

This is handled with an NACK, so the heatpump sends it again, then it fails again. And the same thing goes several times. If I respond with ACK Im sure it dosent repeat it self.

The problem with this buffer is that it is short, so it also reads the next message and therfor misses to ACK/NACK one message. This is what eventually leads to modbus alarm.

These are errors that nibepi ignored before, so it's still 100 times better...

1
  •  JanRi
  •   Gold-Award
3.12.2019  (#179)
Hi,

zitat..
nibepi schrieb: Since I send a NACK the heatpump gets the correct answer and should not go into alarm mode, so I guess this is normal error handling.


I agree to that. Escpecially, as the sensor value is wrong, it might be the case that there is an additional check by the heat pump that figures out that there is a fault and shows this using the checksum. "Sensor glitches" I also saw in USB logs... so this might be a problem with cabling, connectors or electromagnetic influence on the sensor cable.

NACKing this is correct, I guess. If you look into the sources of nibegw.c, they do exactly the same and NACK such messages.

Furthermore, I believe that we have another protocol detail discovered here. You wondered why there is 0x5c in checksum, right? I just searched to my 25000+ log entries. There is NO checksum containing "0x5c" but there are 429 that contain 0xc5 in the checksum (so the other way around, as guessed for the protocol). I have not yet evaluated these checksums to figure out if it was really 0x5c or just 0xc5 but it is significant that 0x5c never occured.

Keep in mind that this comes from UDP - so there are ONLY messages with valid checksums. Everything else gets NACKed by nibegw and is NOT send on UDP. Conclusion: There is no valid message with a checksum containing 0x5c.

So the new guess is: If there is 0x5c in the checksum (and the checksum is wrong?) this indicates a message the heatpump "knows" something is wrong. Maybe in this case the first byte of the checksum field is some error code?

And there is more: You said that you got a (calculated) checksum of zero in one of these strange cases. In my log, there is no case with 0x0000 as checksum. 0x??00 and 0x00?? both occur, but never 0. Maybe this is due to having not enough messages (statistically, there are 65536 different checksum patterns possible... so we have to collect a comparable number of samples), but maybe this is just another unknown protocol detail.

Alltogether, I assume we can just ignore it. This happens rarely and just NACking should be fine (the same is done by nibegw). Furthermore, if this is really signalling an error, NACK should be the right thing to do.

I guess that the heat pump side of the connection has an error counter. This could work similar to the ones in CAN: If something bad happens, it gets increased. If a message was sucessfully ACKed by the receiver, it gets decreased. If a certain threshold is reached, actions are taken. Hence, a single NACK will do nothing but a certain number of consecutive NACK will likely force an alarm. This can be easily tested... just NACK everything and count the number of NACK until we get an alarm.

Greetings,

Jan

1
  •  nibepi
3.12.2019  (#180)

zitat..
JanRi schrieb: And there is more: You said that you got a (calculated) checksum of zero in one of these strange cases. In my log, there is no case with 0x0000 as checksum. 0x??00 and 0x00?? both occur, but never 0. Maybe this is due to having not enough messages (statistically, there are 65536 different checksum patterns possible... so we have to collect a comparable number of samples), but maybe this is just another unknown protocol detail.

Thanks for your respond, there might be something to it that when the heatpump knows something is wrong it's attentionally sends wrong chksum.

With the 0x00 checksum I mean that when I manually calculate the payload the result is 0x00, but the message that I receive is 0x5c.

I wonder how many errors nibegw encounters. Does it have an error log?


1
  •  JanRi
  •   Gold-Award
3.12.2019  (#181)
Hi,

we just cross-posted...

First, a small issue... your decodeMessage can be improved and simplified: For decoding 32bit, you differ between message length 80 and other. I think it would be better to distinguish between message type 104 (thats you have length 80) and 106 (the other). Message type 106 always send 4 data bytes one after the other while type 104 uses two 16 bit data fields, therefore, you have to skip the two bytes in between ( usually the second register number is contained).

zitat..
nibepi schrieb: 92,0,32,104,81,147,156,33,92,92,0,255,255,0,0,143,156,23,0,255,255,0,0,201,175,184,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0,224,92,0,32,238,0,206,92


Hmm... this contains start of next message: 92,0,32,238,0,206,92 -> this is type 238.


zitat..
nibepi schrieb: The problem with this buffer is that it is short, so it also reads the next message and therfor misses to ACK/NACK one message.


nibegw.c here tries to read up to 200 byte. Serial port delivers everything that is available. If it is too short, they seem to ignore that and continue with the next message (they compare data[4] with length of message). In this case, they do not start to read the next message as part of the old one - this happens in the next read call for the next message. Btw... that's why I never see a message with wrong length - nibegw does not forward them to UDP.

Why does your code starts getting the next message at all? There should be a delay in between and the serial read should only return the first message - everything else comes later. Or do you have a timing problem here in a way that the next message comes too short after the corrupted one that you read too much?

Other option would be hardware problem.

Does this really lead to an alarm? If yes, I would just try with nibegw for a similar amount of time. If this works, then it is software/timing, if it also leads to an alarm, it is a problem with the hardware.

I have no idea on the impact of garbage collection on that specific timing issue. node.js does a lot of garbage collection (just monitor its memory usage with "ps aux|grep node") so this might lead to a situation you miss the small delay between the two messages.

Maybe another approach for debugging this issue: If you add an option to the backend to read from UDP instead of serial (i.e., an nibegw-adapter), drop ACK/NACK and write to UDP instead of serial (as a replacement object for low level communication), you could try all your logic with nibegw as real-time unit. If this works perfectly, then it is timing in accessing the serial part from node.js.

I do the reading part that way (just the relevant parts):

var PORT = 9999;
var HOST = '192.168.1.2';  // your IP address, likely localhost for local nibegw
var dgram = require('dgram');
var server = dgram.createSocket('udp4');

server.bind(PORT, HOST);

server.on('message', function(message, remote) {
var data=Array.from(message);

if (data[3]===104 || data[3]==106){
decodeMessage(data);

}
});

decodeMessage is very similar to yours... so this is really simple.

Greetings,

Jan


1


Beitrag schreiben oder Werbung ausblenden?
Einloggen

 Kostenlos registrieren [Mehr Infos]


next