[APP][Pro] Modbus

I tested with register 40233 and it’s returning 100%:

grafik

So it seems it’s not the correct register for yoour inverter?

Do you get correct values for other registers like voltage?

Thanks for all that Ronny. I ve just woken up so haven’t absorbed it all yet but just what I needed. And it confirms my doubt, I don’t have the correct register map yet.
Really appreciate the time you spent. I imagine I will take many days now to track down the right document.

2 Likes

Hi RonnyW,

thanks. Looks like with test version 0.6.0 it’s working again for me with Float32. Only String is still not working (but was working before). But as I read the string registers only for testing that is fine for me right now.

Hi,
you are right. After using size dependent on type, the STRING was only read with 1 register.
I just made a quick fix: test version 0.6.1. String should be read again with the given size.

Perfect. String now works again with 0.6.1 :slight_smile: Thanks for the very quick fix :slight_smile:

Ronny, guess what! I have found my problem. My Inverter was still set to Float. I did change it before I started all this but I couldn’t have saved it properly. So I assumed it was OK. Yesterday reading my way through the Data Manager doc I went and read 40070 and it read 111. Not right!

Sorry for all the hassle when it was just down to my error.

I still only get 2 characters.
Screenshot 2024-03-26 at 9.32.34 am

All working now. Thanks again.

Hi Ronny,
I checked my Modbusflow with the Tablet. The data aquired from my Fenecon Solar Sytem (Fems) look good. Your LE seams to work.

Thanks
Volker

1 Like

You got this working? I have an Acrel R10 power meter laying around, would like to know if i can convert modbus rtu to modbus tcp and read the registers.

Hi @RonnyW,
I have (at least) one register in my heat pump that actually uses four bytes. Don’t ask me why NIBE decided to use four bytes, because the valid range is -7590 to +1000, which perfectly fits into one register.

Reading it is no problem whatsoever, because the upper two bytes are pretty much useless (either 00 00 or FF FF) and just interpreting the lower two bytes gives one the correct value. (I verified this with a Modbus scanner. All four bytes, i.e. two consecutive registers, are used for the value, but the lower two bytes are sufficient)

But writing is impossible currently, because the heat pump expects all four bytes to be sent. If only two are written it resets the whole register (all four bytes) to zero. For this one has to use function code 16 (Write multiple holding registers) to update all two registers at once, whereby the first register contains the lower two bytes and the second register contains the upper two bytes, e.g. F5 EA FF FF is -2582 (or FF FF F5 EA in regular hex).

Would it be possible to implement this? In my opinion this could be integrated in the existing flow card for writing, we would just need additional types like e.g. “INT32 (low to high)” for signed 32-bit integers, where the lower two bytes come before the upper to bytes.

One more question: what what you suggest would be the correct way to read this register, i.e. read all four bytes. If I use “Read holding register with size 2”, no matter what type I select, I don’t get a valid value. I guess the problem is the bit order here, as it is 8-15/0-7/24-31/16-23, i.e. byte order 1-0-3-2.

Short version now… I will check it later in detail.

  1. 4B should be an INT32. You can use this type to read. If the last 2bytes are 00 00, then it seems the device uses little endian. In this case, you can try INT32LE.

  2. For writing I only added type I was able to check.
    I can add INT32 BE/LE

1 Like

Neither INT32 nor INT32LE give correct values if I read with size=2, i.e. all four bytes.

Would be great, however I suggest first solving the issue with correctly interpreting all four bytes when reading. I strongly suspect that the current INT32(LE) expects a different byte order than what NIBE returns here. And when it comes to writing, I’m not sure if you already use function code 16 if writing more than two bytes at once.

As always: thanks for your work!

Using another type than String, the lenth is set internally to the matching size. You can’t overwrite it in your flow card (check the hints in the card).

I only know LE or BE, and both is added and should work (if I remember tight, someone tested INT32LE already).
Do you have a type definition for this register?

For Writing, the generic function is used with defining the lenth for writing multiple registers at once. I think that’s the function cond 16. But I didn’t check the internal code.
I can only test INT16 values. Using INT16, it writes 2 bytes (1 register).
For INT32, I would write 4 bytes (2 registers). Should work, I think :sweat_smile:

What I wrote was ambiguous. What I meant was: when reading that value with INT16, it works fine. When reading it with INT32, it doesn’t. Just for reading it doesn’t matter, because all valid values fit into 16 bit.

It’s INT32 with its bytes split over two registers. Each register itself is big endian, but the first register contains the lower two bytes and the second the upper two bytes, i.e. byte order of all four bytes is 1-0-3-2.

Then the only issue remaining would be the byte order.

I just wanted to try to write the value 4163960831 to the register, which is F8 30 FF FF. That then should be understood by the heat pump as FF FF F8 30 or -2000. If you add just the types UINT32BE and INT32BE, I could try this.

Do you have any possibility to see what bytes are actually written? Would make bug hunting much easier.

Don’t ask me why I didn’t think of this earlier: I can verify the different byte order of course also by reading the register, not only writing. So I read the register as INT32 and got -283377665, which is EF 1B FF FF.

Rearranging this to FF FF EF 1B (i.e. last two bytes to the front, not changing the byte order within each register) and converting back to decimal gives -4325, which is in fact the correct value.

So we need some option to specify the register order in case the value is stored in multiple registers.

New test version 0.7.0:

  • Added new Types: little-endian (LE) for 16bit words. Use this type if the device is using a 16bit word (1 register) type LE variant.
    Example:
    Value as HEX: 01 02 03 04 (INT32, 4 bytes, 2 registers)
    Device uses this value: 03 04 01 02 (LE for 2 byte pairs)
  • Added type BYTE to read the register content as byte string (for test purpose).
  • Added token for “write register” flow card returning the written data as byte string (for test purpose).

@CaptainVoni FYI
You can check the register content as byte string now. And you can try the new type for reading LE values in 16bit pairs.
Writing other types can be added if reading is successful.

1 Like

I tried to read the register with BYTE and size 2 and it returned F8 B8 FF FF, which corresponds to the correct value FF FF F8 B8 or -1864. When using the type “INT32-LE (16-bit Word LE)” I also get the correct value. So reading now works also when interpreting both registers together, great!

New test version 0.7.1:

  • Added new types to write register flow card.
  • Added test mode to write register flow card to check the byte sequence before using live mode.

@CaptainVoni FYI. Hope it’s working :slight_smile:

1 Like