<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nodemint</title>
    <description>The latest articles on DEV Community by Nodemint (@nodemint_7d21b30c9c6298ce).</description>
    <link>https://dev.to/nodemint_7d21b30c9c6298ce</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4007113%2Ff131ac4b-3e9b-455a-9a98-31ddc2020d8a.png</url>
      <title>DEV Community: Nodemint</title>
      <link>https://dev.to/nodemint_7d21b30c9c6298ce</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nodemint_7d21b30c9c6298ce"/>
    <language>en</language>
    <item>
      <title>Closed-loop comms over RS485: getting a JK BMS to talk to a Deye inverter when CAN refused to cooperate</title>
      <dc:creator>Nodemint</dc:creator>
      <pubDate>Mon, 29 Jun 2026 01:18:42 +0000</pubDate>
      <link>https://dev.to/nodemint_7d21b30c9c6298ce/closed-loop-comms-over-rs485-getting-a-jk-bms-to-talk-to-a-deye-inverter-when-can-refused-to-3481</link>
      <guid>https://dev.to/nodemint_7d21b30c9c6298ce/closed-loop-comms-over-rs485-getting-a-jk-bms-to-talk-to-a-deye-inverter-when-can-refused-to-3481</guid>
      <description>&lt;p&gt;If you run an off-grid solar setup, there's a moment that separates a pile of expensive components from an actual system: the inverter and the battery's BMS start talking to each other. Before that, the inverter is guessing your state of charge from voltage alone — which on a LiFePO4 pack is close to useless, because the voltage curve is famously flat. After it, the inverter reads real per-cell data, real SoC, real current limits, straight from the BMS. That's closed-loop communication, and it's the difference between a battery you babysit and one you trust.&lt;/p&gt;

&lt;p&gt;Here's how I got there on my setup, and why the "recommended" path was a dead end.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardware
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inverter:&lt;/strong&gt; Deye SUN-6K-SG04LP1-EU-SM2 (6kW, off-grid)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pack:&lt;/strong&gt; 16S LiFePO4, 16× EVE MB31 314Ah cells, ~16.1kWh&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BMS:&lt;/strong&gt; JK BMS PB2A16S30P
&amp;gt; &lt;strong&gt;Tested on:&lt;/strong&gt; Deye SUN-6K-SG04LP1-EU-SM2 — inverter protocol version &lt;code&gt;0201&lt;/code&gt; (no separate software-version field on this unit) · JK BMS PB2A16S30P — hardware &lt;code&gt;V19A&lt;/code&gt;, firmware &lt;code&gt;V19.30&lt;/code&gt;, JK app &lt;code&gt;v5.12.0&lt;/code&gt; · battery protocol &lt;code&gt;014&lt;/code&gt; (PYLON) · RS485 @ 9600 baud on UART1
&amp;gt;
&amp;gt; Firmware matters here: BMS-to-inverter comms behavior can change between revisions, so if your versions differ from these, treat the protocol/baud combo as a starting point and confirm against your own setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On paper this is a well-supported combination. The Deye has a battery comms port, the JK BMS supports inverter protocols, and every guide tells you the same thing: use CAN bus, select the right protocol on the inverter, done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where CAN let me down
&lt;/h2&gt;

&lt;p&gt;CAN is the path everyone recommends, so that's where I started. Wired the CAN lines from the BMS to the inverter's battery port, set the inverter's battery type to the matching protocol, and waited for the handshake.&lt;/p&gt;

&lt;p&gt;Nothing. The inverter stayed in voltage-only mode, no closed-loop data, no SoC coming across. I went through the usual suspects — pinout, wiring, termination, protocol selection on both ends — and still couldn't get a stable CAN link.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're hitting this too: it's worth confirming the exact pinout of &lt;em&gt;your&lt;/em&gt; Deye revision's battery port against &lt;em&gt;your&lt;/em&gt; BMS, because the silkscreen and the manual don't always agree, and CAN is unforgiving about which pair you land on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At some point you have to make a call: keep chasing the recommended path, or switch to the one that works. I switched.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually worked: RS485, protocol 014, 9600 baud
&lt;/h2&gt;

&lt;p&gt;The JK BMS exposes more than one comms route, and the Deye speaks several battery protocols. The combination that brought the link up for me was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RS485&lt;/strong&gt; (not CAN), on &lt;strong&gt;UART1&lt;/strong&gt; of the BMS&lt;/li&gt;
&lt;li&gt;Protocol &lt;strong&gt;014&lt;/strong&gt; on the Deye — this is the &lt;strong&gt;PYLON&lt;/strong&gt; protocol&lt;/li&gt;
&lt;li&gt;Baud rate &lt;strong&gt;9600&lt;/strong&gt;
The moment that lined up, the inverter switched out of voltage-guessing mode and started reading the BMS directly: SoC, pack voltage, current, and the charge/discharge limits the BMS was advertising. Closed loop, finally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few things worth knowing if you're doing the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pick the right UART.&lt;/strong&gt; The JK has multiple ports, and they aren't interchangeable for this. UART1 was the one that carried the inverter protocol cleanly for me.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Match the baud exactly.&lt;/strong&gt; 9600 for the PYLON protocol. A baud mismatch gives you the same silent failure as a wiring fault, which is what makes this hard to diagnose — everything &lt;em&gt;looks&lt;/em&gt; connected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol number is the whole game.&lt;/strong&gt; On the Deye, the protocol selector is just a number. 014 = PYLON. Choosing the wrong one means the inverter is speaking fluent nonsense at a BMS that's listening in a different language.
## Why bother&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With closed-loop comms running, the inverter stops over- or under-charging based on a voltage curve that barely moves between 20% and 80%. It respects the BMS's actual current limits, which matters a lot for cell longevity, and it reports an SoC you can trust on the dashboard. For a pack I'm planning to keep healthy for 20 years on an 80% depth-of-discharge strategy, that accuracy isn't a nicety — it's the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The recommended path isn't always the one that works. CAN is the default advice for a reason, but when it won't come up and you've exhausted the wiring and pinout checks, RS485 with the correct protocol and baud is a completely valid — and often more forgiving — fallback. On a Deye + JK BMS pairing, protocol 014 (PYLON) over RS485 at 9600 baud on UART1 is the combination I'd reach for first next time.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm building &lt;a href="https://nodemint.dev" rel="noopener noreferrer"&gt;Nodemint&lt;/a&gt; — software, with a hardware-adjacent streak. If you're working on solar monitoring, embedded comms, or anything in this space, &lt;a href="https://nodemint.dev/#contact" rel="noopener noreferrer"&gt;get in touch&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>solar</category>
      <category>lifepo4</category>
      <category>embedded</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
