Reading CAN bus communication between Pylontech battery and Solis inverter

Starting with a new solar system last year, I wanted to have access to ‘real time’ performance data, and to ultimately be able to implement some degree of inverter automation and control. My Solis Hybrid inverter does have a very nice UI screen, and a data logging stick (when it works) does provide a rich source of current and historic performance data. However, there appears to be almost zero availability for end-user access and remote control for either the inverter or the battery.

As part of a very long and time-consuming project, I have spent many hours slogging through Google searches for information to help me. To provide something by way of a ‘thank you’ to the many who publicly document their efforts, here is my update on a project to ‘read the CAN bus’ into HA from a pylontech battery.

Warning:
Lithium batteries are potentially dangerous. Pylontech batteries have a Battery Management System (BMS) that provides information, control, but most importantly protection. Changing settings on the BMS could potentially result in disruption, permanent damage, battery fires, or worse. Reading the CAN bus is a passive listening approach – it does not write anything to either battery or inverter – however without the cable between battery and inverter, my inverter stops seeing the reported SOC, assumes that the battery is ‘flat’, and immediately starts full charge from grid. After a while, the battery would fill up, and as the BMS cannot communicate to the inverter and tell it to ‘stop’, the BMS would open the MOS gate charge switches and effectively blow a fuse to cut off the unwanted charge current. Net result – a (permanently) dead battery. Hence there is an element of risk, so don’t try this at home.

Background:
CAN bus is an often used means by which batteries talk to inverters. Mostly one-way, it allows the battery to ‘tell’ the inverter what to do. Information passed will include SOC%, current and voltage limits, and alarm information. CAN bus is a high-speed, small-packet comms protocol using two wires connected to anything that wants to communicate. Everything listens all the time, and talks when it wants to.

Hardware:
I went for the simple option and purchased an industrial CAN-ethernet converter. Less than £65 in the UK, this has two CAN ports (I only need one) and also an RS485 port, connects by cable to ethernet, and provides TCP – CAN (and RS485) conversion. Needs a 5v power supply, but I ‘borrowed’ this from another serial-ethernet converter I already had. See picture – CAN unit is on the left.

Wiring:
Taking a two-port ethernet face plate, I wired pins 4/5 (the blue/blue-white) across both sockets and then out to the CAN port on the converter. Existing patch cable from battery (to inverter) plugged into one socket, and another cable from other socket to inverter completes the connection. Termination resisters are already in the battery & inverter ends, so are not required at the converter connection.

Setup:
LAN access is via cable to Wi-Fi extender/powerline/ direct cable as required. I have a small router acting as a switch, wired into a powerline adapter back to my router. The unit needs a fixed IP address, which is done by first finding the unit on the network (DHCP to start) and then using the web setup page. I did not need to change the standard settings, but did need to note the port address of the TCP server end.

Converter:
The converter I use can take inbound TCP messages and push them out to CAN bus, or can listen on the CAN bus and capture messages to TCP. As there is no formal protocol as such, all broadcast CAN bus messages are noted but will only be sent out to TCP based on either reaching a given packet length or time out, either of which will trigger buffer out to TCP. CAN bus messages have variable length, but a nice feature of the converter I have is that it puts all buffered messages into a fixed length packet for TCP, and this makes decoding them simpler!

From converter to Node-RED:
Using Node-RED, I have a simple ‘tcp in’ node, setup: connected to the converter port/host IP, and set to output a stream, of buffer payloads. Simple!

Code:
For reasons of safety and confidentiality, I am not sharing either my code or the details of the message protocol. Untested (ie my) code should never be simply copied and run, and I respect potential commercial sensitivity. There is (at the time of writing this) a copy of the protocol as well as at least one informative article by an enthusiast out there on the web, and I am sure anyone can search for pylontech can bus protocol if they so choose… Otherwise, most of the useful data can be decoded by inspection.

Message format:
The master battery sends out 6 different message packets. Each one ends up in TCP as 13 bytes long, but altogether – hence I mostly see buffers of 78 bytes arriving. The other buffers seen are 13 bytes (a heartbeat reply message from the inverter) or something between, which is just a part filled or chopped off buffer at the start, so I ignore those.

Parse buffer:
On the converter I use, each 13 byte buffer block (one ‘standard length’ CAN bus message) consists of a length field (1 byte), the CAN bus frame ID (2 bytes at offset 3) and a data packet of 8 bytes (offset 5). I only need the frame ID and the data packet. After that, each frame type is then decoded to extract the data fields.

ID 0x355 is the message that holds the SOH and SOC, as 2 byte hex, so 100% SOH will typically show as 0x6400 unsigned integer, little endian, and the other 2 byes will be the SOC. Note that only half the 8 byte CAN data buffer is used here, a side effect of the converter putting variable length CAN messages into fixed length TCP packets.

I use node-red-contrib-buffer-parser to parse the buffer, and so it only takes a few nodes to process the buffer into the fields I want. Then I use the HA entity node to create a sensor and pass the values to HA. The key field I use is just the battery SOC, which is available from the inverter, however I also lift the BMS reported voltage and current and calculate the power from this, which I find can differ from the inverter reported ‘battery power’ value by up to 150 watts.

Practicalities:
Messages on the CAN bus run at one BMS update every second, and even with a basic ‘reply’ from the inverter I have not seen any problem with capturing and processing all the message. However, I don’t need most information so I have added a flow limit node to reduce updates to every 30 or 60 seconds for just the fields I want.

Conclusion:
Although there is very little information about CAN bus battery-inverter communication, I found this project simple and easy to complete, mainly due to using the converter unit I purchased. Overall, not necessarily that useful a project to do, however I now get SOC directly from the battery, and realising the importance of the CAN bus link between battery and inverter, I may at some point consider installing a watchdog on HA. Should the CAN link stop (ie SOC goes to undefined or 0) there exists a contact port on the Pylontech that could be used to shut down the battery. Emergency stop in an emergency!

2 Likes

Thanks for publishing such a great article. I’ll soon have a Pylontech battery and Solis inverter installed, so your detailed homework is very relevant to my set-up. Which CAN-Bus to Ethernet converter did you use? Googling seems to throw up numerous devices costing anything from £50 - £500.

Thanks for your positive feedback.

Of all the inverter/battery data connections, my CANbus has been the easiest and most reliable. Plus I get the key battery data straight from the battery. I trust the battery current/voltage/temperature/SOC figures more than those from my inverter, and they are updated every second!

I am using the USR-CANET200 device. I already had a USR serial adaptor which I like.

https://www.pusr.com/products/can-to-ethernet-converters-usr-canet200.html

I managed to purchase one here in the UK via Amazon for £63, which I think is good value for an industrial quality adaptor. It has two CAN bus ports and also an RS485 port which I use too. Only thing to note is that it did not come with a power supply. My other USR serial adaptor came with a plug in 5v supply, and I found that the DC power port on that adaptor then presents 5v outward, so I have simply patched a cable from that to the other unit DC input.

You can see the unit in my picture in the post.

2 Likes

Thanks for the quick reply. I’m now trying to wipe all the egg off my face for not expanding your photo to reveal the make/model details of the CAN-Bus interface unit! :roll_eyes:

It is a long post with a lot of information…

Nice work!

Could you capture a dump of all the messages going on the CAN bus?
I will have a Pylontech battery in the future but want to get a head start on the CAN listener and node-red code.

Easily done

This is the buffer that arrives, every second.

[7,0,0,3,89,0,0,0,0,6,80,78,0,8,0,0,3,81,20,2,172,8,172,8,194,1,4,0,0,3,85,21,0,100,0,0,0,0,0,6,0,0,3,86,42,19,0,0,181,0,0,0,2,0,0,3,92,192,0,0,0,0,0,0,0,8,0,0,3,94,80,89,76,79,78,32,32,32]

Due to the adaptor device I am using, the CANbus packets are encoded into standard sized blocks of 13, and all messages arrive in one go.

As a starter to help you, the first five bytes are the message header, including the effective data block length and the message ID.

This is the heartbeat message, which does not give much away…

[8,0,0,3,5,0,0,0,0,0,0,0,0]

Cool setup, my Domotica system uses canbus, I bought myself an canable can USb stick, to read and write canbus data…

I think I submitted a year ago the option to include kernel drivers to load USB can dongles… (HassOS)

Great write up!
I have Pylontech batteries and a Victron inverter which accurately reads the data via CAN/RS-485

With the CAN to Ethernet converter you’re using can you configure a CAN in and CAN out configuration so CAN data can still go to another CAN device (inverter)?

I’m just wanting to listen to all the extra data that the Victron inverter doesn’t do anything with.

Thanks

Pylontech batteries communicate on four, entirely separate, comms ports.

  • The ‘link’ port is inter-battery communication (probably proprietary serial link - have not looked at this one)
  • The console port is RS232, and used mostly as a human-machine interface for debugging and programming.
  • The RS485 link is a complex vendor specific protocol, used by some inverters but mostly there for multi-block battery control.
  • The CAN bus port is the simplest, and primary comms link for battery-inverter connection.

To avoid confusion, on the newer Pylontech batteries, the ports marked A/CAN and B/RS485 are actually both RS485 and CAN mixed together. The top port is ‘out’ and the bottom is ‘in’, with pins on each port being 7&8 for RS485 and 4&5 for CAN (6 is a nominal CAN ground). Top port ‘out’ usually goes to inverters, ‘in’ usually comes from other Pylontech battery stacks, to allow for control over more than 16 batteries. Typically the connection to inverter is CAN only.

I understand that your Victron inverter (like almost every make) connects to Pylontech batteries only via the CAN bus. It is relatively easy to listen in on this (one-way) conversation, but as a critical control link it should not be disrupted!

To answer your question:

Yes. The adaptor has two CAN ports. These can be used separately (two CAN bus networks) or there is a pass-through mode that means they are effectively linked (two physically separate CAN bus, but one connected network). However…

No, you don’t need both ports. The way CAN works is it uses a single pair of wires to connect to everything in parallel. So, Pylontech CAN H/L → adaptor port H/L → Inverter CAN H/L (just like a chain of parallel light bulbs). The only thing talking on the bus is the battery, and both inverter and adaptor can listen in when wired together.

Just attach the adaptor CAN H/L pair on to the wiring between battery and inverter at a convenient point. Note that the bus must be terminated at each end with resistors. Fortunately both inverter and battery have these in-built, so just adding in the adaptor somewhere between does not require any additional changes (and adaptor terminating resistors should be left switched-out).

There is absolutely no need for the adaptor to act as a repeater, however it can, and I assume it is possible to listen to the battery on CAN port A, then make modifications, and pass on a new message to the inverter via CAN port B. Clearly not recommended unless you really do know what you are doing! The CAN connection between battery and inverter must be maintained, even if the adaptor is turned off, so basically, don’t even try.

There is not a great deal of information on the CAN messages, and I suspect that everything is consumed and used by your inverter. My Solis inverter certainly appears to use all the data, it is just quicker and easier to listen in on the CAN messages than to use Modbus to get the data back from the inverter. The only peice of information that does not appear to get used is a new ‘charge me now’ flag. Pylontech batteries should be charged to 100% SOC every 28 days so as to re-calibrate the SOC values. There is supposed to be a bit-flag that turns on after 28 days which can be used to tell the inverter to charge to full, however I have not yet seen this data bit change value.

2 Likes

Whoa! Thanks very much for this. It looks like it is going to be super useful, but a bit overwhelming for a non coder / hardware engineer like me! We’re about to commit to a solar & battery installation with a Solis RHI-6K-48ES-5G Hybrid Inverter and Pylon batteries. Shame there’s nothing off the shelf for integration, but comprehensive info like this is going to be super useful - just hope it’s not beyond me!

Hello, maybe you can answer if you are aleady aware about pylontech protocol. What about several batteries connected (in daisy chain). Is the master “one” aggregating everything and send to the inverter or each batteries send it’s own information over canbus ? Thx

For CANbus, the master battery manages the communication, and provides a summary. CANbus does not hold much information, but things like the SOC and temperature are the average across the stack. The voltage and current are for the entire stack, as presented to the inverter.

If you want individual battery information then you need to use the RS232 comms port or the RS485 communication port. Both of these again come from the mater battery, but these communication protocols permit both system (summary) and individual battery responses, the master battery talking down to each unit and responding as appropriate


.
The individual battery SOC comes using RS232 console protocol to get each battery SOC.

CANbus sends just 80%, which is the 80% value. This is what the inverter will see over CANbus.

Thx for your quick reply… I want more or less what SAUK007 is doing with one JKBMS (conversion and canbus commands) but with several JKBMS this time.

I suspect that individually managing Pylontech battery units is both impractical and certainly inadvisable.

CANbus is a one-way communication. From battery to inverter. The inverter listens to the battery situation and manages the applied voltage to drive the appropriate charge / discharge response.

Disconnecting the CANbus in my experience results in the inverter seeing a flat battery, and immediately applying a full emergency charge, the result of which would probably be the individual battery BMSs opening the MOS gate fuses to prevent overcharge, overheating, and a fire.

Tinker at your own risk.

That seems surprising and I would not want to own an inverter that behaved in that fashion. My inverter reacts to loss of CAN comms by stopping charge and discharge. A force-charge requires manual action (via the control app.)

My inverter will switch to charge mode if the battery reports charge state below a threshold, but that obviously won’t happen in the absence of communication.

Hi Geoff

I have very little info regarding this topic. I ll appreciate if u can help me out.

I have a Growatt SPH 10KW Inverter which has CAN and RS485 communication ports for Lithium Batteries. To charge the battery bank its. voltage ranges from 100 - 550 DCVolts. I plan to use toyota Prius Hybrid Battery Bank which charges at 210 Volts. It communicates thru CANBUS, do u think if I connect the Battery direct to the inverter to the CAN port, will it run fine?

I know even less than you about the battery and inverter you mention, however I have to say NO!

All inverters have either CAN bus or RS485 or both, and the inverter expects to communicate with a compatible battery BMS (Battery Management System) using one or the other.

Lithium batteries MUST have a good BMS, which will be part of the battery, a separate commercial device, or a well designed and built DIY (NOT RECOMMENDED).

The inverter must be either configured or can be configured for the exact battery model. Matching charging voltage for lithium batteries is essential and over voltage at any time can lead to overheating and thermal runaway and fire.

For moral, humanist, ethical, and legal reasons I am obliged to say don’t even think about doing this.

My recommendation - start with the inverter and use a battery that the inverter manufacturer recommends or has listed as compatible. Do not attempt to connect anything else.

I don’t wish to be negative or to pour cold water on your idea, but lithium batteries are very dangerous if not managed very very carefully.