Converts the JK-BMS RS485 data to Pylontech CAN data
Converts the JK-BMS RS485 data to Pylontech CAN data for inverters which are not compatible with JK-BMS protocol but with Pylontech protocol, like Deye inverters.
Display of many BMS information and alarms on a locally attached serial 2004 LCD.
Based on https://github.com/syssi/esphome-jk-bms and https://github.com/maxx-ukoo/jk-bms2pylontech.
The JK-BMS RS485 data (e.g. at connector GPS) are provided as RS232 TTL with 115200 Bit/s.
If the Aduino IDE complains about more than 100% of program storage space, burn the Uno Bootloader on your Nano, if not already done, and select the Uno as board. The Arduino Nano board definition has a wrong "upload.maximum_size" value.
Enabling the macro NO_SERIAL_INFO_PRINT
saves program space.
On a MCP2515 / TJA1050 kit for Arduino you must replace the assembled 8 MHz crystal with a 16 MHz one.
The MCP2515 / TJA1050 kit for Arduino may be supplied by an extra 5 V regulator. My Arduino-Nano internal regulator cannot provide more than 100 mA and got defect on my site after a few days.
By default, the program sends a request to force charge the battery if SOC is below 5 %. This can be adapted by changing the line #define SOC_THRESHOLD_FOR_FORCE_CHARGE_REQUEST_I 5
.
At around 100% SOC, the JK-BMS seems to send strange current information of more than +/- 1 ampere.
If CAN communications breaks, the inverter may use different values for controlling the battery (e.g. "Use Batt V"), which may lead to additional discharging / charging.
Created by attaching Arduio 1.8 Serial Plotter and then doing a long button press followed by a single one to enter the capacity info page.
Here you see a peak at the transition from 100 % to 99 %. This happens at the start of the system, when there was no full 0% to 100% capacity cycle
and the BMS has not yet learned the correct capacity for 100%. The new 99 % learned by the BMS is bigger than the old 100 %!
The capacity drop is due to a (fixed!) overflow problem.
The voltage line is smooth, because it is corrected with the ESR (Equivalent Series Resistance) of the Battery.
The same (raw) data without the ESR correction.
The screenshots are taken from the Wokwi example with STANDALONE_TEST
enabled and therefore may contain random data.
Big Info page with: - SOC and Power - Maximum of 3 Temperatures and Ampere in/out - Difference between minimum / empty and (current battery voltage - Volt to full) - Display of "C"harging "D"ischarging and "B"alancing active flags |
Overview pagewith : - SOC, charged capacity, state of enable flags - Voltage, current and power - Voltage difference to empty, MosFet temperature, maximum sensor temperature, state of enabled functions. - If Overvoltage, C is replaced by O - If Undervoltage, D is Replaced by U |
---|---|
Undervoltage Alarm page Start of alarm message in first line Index and value of minimum cell and uptime in second line |
Overtemperature Alarm page Alarm message is cleared by switching page |
Cell info page with maximum and minimum indicators | Cell info page with: - (Cell voltages - 3 V) - SOC, current in A, balancing flag and difference between minimum / empty and current battery voltage in last column |
Maximum Cell Statistics page with total Time of Balancing | Maximum Cell Statistics page |
CAN info page | |
Capacity Statistics page percentages | Capacity Statistics page voltages |
My installation | Automatic brightness |
---|---|
Breadboard detail | |
Breadboard without BMS connected | Standalone test |
No-breadboard version overview | No-breadboard version overview |
Nano top view | Nano bottom view |
Also usable as connection schematic.
The standard RX of the Arduino is used for the JK_BMS connection.
A schottky diode is inserted into the RX line to allow programming the AVR with the JK-BMS still connected and switched on.
Keep in mind that programming will fail if JK-BMS is connected and switched off.
The standard TX of the Arduino is used for Serial.print() for monitoring and debugging. The short request to JK-BMS is sent by SoftwareSerialTX
using pin 4.
If you use the cable from the separate RS485 adapter of the JK-BMS and follow the labeling on the board, you have to swap the lines for RX and TX (pin 4) on the Uno / Nano.
Power is taken from an USB power supply connected to the Nano. Current is 40 mA for a dark 2004 display and 55 mA for a bright one.
Optionally, power can be taken from the second battery, but then you may require an external 5V regulator. My built in regulator broke 2 times (with LCD connected).
Or use the complete battery voltage for Nano supply and a buck converters for around 48 to 60 volt. But my test converter had an idle current of 6 mA (0.3 W), so I decided to stay with the USB power supply.
On the Deye, connect cable before setting Battery Mode
to Lithium
, to avoid alarm. Lithium Mode
for Pylontech CAN is 0
or PYLON
.
ALTERNATIVE EXTERNAL POWER SUPPLY:
78L05 Optional Schottky diode - From Uno/Nano 5 V
___ to enable powering CAN
Optional 6.6 V from Battery #2 >-o-------|___|-------o-|<|-< Uno 5V module by Nano USB, if
| | | battery is not attached
| --- |
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
| |
__________ Schottky diode ____|____ ____|____ _________
| TX|>---|<|-- RX -->|RX Vin |<- SPI ->| 5V | | |
| RX|<-------- TX --<|4 Uno/ | | MCP2515 | | |
| JK-BMS | | Nano | | CAN |<-- CAN -->| DEYE |
| |<------- GND -->| |<- GND ->| | | |
|__________| |_________| |_________| |_________|
# Connection diagram for JK-BMS GPS / UART-TTL socket (4 Pin, JST 1.25mm pitch)
___ ________ ___
| |
| O O O O |
|GND RX TX VBAT|
|________________|
| | |
| | --|<|-- RX of Uno / Nano
| ----------- D4 (or other pin, if specified)
--------------- GND
# Automatic brightness control for 2004 LCD
5V O------o------o
| |
.-. |
LDR | | |
| | |
'-' |
| |/
o----|
|>
|
O To anode of LCD backlight
Alternative circuit for VCC lower than 5 volt e.g. for supply by Li-ion battery
3.5V to 5V O------o------o Anode of LCD backlight
|
.-.
LDR with | |
high R | | o Kathode of LCD backlight
'-' |
| |/
o----|
|>
|
GND O-------------o
EasyEda shematics by Ngoc Dang Dinh
Download and extract the repository. In the Arduino IDE open the sketch with File -> Open... and select the JK-BMSToPylontechCAN folder.
All libraries, especially the modified ones, are included in this project.
It is always recommended to burn the Uno bootloader on a Nano board, and trating your Nano board as an an Uno board for Arduino compiles. This will give you 1.5 kB more program space, without any disadvantages. Even A6 and A7 are available :-).
To customize the software to different requirements, there are some compile options / macros available.
Modify them by enabling / disabling them, or change the values if applicable.
Name | Default value | Description |
---|---|---|
MILLISECONDS_BETWEEN_JK_DATA_FRAME_ REQUESTS |
2000 | % |
MILLISECONDS_BETWEEN_CAN_FRAME_SEND |
2000 | % |
NO_BEEP_ON_ERROR |
disabled | . |
ONE_BEEP_ON_ERROR |
disabled | If activated, only beep once if error was detected. |
BEEP_TIMEOUT_SECONDS |
60 | 1 minute, every 2 seconds. |
MULTIPLE_BEEPS_WITH_TIMEOUT |
enabled | If error was detected, beep for 60 s. |
SUPPRESS_LIFEPO4_PLAUSI_WARNING |
disabled | Disables warning on Serial out about using LiFePO4 beyond 3.0 v to 3.45 V. |
MAXIMUM_NUMBER_OF_CELLS |
24 | Maximum number of cell info which can be converted. Saves RAM. |
USE_NO_LCD |
disabled | Disables the code for the LCD display. Saves 25% program space on a Nano. |
DISPLAY_ALWAYS_ON |
disabled | If activated, the display backlight is always on. This disables the value of DISPLAY_ON_TIME_SECONDS . |
DISPLAY_ON_TIME_SECONDS |
300 | 300 s / 5 min after the last button press, the backlight of the LCD display is switched off. |
DISPLAY_ON_TIME_SECONDS_IF_TIMEOUT |
180 | 180 s / 3 min after the first timeout / BMS shutdown, the backlight of the LCD display is switched off. |
USE_NO_COMMUNICATION_STATUS_LEDS |
disabled | If activated, the code for the BMS and CAN communication status LED is deactivated and the pins are not switched to output. |
NO_SERIAL_INFO_PRINT |
enabled | Disables writing some info to serial output. Saves 974 bytes program space. |
DISABLE_MONITORING |
enabled | Disables writing cell and current values CSV data to serial output. Saves 534 bytes program space. |
NO_CELL_STATISTICS |
disabled | Disables generating and display of cell balancing statistics. Saves 16558 bytes program space. |
NO_ANALYTICS |
disabled | Disables generating, storing and display of SOC graph for Arduino Serial Plotter. Saves 3882 bytes program space. |
BATTERY_ESR_MILLIOHM |
If defined, the voltage in the analytics graph is corrected to get a smoother voltage curve. You can compute the ESR by looking at a big current jump and then use the voltage jump to compute the ESR. | |
STANDALONE_TEST |
disabled | If activated, fixed BMS data is sent to CAN bus and displayed on LCD. |
NO_CAPACITY_35F_EXTENSIONS |
disabled | If activated, supress sending of frame 0x35F for total capacity for SMA Sunny Island inverters over CAN. |
NO_CAPACITY_379_EXTENSIONS |
disabled | If activated, supress sending of frame 0x379 for total capacity for Luxpower SNA inverters over CAN. |
NO_BYD_LIMITS_373_EXTENSIONS |
disabled | If activated, supress sending of frame 0x373 for cell limits as sent by BYD battery over CAN. |
DO_NOT_SHOW_SHORT_CELL_VOLTAGES |
disabled | If activated, do not print 3 digits cell voltage (value - 3.0 V) on Cell Info page. Disables display of up to 20 voltages or display of additional information on this page. |
DISABLE_MONITORING |
disabled | If activated, no cell and current values CSV data are written to serial output |
. | ||
CAN_DATA_MODIFICATION |
disabled | If activated, it currently enables the function to reduce max current at high SOC level. |
MAX_CURRENT_MODIFICATION_LOWER_SOC_ THRESHOLD_PERCENT |
80 | Start SOC for linear reducing maximum current. |
MAX_CURRENT_MODIFICATION_MIN_CURRENT_ TENTHS_OF_AMPERE |
50 | Value of current at 100 % SOC. Units are 100 mA! |
There may be some some more options like BUTTON_DEBOUNCING_MILLIS
, which are only for very special requirements.
The CSV data has the caption:
Cell_1;Cell_2;Cell_3;Cell_4;Cell_5;Cell_6;Cell_7;Cell_8;Cell_9;Cell_10;Cell_11;Cell_12;Cell_13;Cell_14;Cell_15;Cell_16;Voltage,Current;SOC;Balancing
Example data: CSV: 270;262;271;271;271;269;270;271;266;266;266;266;265;262;265;265;5228;-22.56;71;1
This program uses the following libraries, which are already included in this repository:
CAPACITY_35F_EXTENSIONS
, CAPACITY_379_EXTENSIONS
and BYD_LIMITS_373_EXTENSIONS
.BATTERY_ESR_MILLIOHM
for voltage compensation.SHOW_SHORT_CELL_VOLTAGES
is default now.USE_NO_LCD
.See also here.
START ../src/JK-BMSToPylontechCAN.cpp
Version 2.0 from Sep 8 2023
Serial to JK-BMS started with 115200 bit/s!
CAN started with 500 kbit/s!
If you connect debug pin 3 to ground, additional debug data is printed
2000 ms between 2 BMS requests
2000 ms between 2 CAN transmissions
*** BMS INFO ***
Protocol Version Number=1
Software Version Number=11.XW_S11.26___
Modify Parameter Password=1234
# External Temperature Sensors=2
*** BATTERY INFO ***
Manufacturer Date=2307
Manufacturer Id=Armins__BMS1JK_B2A20S20P
Device ID String=Armins__
Device Address=1
Total Battery Capacity[Ah]=115, Low Capacity Alarm Percent=20
Charging Cycles=1
Total Charging Cycle Capacity=218
# Battery Cells=16, Cell Count=16
*** VOLTAGE PROTECTION INFO ***
Battery Overvoltage Protection[mV]=55200, Undervoltage=48000
Cell Overvoltage Protection[mV]=3450, Recovery=3400, Delay[s]=5
Cell Undervoltage Protection[mV]=3000, Recovery=3050, Delay[s]=5
Cell Voltage Difference Protection[mV]=300
Discharging Overcurrent Protection[A]=80, Delay[s]=30
Charging Overcurrent Protection[A]=43, Delay[s]=30
*** TEMPERATURE PROTECTION INFO ***
Power MosFet Temperature Protection=80, Recovery=70
Sensor1 Temperature Protection=100, Recovery=100
Sensor1 to Sensor2 Temperature Difference Protection=20
Charge Overtemperature Protection=45, Discharge=45
Charge Undertemperature Protection=3, Recovery=5
Discharge Undertemperature Protection=-20, Recovery=-10
*** MISC INFO ***
Balance Starting Cell Voltage=[mV]3350
Balance Triggering Voltage Difference[mV]=10
Current Calibration[mA]=1048
Sleep Wait Time[s]=10
Dedicated Charge Switch Active=0
Start Current Calibration State=0
Battery Actual Capacity[Ah]=115
Total Runtime Minutes=49260 -> 34D05H00M
*** CELL INFO ***
16 Cells, Minimum=3397 mV, Maximum=3408mV, Delta=11 mV, Average=3403 mV
1=3397 mV, 2=3399 mV, 3=3400 mV, 4=3403 mV, 5=3406 mV, 6=3407 mV, 7=3407 mV, 8=3408 mV,
9=3400 mV, 10=3406 mV, 11=3407 mV, 12=3404 mV, 13=3404 mV, 14=3403 mV, 15=3401 mV, 16=3402 mV,
Temperature: Power MosFet=28, Sensor 1=25, Sensor 2=25
SOC[%]=99 -> Remaining Capacity[Ah]=113
Battery Voltage[V]=54.41, Current[A]=-1.25, Power[W]=-68
Battery Voltage difference to full[V]=0.8
Charging MosFet enabled, active | Discharging MosFet enabled, active | Balancing enabled, not active
Battery Voltage[V]=54.41, Current[A]=1.25, Power[W]=68
Battery Voltage difference to full[V]=0.8
Set LCD display page to: 0
Set LCD display page to: 1
Set LCD display page to: 2
Debug mode just activated
Send CAN
CANId=0x351, FrameLength=8, Data=0x28, 0x2, 0xF4, 0x1, 0x20, 0x3, 0xE0, 0x1
CANId=0x355, FrameLength=4, Data=0x3C, 0x0, 0x64, 0x0
CANId=0x356, FrameLength=6, Data=0x6C, 0x14, 0x0, 0x0, 0xDC, 0x0
CANId=0x35E, FrameLength=8, Data=0x50, 0x59, 0x4C, 0x4F, 0x4E, 0x20, 0x20, 0x20
CANId=0x35C, FrameLength=2, Data=0xC0, 0x0
CANId=0x305, FrameLength=8, Data=0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
CANId=0x359, FrameLength=7, Data=0x0, 0x0, 0x0, 0x0, 0x1, 0x50, 0x4E
Send requestFrame with TxToJKBMS
0x4E 0x57 0x0 0x13 0x0 0x0 0x0 0x0 0x6 0x3 0x0 0x0 0x0 0x0 0x0 0x0 0x68 0x0 0x0 0x1 0x29
291 bytes received
0x00 0x4E 0x57 0x01 0x21 0x00 0x00 0x00 0x00 0x06 0x00 0x01
0x0B 0x79 0x30 0x01 0x0C 0xC6
0x10 0x02 0x0C 0xBE 0x03 0x0C 0xC7 0x04 0x0C 0xC7 0x05 0x0C 0xC7 0x06 0x0C 0xC5 0x07
0x20 0x0C 0xC6 0x08 0x0C 0xC7 0x09 0x0C 0xC2 0x0A 0x0C 0xC2 0x0B 0x0C 0xC2 0x0C 0x0C
0x30 0xC2 0x0D 0x0C 0xC1 0x0E 0x0C 0xC1 0x0F 0x0C 0xC1 0x10 0x0C 0xC1
0x3D 0x80 0x00 0x16
0x40 0x81 0x00 0x15 0x82 0x00 0x16 0x83 0x14 0x6C 0x84 0x00 0x00 0x85 0x3C 0x86 0x02
0x50 0x87 0x00 0x00 0x89 0x00 0x00 0x00 0x00 0x8A 0x00 0x10 0x8B 0x00 0x00 0x8C 0x00
0x60 0x03 0x8E 0x15 0x90 0x8F 0x12 0xC0 0x90 0x0D 0x7A 0x91 0x0D 0x48 0x92 0x00 0x05
0x70 0x93 0x0B 0xB8 0x94 0x0B 0xEA 0x95 0x00 0x05 0x96 0x01 0x2C 0x97 0x00 0x50 0x98
0x80 0x00 0x1E 0x99 0x00 0x32 0x9A 0x00 0x1E 0x9B 0x0C 0x80 0x9C 0x00 0x0A 0x9D 0x01
0x90 0x9E 0x00 0x50 0x9F 0x00 0x46 0xA0 0x00 0x64 0xA1 0x00 0x64 0xA2 0x00 0x14 0xA3
0xA0 0x00 0x3C 0xA4 0x00 0x46 0xA5 0x00 0x05 0xA6 0x00 0x0A 0xA7 0xFF 0xEC 0xA8 0xFF
0xB0 0xF6 0xA9 0x10 0xAA 0x00 0x00 0x00 0x6E 0xAB 0x01 0xAC 0x01 0xAD 0x04 0x18 0xAE
0xC0 0x01 0xAF 0x00 0xB0 0x00 0x0A 0xB1 0x14 0xB2 0x31 0x32 0x33 0x34 0x35 0x36 0x00
0xD0 0x00 0x00 0x00 0xB3 0x00 0xB4 0x41 0x72 0x6D 0x69 0x6E 0x73 0x5F 0x5F 0xB5 0x32
0xE0 0x33 0x30 0x37 0xB6 0x00 0x00 0x0E 0x85 0xB7 0x31 0x31 0x2E 0x58 0x57 0x5F 0x53
0xF0 0x31 0x31 0x2E 0x32 0x36 0x5F 0x5F 0x5F 0xB8 0x00 0xB9 0x00 0x00 0x00 0x6E 0xBA
0x100 0x41 0x72 0x6D 0x69 0x6E 0x73 0x5F 0x5F 0x42 0x4D 0x53 0x00 0x4A 0x4B 0x5F 0x42
0x110 0x32 0x41 0x32 0x30 0x53 0x32 0x30 0x50 0xC0 0x01
0x11A 0x00 0x00 0x00 0x00 0x68 0x00
0x120 0x00 0x51 0xCA