Pylontech Protocol In Inverter Battery Communication.

Deep technical breakdown of the Pylontech protocol, message IDs, byte structure, and why many “compatible” BMS clones fail with inverters.

Introduction

Pylontech published their CAN message format for inverter integration around 2015. It was never intended as a formal standard. No IEEE specification, no certification body, no compliance testing. Just internal documentation shared with inverter partners to enable their batteries to communicate charge and discharge limits. Other battery manufacturers noticed that inverters were adding “Pylontech compatible” modes. They reverse engineered the message structure and copied it. Same message IDs, same byte positions, close enough to work.

Inverter manufacturers saw market demand and added Pylontech support because enough batteries used it. Network effect took over. More batteries claimed compatibility to access those inverters. More inverters added support because batteries used it. The cycle reinforced itself. Today hundreds of battery brands claim “Pylontech compatible” on their specification sheets.

Reality is more complicated than the marketing claims. Message IDs match. The core structure is similar. But implementations vary in subtle ways that matter. Timing jitter differs between manufacturers. Some use little-endian byte order, others use big-endian. Scaling factors vary. Some implementations send all defined messages, others send only the minimum subset. Temperature units might be Celsius or Kelvin. Error handling differs.

Also Read: Inverter Battery Communication Protocols in Modern Solar Systems

This creates a compatibility spectrum instead of a binary yes or no. One battery-inverter combination works perfectly. Another combination using the same claimed protocol has intermittent errors. A third combination appears to communicate but interprets values wrong, leading to chronic overcharge or failed balancing. All three claim “Pylontech compatible” because they copied the message IDs and approximate structure.

This post decodes the actual protocol structure at the byte level. It explains the three core messages that carry all critical data. It documents common clone variations and where they diverge from the original implementation. It shows how to use a CAN analyzer to verify what your specific BMS actually transmits. Understanding the protocol enables diagnosis when “compatible” devices fail to communicate properly.

What Gets Transmitted Every Second

The Pylontech protocol uses CAN 2.0B extended frame format with 29-bit message identifiers. Each message carries zero to eight data bytes. CAN includes built-in error detection through CRC checksums, bit stuffing, and acknowledgment mechanisms. Priority arbitration uses the identifier value where lower numbers get higher priority on the bus. Standard baud rate is 500 kilobits per second, which determines maximum reliable cable length and timing constraints for the entire system.

Pylontech Protocol

Messages transmit every 1000 milliseconds in the original Pylontech implementation, exactly one hertz update rate. Some clone implementations vary from 800 to 1200 milliseconds with inconsistent jitter. This timing variation is the first source of incompatibility. Inverters with strict timeout thresholds expect messages within a narrow window. If the BMS sends at 1150 milliseconds and the inverter times out at 1100 milliseconds, communication appears to work initially but fails intermittently under certain conditions.

Three primary messages carry all critical operational data. Message 0x351 contains charge voltage limit, charge current limit, discharge current limit, and discharge voltage limit. This message controls how the inverter charges and discharges the battery. Message 0x355 carries state of charge and state of health as percentage values. This message allows the inverter to display remaining capacity and overall battery condition. Message 0x356 transmits real-time measurements including pack voltage, pack current, and temperature. This message provides the inverter with sensor data for validation and monitoring.

An optional fourth message 0x359 carries alarm and warning flags indicating various protection states like over-voltage, under-voltage, over-current, and over-temperature conditions. The original Pylontech implementation includes this message. Many clone implementations omit it entirely. Inverters expecting alarm data may throw errors when this message is missing, while other inverters ignore its absence and function normally. This inconsistency creates another compatibility variable that bench testing might not reveal until specific fault conditions occur in the field.

Message 0x351: Charge and Discharge Limits

Message 0x351 carries the four fundamental control parameters as eight data bytes. Bytes zero and one contain Charge Voltage Limit in units of 0.1 volts as a 16-bit unsigned integer. Bytes two and three contain Charge Current Limit in units of 0.1 amps as a 16-bit signed integer. Bytes four and five contain Discharge Current Limit in units of 0.1 amps as a 16-bit signed integer. Bytes six and seven contain Discharge Voltage Limit in units of 0.1 volts as a 16-bit unsigned integer.

Example decode for a 16S LFP pack at normal operating conditions: CVL equals 56.0 volts, transmitted as decimal 560 or hexadecimal 0x0230. CCL equals 100 amps, transmitted as decimal 1000 or hex 0x03E8. DCL equals 80 amps, transmitted as decimal 800 or hex 0x0320. The byte order determines how these 16-bit values split across two bytes.

Also Read: CVL, CCL, and DCL: Understanding Dynamic Battery Limits in Real-Time

Standard Pylontech uses little-endian byte order where the least significant byte comes first. The value 560 in hex 0x0230 transmits as byte zero equals 0x30 and byte one equals 0x02. Reading left to right gives 0x30 then 0x02, but combining them as 16-bit little-endian produces 0x0230 which equals 560 decimal. Some clone implementations use big-endian where most significant byte comes first. The same value 560 would transmit as byte zero equals 0x02 and byte one equals 0x30.

If endianness mismatches between BMS and inverter, interpretation fails completely. A BMS sending little-endian 0x30 0x02 (560 for 56.0 volts) gets interpreted by a big-endian inverter as 0x3002 which equals 12290 decimal or 1229.0 volts. This impossible value causes the inverter to reject the data, throw errors, or fall back to default settings. The opposite mismatch where BMS sends big-endian and inverter expects little-endian produces equally wrong results. This is not fixable in the field. It requires firmware changes on either the BMS or inverter to match byte order conventions.

Messages 0x355 and 0x356: State and Measurements

Message 0x355 transmits state information using eight data bytes. Bytes zero and one contain State of Charge as a percentage from zero to 100, encoded as a 16-bit unsigned integer in units of 1 percent. Bytes two and three contain State of Health as a percentage, also 16-bit unsigned in units of 1 percent. Bytes four through seven are reserved or used for additional status data depending on implementation. A battery at 75 percent SOC and 100 percent SOH transmits 75 in bytes zero and one, and 100 in bytes two and three, using the same little-endian convention as message 0x351.

This message enables the inverter to display BMS-calculated state of charge rather than relying on its own coulomb counting estimate. It also allows the inverter to validate its own SOC calculation against the BMS value and detect divergence. Some clone implementations always transmit 100 percent for state of health regardless of actual battery condition because calculating real SOH requires tracking capacity fade over time, which adds complexity. The inverter display shows 100 percent health even as capacity degrades, misleading the user about actual battery condition.

Message 0x356 carries real-time sensor measurements. Bytes zero and one contain pack voltage in units of 0.01 volts as a 16-bit unsigned integer. Bytes two and three contain pack current in units of 0.1 amps as a 16-bit signed integer where positive values indicate charging and negative values indicate discharging. Bytes four and five contain pack temperature in units of 0.1 degrees Celsius as a 16-bit signed integer allowing negative temperatures in cold climates. Bytes six and seven are additional temperature data or reserved depending on implementation.

Example decode: Pack voltage at 52.80 volts transmits as 5280 decimal or hex 0x14A0. Charge current at positive 47.5 amps transmits as 475 decimal or hex 0x01DB. Discharge current at negative 30.2 amps uses two’s complement signed representation, transmitting as negative 302 which is hex 0xFED2. Temperature at 28.5 degrees Celsius transmits as 285 decimal or hex 0x011D. Misinterpreting signed values as unsigned creates garbage data. A discharge current of negative 30 amps read as unsigned becomes 65506 amps, an impossible value that should trigger inverter validation errors.

Clone Implementation Differences

Message timing varies significantly across clone implementations. The original Pylontech transmits messages every 1000 milliseconds with minimal jitter, maintaining consistent intervals within plus or minus 5 percent. Some clones exhibit timing jitter from 800 to 1200 milliseconds with no consistent pattern. This results from poor timer implementation or low-priority firmware tasks that delay CAN transmission. Inverters with strict timeout thresholds expect messages within 1100 to 1200 milliseconds. When gaps exceed this threshold due to BMS timing inconsistency, the inverter declares communication lost even though the BMS is still transmitting.

Read This: CAN Bus Physical Layer: The 60-Second Fix for Battery Communication Failures

Other clones use burst transmission where all three messages (0x351, 0x355, 0x356) transmit within 10 milliseconds, followed by silence for 1500 milliseconds, then another burst. This concentrates bus traffic into brief periods instead of spacing messages evenly. Some inverter firmware expects relatively even message distribution and throws errors when receiving rapid bursts followed by long gaps, even though total message count over time matches the expected rate.

Endianness creates binary incompatibility with no field workaround. Standard implementations use little-endian byte order. Some clones use big-endian. When a little-endian BMS communicates with a big-endian inverter, every multi-byte value gets interpreted backwards. CVL of 56.0 volts becomes 1229.0 volts or 5.6 volts depending on which direction the mismatch goes. CCL of 100 amps becomes 25600 amps or 0.39 amps. These garbage values cause immediate obvious failure during commissioning rather than subtle problems that appear later.

Scaling factor variations create less obvious problems. Standard protocol uses 0.1-volt units for voltage and 0.1-amp units for current. Some clones use 0.01-volt units providing ten times higher resolution. If the inverter expects 0.1-volt units but receives 0.01-volt units, a CVL of 56.00 volts transmitted as 5600 gets interpreted as 560.0 volts, triggering immediate over-voltage protection. The reverse mismatch where the inverter expects 0.01-volt units but receives 0.1-volt units interprets 560 as 5.60 volts, preventing charging entirely because this voltage is below the minimum cell voltage for LFP chemistry.

Decoding Messages with a CAN Analyzer

A CAN analyzer captures all bus traffic and displays it as timestamped message frames. Typical output shows timestamp in seconds, message identifier in hexadecimal, and eight data bytes also in hexadecimal. Example captured frame: timestamp 12.456789, ID 0x351, data bytes 30 02 E8 03 20 03 00 22. This is message 0x351 containing charge and discharge limits.

Decoding bytes zero and one for CVL: hex 0x30 and 0x02 combine as little-endian 16-bit to form 0x0230, which equals 560 decimal, representing 56.0 volts. Bytes two and three for CCL: hex 0xE8 and 0x03 combine as 0x03E8, which equals 1000 decimal, representing 100.0 amps. Bytes four and five for DCL: hex 0x20 and 0x03 combine as 0x0320, which equals 800 decimal, representing 80.0 amps. Bytes six and seven for DVL: hex 0x00 and 0x22 combine as 0x2200, which equals 8704 decimal, representing 870.4 volts.

That last value immediately flags an error. Discharge voltage limit of 870.4 volts makes no sense for a 16S LFP pack which operates between 40 and 58 volts. Either the byte order for this field is swapped (0x22 0x00 would equal 34 decimal or 3.4 volts, still wrong but closer), or this clone implementation uses bytes six and seven for different data entirely instead of discharge voltage limit. Some clones transmit pack identifier or reserved values in this position. The inverter expecting DVL gets garbage data.

Verifying BMS implementation requires capturing traffic during known states. Set the battery to 50 percent SOC at 25 degrees Celsius with no current flowing. Capture messages and decode all three primary IDs. Compare decoded values to what the BMS display shows if accessible. CVL should match expected voltage (around 56 volts for LFP).

SOC in message 0x355 should show 50 percent. Pack voltage in message 0x356 should match actual measured pack voltage (around 52 to 53 volts for 16S LFP at 50 percent SOC). Current should read near zero. Temperature should match ambient. If decoded values match reality, the BMS implements standard Pylontech format correctly. If values are wrong by factors of ten, suspect scaling mismatch. If completely garbage, suspect endianness mismatch.

Troubleshooting Protocol Mismatches

No communication at all requires checking physical layer before investigating protocol issues. Verify termination reads 60 ohms between CAN-H and CAN-L with power off. Confirm cable is twisted pair under 5 meters with no visible damage. Check that both devices use 500 kilobits per second baud rate. Only after confirming physical layer is correct should you investigate protocol problems.

Connect a CAN analyzer and verify the BMS transmits messages. If no traffic appears, either the BMS CAN interface is disabled in configuration, the baud rate setting is wrong causing the analyzer to miss messages, or the BMS hardware has failed. If messages appear but use different IDs than 0x351, 0x355, 0x356, the BMS implements a completely different protocol and is not Pylontech compatible despite marketing claims. If correct message IDs appear but the inverter does not respond, the inverter may expect different IDs (some use 0x250 range instead of 0x350 range), or the inverter is configured for a different protocol mode entirely like Modbus instead of CAN.

Communication works but values are wrong indicates scaling or endianness mismatch. Inverter displaying CVL as 5.6 volts or 560.0 volts instead of 56.0 volts points to scaling factor confusion. Capture message 0x351 with the analyzer and check bytes zero and one. If they contain 560 decimal (0x0230 hex) and the inverter shows wrong voltage, the inverter interprets scaling incorrectly. If bytes contain 5600 decimal (0x15E0 hex), the BMS uses 0.01 volt units when it should use 0.1 volt units. No field fix exists for this. Firmware update on either BMS or inverter is required to match scaling conventions.

Inverter showing negative CVL or completely nonsensical values suggests endianness mismatch. Capture message 0x351 and verify byte order. Standard little-endian for CVL of 56.0 volts shows bytes as 0x30 0x02. If the inverter interprets this as big-endian, it reads 0x3002 which equals 12290 decimal or 1229.0 volts, an impossible value. SOC stuck at zero percent or not updating means either message 0x355 is not transmitted by the BMS, or the inverter does not parse it. Confirm with analyzer whether 0x355 appears on the bus. If missing, the BMS implements only minimal protocol subset. If present, check that byte positions match standard format.

Firmware Version Compatibility

Protocol evolution happens without formal versioning. Pylontech updates their firmware over time and message structure stays similar, but timing behavior, error handling, and edge case responses change. No version field exists in CAN messages, so the inverter cannot detect which protocol generation the BMS implements. Clone manufacturers reverse engineer from different Pylontech firmware versions captured at different times, creating multiple protocol generations all claiming to be Pylontech compatible.

Inverter firmware also evolves independently. Early inverter firmware might be strict about timing, requiring messages every 1000 milliseconds plus or minus 50 milliseconds. Later firmware becomes more tolerant, accepting 1000 milliseconds plus or minus 200 milliseconds to accommodate sloppy BMS implementations. Or the evolution goes the opposite direction where later firmware becomes stricter to fix bugs that allowed problematic timing. The BMS and inverter firmware versions create a compatibility matrix where some combinations work perfectly and others fail intermittently.

Community knowledge fills the gap that manufacturer documentation leaves empty. Online forums contain field reports from thousands of installations documenting which BMS and inverter combinations actually work. Example from real field experience: Generic LFP BMS clone firmware 2.4 with Victron MultiPlus II firmware 497 shows intermittent SOC jumps to 100 percent and communication dropouts. BMS firmware update to 2.7 corrects timing jitter and resolves the issue. Another example: JK BMS firmware 11.XW with Deye inverter firmware 0.09 results in CVL being ignored because JK transmits big-endian while Deye expects little-endian. No firmware fix exists for this combination, requiring different hardware selection.

Testing compatibility before installation prevents discovering problems after commissioning. Connect BMS and inverter on the bench with a short one-meter cable. Power both devices and verify communication establishes. Check whether the inverter display shows CVL, CCL, DCL values and whether those values are reasonable (56 volts CVL, 100 amps CCL typical for LFP). Change BMS state by heating or cooling slightly and verify limits update on the inverter display. Let the system run for 30 minutes minimum and monitor for intermittent errors. Bench testing catches obvious incompatibilities but misses issues that only appear with long cables, high EMI environments, or specific operating conditions like temperature extremes.

Building Community Compatibility Knowledge

Document every installation with specific details that enable others to learn from your experience. Record BMS manufacturer, model number, and firmware version. Record inverter manufacturer, model number, and firmware version. Note cable type and length. Document whether the combination works perfectly, fails completely, or works with intermittent issues. Describe specific symptoms if problems occur and any workarounds discovered. This structured data becomes valuable when shared with the community.

Online forums provide the platform for sharing field experience. DIYSolarPowerForum and SecondLifeStorage host active communities with thousands of battery builders and installers. Reddit communities like r/SolarDIY and r/Batteries attract technically knowledgeable participants. Facebook groups organized around specific inverter or BMS brands contain users who have tested many combinations. GitHub repositories for open-source BMS projects like JK and Daly maintain issue trackers where compatibility problems get documented with technical detail.

The value of shared knowledge exceeds manufacturer documentation because manufacturers rarely test all possible combinations. Official compatibility lists, when they exist, show only the few battery models the inverter manufacturer tested in their lab. Real field installations involve hundreds of battery brands, many of which are clones with subtle variations. Community documentation reveals which claimed compatible combinations actually work in practice and which combinations cause problems despite matching specifications.

Contributing back to the community strengthens the knowledge base for everyone. When you discover a working combination, post the details so others can replicate your success. When you encounter incompatibility, document it with enough detail that others can avoid the same mistake. When you find a workaround like changing cable type or adjusting configuration settings, share the solution. Compatibility databases grow more valuable as more installers contribute their field experience, creating a resource that helps everyone make better equipment selection decisions and troubleshoot problems faster when they occur.

Manufacturer forums vary in quality. Some manufacturers actively monitor user discussions and provide technical support, making their forums valuable for finding official responses to compatibility questions. Other manufacturer forums receive minimal attention, leaving users to help each other without factory input. Independent forums often provide more honest compatibility information because users share both successes and failures without marketing pressure to present only positive results.

Conclusion

This protocol deep dive provides the technical foundation for diagnosing Pylontech compatibility problems. Message 0x351 carries CVL, CCL, DCL, and DVL in eight bytes with 16-bit values using 0.1 unit scaling and little-endian byte order in standard implementations. Message 0x355 transmits SOC and SOH as percentage values. Message 0x356 provides real-time voltage, current, and temperature measurements. These three messages constitute the minimum viable protocol that enables basic BMS to inverter communication.

Clone implementations diverge from the standard in predictable ways. Timing varies from strict 1000 millisecond intervals to inconsistent jitter or burst transmission patterns. Endianness differs with some using big-endian instead of standard little-endian, causing complete interpretation failure. Scaling factors vary with some using 0.01 unit resolution instead of 0.1 units, creating ten times multiplication errors. Message subsets differ with minimal clones omitting SOC or measurement data entirely.

Use this knowledge during commissioning to verify communication works correctly. Connect a CAN analyzer and capture actual message traffic. Decode bytes manually to confirm values match expected ranges. CVL around 56 volts for LFP, CCL and DCL matching battery specifications, SOC matching actual state, measurements matching physical reality. Deviations from expected values indicate protocol implementation problems that will cause operational issues later.

Apply this knowledge when troubleshooting compatibility failures. No communication at all usually indicates physical layer problems or completely wrong protocol selection, not subtle Pylontech variations. Communication established but wrong values points to scaling or endianness mismatch requiring firmware updates. Intermittent errors suggest timing problems where BMS transmission intervals exceed inverter timeout thresholds.

Understand what Pylontech compatible actually means in practice. Message IDs match the 0x351, 0x355, 0x356 standard. Data fields occupy approximately correct byte positions. Scaling and endianness hopefully match but verification is required. Full protocol compliance with proper timing and complete message set is not guaranteed by the compatibility claim. Community knowledge and bench testing reveal true compatibility better than manufacturer specifications. For complete context on how protocol implementation affects overall system reliability including physical layer requirements and dynamic limit coordination, see the main guide on inverter battery communication protocols.

Leave a Reply

Your email address will not be published. Required fields are marked *