Needing help with emonhub configuration for a modbus RS485 RTU connection to Solax X1 Gen.4 hybrid inverter

Hello everyone,

Although I signed up to the openenergymonitor forum in September 2023, and with much interest and great benefit have followed the various discussions both before and after that time, this is my first contribution here. Sorry if it does not (yet) follow standard layout or terminology.

My interest in openenergymonitor and their emoncms system stems from planning and installing solar PV and ASHP systems at my house in spring/summer of 2023. I wanted to collect & monitor the systems’ running data in-house, and being an old time Debian Linux user (and with a Raspberry pi3 to spare) I decided to use emoncms for this.

My installations are (briefly told): Vaillant Aerotherm Plus 7kW, and Solax X1 Gen.4 3.7D hybrid inverter with Solax Triple Power batteries, 3 x 5.8kWh.

I put the (Raspbian 11 based) emoncms Nov.2022 image onto a (industrial grade) microSD card for my pi3, and communicate with the OS over a wifi connection (via ssh).

I have been collecting data (into emoncms) from the heatpump (through a Sontex Supercal 5S heatmeter and SM120 power meter) since the beginning, and more recently also from the heatpump ebus system directly (using the elecrow eBUS Adapter Shield C6).

Now I am trying to retrieve data from the Solax inverter via its RJ45 ‘COM/LCD’ port (RS485 modbus) into my pi3 emoncms using a modbus-USB converter cable (the FTDI USB-RS485-WE-1800-BT), as the inverter and the pi3 are just 1.5 metres apart.
But so far without complete success, and this is where I need help.

I am not a programmer, but here is what I have tried and where I’ve got to in this process:

To check the inverter-pi3 connection I installed ‘mbpoll’ (from the raspbian 11 repository), and tested (after a few failed attempts) with the following command string:

mbpoll -P none -a 1 -b 19200 -l 10000 -1 -t 3 -r 1 -c 10 /dev/ttyUSB1

which gave the following output, which shows that the connection as such is OK:

Protocol configuration: Modbus RTU
Slave configuration...: address = [1]
                        start reference = 1, count = 10
Communication.........: /dev/ttyUSB1,  19200-8N1
                        t/o 1.00 s, poll rate 10000 ms
Data type.............: 16-bit register, input register table

-- Polling slave 1...
[1]: 2401
[2]: 21
[3]: 493
[4]: 1544
[5]: 1217
[6]: 26
[7]: 27
[8]: 5011
[9]: 38
[10]: 2
......

These are the first 10 registers in the table ‘0x04: Read Input Register’ of Solax’ document
“Energy Storage Inverter Modbus TCP&RTU Communications Protocols v.3.36”
(the file is named “Hybrid X1&X3-G4 ModbusTCP&RTU V3.36-English_240611.pdf”),
and include registers I want to access.

Inspired by the configuration for SM120 in /etc/emoncms/emoncms.conf, I hazarded the following for a Solax configuration:

   [[SolaxX1G4]]
      Type = EmonHubMinimalModbusInterfacer
       [[[init_settings]]]
           device = /dev/ttyUSB1
           baud = 19200
           parity = none
           datatype = int
      [[[runtimesettings]]]
           pubchannels = ToEmonCMS,
           read_interval = 30
           nodename = solaxX1G4
           # prefix = solax_
           [[[[meters]]]]
                [[[[[inverter]]]]]
                      address = 1
                      registers = 0,1,2,3,4,5,6,9,10,11,22,24,28,32,70,72,80
                      names = GridVoltage,GridCurrent,GridPower,PV1Voltage,PV2Voltage,PV1Current,PV2Current,RunMODE,PowerDC1,PowerDC2,BatteryPowerCharge,BatteryTemp,BatterySOC,BatteryOutputEnergyToday,FeedInPower,FeedInTotal,DailyYield
                      scales = 0.1,0.1,1,0.1,0.1,0.1,0.1,1,1,1,1,1,0.01,0.1,1,1,0.1
                      precision = 2,3,1,2,2,3,3,1,1,1,1,1,1,1,1,1,1

This pulls Solax data into emoncms OK, but not the values I want.

When running the command string:

mbpoll -P none -a 1 -b 19200 -l 10000 -1 -t 4 -r 1 -c 10 /dev/ttyUSB1 (so -t 4 rather than -t 3 used above)

output is:

Protocol configuration: Modbus RTU
Slave configuration...: address = [1]
                        start reference = 1, count = 10
Communication.........: /dev/ttyUSB1,      19200-8N1
                        t/o 1.00 s, poll rate 10000 ms
Data type.............: 16-bit register, output (holding) register table

-- Polling slave 1...
[1]: 	18484
[2]: 	13111
[3]: 	12865
[4]: 	18743
[5]: 	13363
[6]: 	13617
[7]: 	13620
[8]: 	21359
[9]: 	27745
[10]: 	30752
......

These data are the same as those received into emoncms through my emonhub [[SolaxX1G4]] configuration above, taken from what mbpoll calls the ‘output (holding) register table’.
If this is the same as Solax’ document ‘0x03: Read Holding Register’ table, the first registers should give the inverter serial number (SN), but the figures bear no resemblance to the actual serial number is has, and anyway are not the data I want.

And from here I don’t know how to proceed.
So if anyone can suggest a (simple) way to change the ‘registers’ in above Solax configuration script to point to the Solax 0x04 Input Registers, I would be very thankful. Any other suggestions for a solution would also be welcome. Although if it means heavy editing of the
/opt/openenergymonitor/emonhub/src/interfacers/EmonHubMinimalModbusInterfacer.py script,
it would probably be beyond me.

Thanks,

LB

Hi @leiv - I’m not an expert in Modbus, but a read of the linked documentation suggests the issue lies in the addressing. The Solax is arranged in pages, so I think you need to include the page as part of the address. Shift the page address, 0x04 here, left by 8 bits, followed by the register. For example (decimals that you’ll need for the interfacer configuration, hex first as it’s easier to deal with the shifts :slight_smile:):

  • GridVoltage @ 0 → 0x400 (1024)
  • GridCurrent @ 1 → 0x401 (1025)
  • GridPower @ 2 → 0x402 (1026)

This is from a very quick skim of the minimalmodbus module, I think it’s little Endian so sends the lower byte first. The relevant diagram in the Solax documentation is here:

Give that a try and let us know.

Apologies @leiv - the values I gave were only 4 bit shifted before :melting_face: I’ve corrected them with updated values in the original post.

Hi @awjlogan,

Thank you so much for your quick and very helpful input. My understanding of memory addressing is nearly zero, but I entered the figures you gave me into my ‘SolaxX1G4’ configuration’s registers string. They did not produce the hoped-for outcome but spurred me to play around with other values, and in the end this series worked just right:

registers = 596,597,598,599,600,601,602,605,606,607,618,620,624,628,666,668,676

And as decimal 596 is 254 hex, what does that tell you about how much shift of page address there actually was?

In any case, thanks again! I’ve been hoping for a solution to this for several months…

:grinning_face:

1 Like

Hi @leiv - well, glad to put you on the right track and well done for finding the right addresses. 0x254 bears no resemblance to 0x4 shifted as it’s binary 0b1010100 from 0b100 so I can’t say I know why it’s worked! Time for a bit of code investigation here, but happy to help.

In case anyone else is interested in my emonhub configuration for a Solax X1 Gen. 4 inverter, when using a modbus RS485 RTU connection, here is the working end result, including a couple of changes in the ‘scales’ string:

[[SolaxX1G4]]
      Type = EmonHubMinimalModbusInterfacer
       [[[init_settings]]]
           device = /dev/ttyUSB1
           baud = 19200
           parity = none
           datatype = int
      [[[runtimesettings]]]
           pubchannels = ToEmonCMS,
           read_interval = 30
           nodename = solaxX1G4
           # prefix = solax_
           [[[[meters]]]]
                [[[[[inverter]]]]]
                      address = 1
                      registers = 596,597,598,599,600,601,602,605,606,607,618,620,624,628,666,668,676
                      names = GridVoltage,GridCurrent,GridPower,PV1Voltage,PV2Voltage,PV1Current,PV2Current,RunMODE,PowerDC1,PowerDC2,BatteryPowerCharge,BatteryTemp,BatterySOC,BatteryOutputEnergyToday,FeedInPower,FeedInTotal,DailyYield
                      scales = 0.1,0.1,1,0.1,0.1,0.1,0.1,1,1,1,1,1,1,0.1,1,0.1,0.1
                      precision = 2,3,1,2,2,3,3,1,1,1,1,1,1,1,1,1,1

As for the hardware side, the modbus-USB interface cable connects to terminals 4 and 5 of the RJ45 connector.

1 Like