Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JK BMS RS485 protocol #112

Closed
CRaccani opened this issue May 8, 2021 · 67 comments
Closed

JK BMS RS485 protocol #112

CRaccani opened this issue May 8, 2021 · 67 comments
Assignees

Comments

@CRaccani
Copy link

CRaccani commented May 8, 2021

Please find attached a different RS485 protocol document, sent to me by IC GOGOGO Store for the BMS I bought from them.
I have also just received their RS485 Dongle.
The Dongle plugs into the BMS but the dongle ends in 3 bare wires at the other end. I presume these are RS485- GND, A+, B+.
I have connected these to an RS485-USB dongle.
Any experience with this setup.

20210508_212723

I tried your RS485 protocol but did not receive any bytes back.
So looks like this BMS may use a different protocol.

Any chance of adding this protocol:
RS485-english.pdf

@jblance
Copy link
Owner

jblance commented May 9, 2021

I've had a go at adding the first attempt at this protocol (called it jk232), likely still got work to do
can you update to version 0.7.54 or later and try with
jkbms -p /dev/ttyUSB0 -b 9600 -P JK232 -I
(change the port to whereever the adapter shows up), can you post the results

@jblance jblance self-assigned this May 9, 2021
@CRaccani
Copy link
Author

CRaccani commented May 9, 2021

Thank you.
Here is the output requested:

$ jkbms -p /dev/ttyUSB0 -b 9600 -P JK232 -D

INFO:root:Solar Device Command Utility, version: 0.7.54, recent changes: add jk rs232/485 protocol
INFO:root:Creating device "unnamed" (type: "jkbms") on port "/dev/ttyUSB0 (porttype=None)" using protocol "JK232"
DEBUG:root:device_class <class 'mppsolar.devices.jkbms.jkbms'>
DEBUG:device:jkbms __init__ args ()
DEBUG:device:jkbms __init__ kwargs {'name': 'unnamed', 'port': '/dev/ttyUSB0', 'protocol': 'JK232', 'baud': 9600, 'porttype': None, 'mqtt_broker': 'localhost', 'mqtt_port': 1883, 'mqtt_user': None, 'mqtt_pass': None}
DEBUG:device:get_port_type: port matches ttyusb
INFO:device:set_port: Using serialio for communications
DEBUG:device:set_protocol: Protocol JK232
DEBUG:device:jkbms __init__ name unnamed, port <mppsolar.io.serialio.SerialIO object at 0xb6d609cc>, protocol <mppsolar.protocols.jk232.jk232 object at 0xb6d60a8c>
DEBUG:root:Commands [(<mppsolar.devices.jkbms.jkbms object at 0xb6d60a0c>, '', '', 'screen', None, None)]
INFO:root:Looping 1 commands
INFO:root:Getting results from device: jkbms device - name: unnamed, port: <mppsolar.io.serialio.SerialIO object at 0xb6d609cc>, protocol: <mppsolar.protocols.jk232.jk232 object at 0xb6d60a8c> for command: , tag: , outputs: screen
INFO:device:run_command: Running command
INFO:jk232:get_full_command: Using protocol b'JK232' with 1 commands
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK232'
DEBUG:jk232:get_full_command: cmd with start bit: bytearray(b'\xdd\x00\x00\x00\x00\x00\x00')
DEBUG:jk232:get_full_command: cmd with crc: bytearray(b'\xdd\xa5\x03\x00\xff\xfdw')
INFO:device:run_command: full command bytearray(b'\xdd\xa5\x03\x00\xff\xfdw') for command getBalancerData
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK232'
DEBUG:SerialIO:send_and_receive: port /dev/ttyUSB0, baudrate 9600
DEBUG:SerialIO:send_and_receive: Executing command via serialio...
DEBUG:SerialIO:send_and_receive: serial response was: b''
DEBUG:device:run_command: Send and Receive Response b''
INFO:AbstractProtocol:decode: response passed to decode: b''
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK232'
DEBUG:jk232:get_responses: responses [b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'']
DEBUG:AbstractProtocol:decode: trimmed and split responses: [b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'']
INFO:AbstractProtocol:decode: Processing response of type POSITIONAL
DEBUG:AbstractProtocol:decode: Processing POSITIONAL type responses
DEBUG:AbstractProtocol:Processing data_type: Hex2Str for data_name: Start Byte, raw_value b''
DEBUG:AbstractProtocol:Processing format string Hex2Str(raw_value)
DEBUG:protocol_helpers:Hex b'' decoded to
DEBUG:AbstractProtocol:decode: Processing POSITIONAL type responses
DEBUG:AbstractProtocol:Processing data_type: Hex2Str for data_name: Command Code, raw_value b''
DEBUG:AbstractProtocol:Processing format string Hex2Str(raw_value)
DEBUG:protocol_helpers:Hex b'' decoded to
DEBUG:AbstractProtocol:decode: Processing POSITIONAL type responses
DEBUG:AbstractProtocol:Processing data_type: Hex2Str for data_name: Status, raw_value b''
DEBUG:AbstractProtocol:Processing format string Hex2Str(raw_value)
DEBUG:protocol_helpers:Hex b'' decoded to
DEBUG:AbstractProtocol:decode: Processing POSITIONAL type responses
DEBUG:AbstractProtocol:Processing data_type: Hex2Int for data_name: Data Length, raw_value b''
DEBUG:AbstractProtocol:Processing format string Hex2Int(raw_value)
Traceback (most recent call last):
  File "/usr/local/bin/jkbms", line 33, in <module>
    sys.exit(load_entry_point('mpp-solar', 'console_scripts', 'jkbms')())
  File "/home/pi/src/mpp-solar/mppsolar/__init__.py", line 388, in main
    results = _device.run_command(command=_command)
  File "/home/pi/src/mpp-solar/mppsolar/devices/device.py", line 330, in run_command
    decoded_response = self._protocol.decode(raw_response, command)
  File "/home/pi/src/mpp-solar/mppsolar/protocols/abstractprotocol.py", line 350, in decode
    frame_number=frame_number,
  File "/home/pi/src/mpp-solar/mppsolar/protocols/abstractprotocol.py", line 122, in process_response
    r = eval(format_string)
  File "<string>", line 1, in <module>
  File "/home/pi/src/mpp-solar/mppsolar/protocols/protocol_helpers.py", line 70, in Hex2Int
    answer = hexString[0]
IndexError: index out of range

@jblance
Copy link
Owner

jblance commented May 9, 2021

So still some bugs in the code - but more importantly there was no response from the device
Is ttyUSB0 the correct device?
Do you have any indication of communications happening?
Does dmesg give any insight?
What does lsusb report?

@CRaccani
Copy link
Author

CRaccani commented May 10, 2021

Am now using my Victron RS485 to USB cable. Higher quality and I know it works.
It has flashing LEDS when activity.
There is a heartbeat denoted by the GREEN LED which flashes on a regular basis- so heart beat from BMS?
When I run your program the GREEN LED blinks once.

OUTPUT:dmesg

:    :   : 
:    :   :  
[614891.532083] usb 1-1.4: new full-speed USB device number 67 using ehci-pci
[614891.650899] usb 1-1.4: New USB device found, idVendor=0403, idProduct=6001, bcdDevice= 6.00
[614891.650902] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[614891.650904] usb 1-1.4: Product: FT232R USB UART
[614891.650906] usb 1-1.4: Manufacturer: FTDI
[614891.650908] usb 1-1.4: SerialNumber: AK08MAON
[614891.654312] ftdi_sio 1-1.4:1.0: FTDI USB Serial Device converter detected
[614891.654347] usb 1-1.4: Detected FT232RL
[614891.654772] usb 1-1.4: FTDI USB Serial Device converter now attached to ttyUSB0

OUTPUT: lsusb

Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 004: ID 17ef:480c Lenovo Integrated Webcam
Bus 001 Device 067: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 001 Device 066: ID 0409:005a NEC Corp. HighSpeed Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 003: ID 0a5c:2145 Broadcom Corp. BCM2045B (BDC-2.1) [Bluetooth Controller]
Bus 004 Device 002: ID 08ff:2810 AuthenTec, Inc. AES2810
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

OUTPUT protocol: 232 using Victron dongle:

jkbms -p /dev/ttyUSB0 -b 9600 -P JK232 -D

INFO:root:Solar Device Command Utility, version: 0.7.54, recent changes: add jk rs232/485 protocol
INFO:root:Creating device "unnamed" (type: "jkbms") on port "/dev/ttyUSB0 (porttype=None)" using protocol "JK232"
DEBUG:root:device_class <class 'mppsolar.devices.jkbms.jkbms'>
DEBUG:device:jkbms __init__ args ()
DEBUG:device:jkbms __init__ kwargs {'name': 'unnamed', 'port': '/dev/ttyUSB0', 'protocol': 'JK232', 'baud': 9600, 'porttype': None, 'mqtt_broker': 'localhost', 'mqtt_port': 1883, 'mqtt_user': None, 'mqtt_pass': None}
DEBUG:device:get_port_type: port matches ttyusb
INFO:device:set_port: Using serialio for communications
DEBUG:device:set_protocol: Protocol JK232
DEBUG:device:jkbms __init__ name unnamed, port <mppsolar.io.serialio.SerialIO object at 0xb6e39f6c>, protocol <mppsolar.protocols.jk232.jk232 object at 0xb6e4196c>
DEBUG:root:Commands [(<mppsolar.devices.jkbms.jkbms object at 0xb6e39fcc>, '', '', 'screen', None, None)]
INFO:root:Looping 1 commands
INFO:root:Getting results from device: jkbms device - name: unnamed, port: <mppsolar.io.serialio.SerialIO object at 0xb6e39f6c>, protocol: <mppsolar.protocols.jk232.jk232 object at 0xb6e4196c> for command: , tag: , outputs: screen
INFO:device:run_command: Running command
INFO:jk232:get_full_command: Using protocol b'JK232' with 1 commands
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK232'
DEBUG:jk232:get_full_command: cmd with start bit: bytearray(b'\xdd\x00\x00\x00\x00\x00\x00')
DEBUG:jk232:get_full_command: cmd with crc: bytearray(b'\xdd\xa5\x03\x00\xff\xfdw')
INFO:device:run_command: full command bytearray(b'\xdd\xa5\x03\x00\xff\xfdw') for command getBalancerData
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK232'
DEBUG:SerialIO:send_and_receive: port /dev/ttyUSB0, baudrate 9600
DEBUG:SerialIO:send_and_receive: Executing command via serialio...
DEBUG:SerialIO:send_and_receive: serial response was: b'\x00'
DEBUG:device:run_command: Send and Receive Response b'\x00'
INFO:AbstractProtocol:decode: response passed to decode: b'\x00'
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK232'
DEBUG:jk232:get_responses: responses [b'\x00', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'']
DEBUG:AbstractProtocol:decode: trimmed and split responses: [b'\x00', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'']
INFO:AbstractProtocol:decode: Processing response of type POSITIONAL
DEBUG:AbstractProtocol:decode: Processing POSITIONAL type responses
DEBUG:AbstractProtocol:Processing data_type: Hex2Str for data_name: Start Byte, raw_value b'\x00'
DEBUG:AbstractProtocol:Processing format string Hex2Str(raw_value)
DEBUG:protocol_helpers:Hex b'\x00' decoded to 00
DEBUG:AbstractProtocol:decode: Processing POSITIONAL type responses
DEBUG:AbstractProtocol:Processing data_type: Hex2Str for data_name: Command Code, raw_value b''
DEBUG:AbstractProtocol:Processing format string Hex2Str(raw_value)
DEBUG:protocol_helpers:Hex b'' decoded to
DEBUG:AbstractProtocol:decode: Processing POSITIONAL type responses
DEBUG:AbstractProtocol:Processing data_type: Hex2Str for data_name: Status, raw_value b''
DEBUG:AbstractProtocol:Processing format string Hex2Str(raw_value)
DEBUG:protocol_helpers:Hex b'' decoded to
DEBUG:AbstractProtocol:decode: Processing POSITIONAL type responses
DEBUG:AbstractProtocol:Processing data_type: Hex2Int for data_name: Data Length, raw_value b''
DEBUG:AbstractProtocol:Processing format string Hex2Int(raw_value)
Traceback (most recent call last):
  File "/usr/local/bin/jkbms", line 33, in <module>
    sys.exit(load_entry_point('mpp-solar', 'console_scripts', 'jkbms')())
  File "/home/pi/src/mpp-solar/mppsolar/src/mpp-solar/mppsolar/__init__.py", line 388, in main
    results = _device.run_command(command=_command)
  File "/home/pi/src/mpp-solar/mppsolar/src/mpp-solar/mppsolar/devices/device.py", line 330, in run_command
    decoded_response = self._protocol.decode(raw_response, command)
  File "/home/pi/src/mpp-solar/mppsolar/src/mpp-solar/mppsolar/protocols/abstractprotocol.py", line 350, in decode
    frame_number=frame_number,
  File "/home/pi/src/mpp-solar/mppsolar/src/mpp-solar/mppsolar/protocols/abstractprotocol.py", line 122, in process_response
    r = eval(format_string)
  File "<string>", line 1, in <module>
  File "/home/pi/src/mpp-solar/mppsolar/src/mpp-solar/mppsolar/protocols/protocol_helpers.py", line 70, in Hex2Int
    answer = hexString[0]
IndexError: index out of range

OUTPUT protocol: 485 using Victron dongle:

jkbms -p /dev/ttyUSB0 -b 9600 -P JK485 -D

INFO:root:Solar Device Command Utility, version: 0.7.54, recent changes: add jk rs232/485 protocol
INFO:root:Creating device "unnamed" (type: "jkbms") on port "/dev/ttyUSB0 (porttype=None)" using protocol "JK485"
DEBUG:root:device_class <class 'mppsolar.devices.jkbms.jkbms'>
DEBUG:device:jkbms __init__ args ()
DEBUG:device:jkbms __init__ kwargs {'name': 'unnamed', 'port': '/dev/ttyUSB0', 'protocol': 'JK485', 'baud': 9600, 'porttype': None, 'mqtt_broker': 'localhost', 'mqtt_port': 1883, 'mqtt_user': None, 'mqtt_pass': None}
DEBUG:device:get_port_type: port matches ttyusb
INFO:device:set_port: Using serialio for communications
DEBUG:device:set_protocol: Protocol JK485
DEBUG:device:jkbms __init__ name unnamed, port <mppsolar.io.serialio.SerialIO object at 0xb6d85f8c>, protocol <mppsolar.protocols.jk485.jk485 object at 0xb6d8d96c>
DEBUG:root:Commands [(<mppsolar.devices.jkbms.jkbms object at 0xb6d85fec>, '', '', 'screen', None, None)]
INFO:root:Looping 1 commands
INFO:root:Getting results from device: jkbms device - name: unnamed, port: <mppsolar.io.serialio.SerialIO object at 0xb6d85f8c>, protocol: <mppsolar.protocols.jk485.jk485 object at 0xb6d8d96c> for command: , tag: , outputs: screen
INFO:device:run_command: Running command
INFO:jk485:get_full_command: Using protocol b'JK485' with 1 commands
DEBUG:jkAbstractProtocol:get_command_defn: get_command_defn for: getBalancerData
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK485'
DEBUG:jk485:get_full_command: cmd with header: bytearray(b'U\xaa\x00\x00\x00\x00\x00')
DEBUG:jk485:get_full_command: cmd with header + slave address: bytearray(b'U\xaa\x01\x00\x00\x00\x00')
DEBUG:jk485:get_full_command: cmd with command code and frame data: bytearray(b'U\xaa\x01\xff\x00\x00\x00')
DEBUG:jk485:get_full_command: cmd with crc: bytearray(b'U\xaa\x01\xff\x00\x00\xff')
INFO:device:run_command: full command bytearray(b'U\xaa\x01\xff\x00\x00\xff') for command getBalancerData
DEBUG:jkAbstractProtocol:get_command_defn: get_command_defn for: getBalancerData
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK485'
DEBUG:SerialIO:send_and_receive: port /dev/ttyUSB0, baudrate 9600
DEBUG:SerialIO:send_and_receive: Executing command via serialio...
DEBUG:SerialIO:send_and_receive: serial response was: b'\x00'
DEBUG:device:run_command: Send and Receive Response b'\x00'
INFO:jkAbstractProtocol:decode: response passed to decode: b'\x00'
DEBUG:jkAbstractProtocol:get_command_defn: get_command_defn for: getBalancerData
DEBUG:AbstractProtocol:get_command_defn: Processing command 'getBalancerData'
DEBUG:AbstractProtocol:get_command_defn: Found command getBalancerData in protocol b'JK485'
DEBUG:jkAbstractProtocol:decode: Length of responses 1
DEBUG:jkAbstractProtocol:decode: Processing defn ['hex', 2, 'Header', '']
DEBUG:jkAbstractProtocol:decode: hex defn
Traceback (most recent call last):
  File "/usr/local/bin/jkbms", line 33, in <module>
    sys.exit(load_entry_point('mpp-solar', 'console_scripts', 'jkbms')())
  File "/home/pi/src/mpp-solar/mppsolar/src/mpp-solar/mppsolar/__init__.py", line 388, in main
    results = _device.run_command(command=_command)
  File "/home/pi/src/mpp-solar/mppsolar/src/mpp-solar/mppsolar/devices/device.py", line 330, in run_command
    decoded_response = self._protocol.decode(raw_response, command)
  File "/home/pi/src/mpp-solar/mppsolar/src/mpp-solar/mppsolar/protocols/jkabstractprotocol.py", line 198, in decode
    value += f"{responses.pop(0):02x}"
IndexError: pop from empty bytearray

I'm none the wiser.
Hope this helps.

Ready and willing to try what ever you think may move this forward.
Thanks again.

@jblance
Copy link
Owner

jblance commented May 10, 2021

Well that output is slightly better (we are getting a response \x00 from both)
So that means the command being sent is likely wrong

@jblance
Copy link
Owner

jblance commented May 10, 2021

can you try running the below

import serial
import time

## Vars ################
port = "/dev/ttyUSB0"
baud = 9600
########################

# DD A5 03 00 FF FD 77
cmds = [b'\xdd\xa5\x03\x00\xff\xfdw', b'\xdd\xa5\x03\x00\xff\xfdw\n', b'\xdd\xa5\x03\x00\xff\xfdw', b'\xdd \xa5 \x03 \x00 \xff \xfd w', b'DD A5 03 00 FF FD 77' , b'DDA50300FFFD77']

with serial.serial_for_url(port, baud) as s:
    s.timeout = 1
    s.write_timeout = 1
    s.flushInput()
    s.flushOutput()
    for cmd in cmds:
        print (f"sending command {cmd}")
        bytes_written = s.write(cmd)
        print (f"wrote {bytes_written} bytes")

        for _ in range(5):
            response_line = s.readline()
            time.sleep(1)
            print (f"Got response: {response_line}")

@CRaccani
Copy link
Author

Corrected syntax error for future testing.

File "rs485.py", line 10
  cmds = [b'\xdd\xa5\x03\x00\xff\xfdw', b'\xdd\xa5\x03\x00\xff\xfdw\n', b'\xdd\xa5\x03\x00\xff\xfdw', b'\xdd \xa5 \x03 \x00 \xff \xfd w', b'DD A5 03 00 FF FD 77', , b'DDA50300FFFD77']
                                                                                                                                                                   ^
SyntaxError: invalid syntax

Ran the script, a few times:

sending command b'\xdd\xa5\x03\x00\xff\xfdw'
wrote 7 bytes
Got response: b'\x00\x00'
Got response: b''
Got response: b''
Got response: b''
Got response: b''
sending command b'\xdd\xa5\x03\x00\xff\xfdw\n'
wrote 8 bytes
Got response: b'\x00'
Got response: b''
Got response: b''
Got response: b''
Got response: b''
sending command b'\xdd\xa5\x03\x00\xff\xfdw'
wrote 7 bytes
Got response: b'\x00'
Got response: b''
Got response: b''
Got response: b''
Got response: b''
sending command b'\xdd \xa5 \x03 \x00 \xff \xfd w'
wrote 13 bytes
Got response: b'\x00'
Got response: b''
Got response: b''
Got response: b''
Got response: b''
sending command b'DD A5 03 00 FF FD 77'
wrote 20 bytes
Got response: b'\x00'
Got response: b''
Got response: b''
Got response: b''
Got response: b''
sending command b'DDA50300FFFD77'
wrote 14 bytes
Got response: b'\x00'
Got response: b''
Got response: b''
Got response: b''
Got response: b''

But got this every so often:

sending command b'\xdd\xa5\x03\x00\xff\xfdw'
wrote 7 bytes
Got response: b'\x00'
Got response: b''
Got response: b''
Got response: b''
Got response: b''
sending command b'\xdd\xa5\x03\x00\xff\xfdw\n'
wrote 8 bytes
Got response: b'\x00'
Got response: b''
Got response: b''
Got response: b''
Got response: b''
sending command b'\xdd\xa5\x03\x00\xff\xfdw'
wrote 7 bytes
Got response: b'\x00'
Traceback (most recent call last):
  File "rs485.py", line 23, in <module>
    response_line = s.readline()
  File "/usr/local/lib/python3.7/dist-packages/serial/serialposix.py", line 596, in read
    'device reports readiness to read but returned no data '
serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)

Could this be a timing issue?

Also would it make any difference to use Serial.RS485?
I'm not a Python programmer by the way.

@jblance
Copy link
Owner

jblance commented May 10, 2021

Corrected syntax error for future testing.

Opps thanks - will edit the comment

Could this be a timing issue?

It could be - is anything else using the port?
Does any application talk to the BMS?

Also would it make any difference to use Serial.RS485?
I'm not a Python programmer by the way.

It shouldnt - it looks to me like we are communicating ok, but not the correct commands (but I cant be sure)

@CRaccani
Copy link
Author

CRaccani commented May 10, 2021

Could the Bluetooth of the BMS be messing with it?
Does this need to be switched to RS485 mode? Power BMS off then on again, with USB dongle connected?

There was a flurry of green LED right before test script ended, but and as each command was sent.
Then reported error.

@jblance
Copy link
Owner

jblance commented May 10, 2021

Could the Bluetooth of the BMS be messing with it?
Does this need to be switched to RS485 mode? Power BMS off then on again, with USB dongle connected?

It is possible - I have never used a JKBMS with RS485 before - is there any options in the BLE app?

I know there is also a CAN bus as well, is that connected as well?
Are you certain the physical connections are correct?

There was a flurry of green LED right before test script ended, but not as each command was sent.

Was the script still trying to read a response?

@jblance
Copy link
Owner

jblance commented May 10, 2021

jkrs485

@CRaccani
Copy link
Author

CRaccani commented May 10, 2021

is there any options in the BLE app?

No options in BLE App.

I know there is also a CAN bus as well, is that connected as well?
Are you certain the physical connections are correct?

Only RS485 plug connected.
There are only 2 possible ways to connect RS485. Also tried, with and without GND. Have tried all possible combos.

Was the script still trying to read a response?

Don't know, possibly just flushing buffer on error.

Will contact seller and see if they can help.

Thanks again.
Time for bed.

12/05/21: Waiting for seller to get back to me.

@CRaccani
Copy link
Author

Got response from seller:
I sent them this screenshot of Version information from Android App:
Screenshot_20210513-144051

They sent back yet another protocol document in CHINESE.

BMS Protocol V2.5 CHINESE.pdf

I then put this through GOOGLE Translate:

BMS Protocol V2.5 ENGLISH (GOOGLE Translate).pdf

This protocol seems radically different to any other I have seen so far.

I gladly hand it over to you to take a bite at it.
Let us know what you think.
Kind regards.

@CRaccani
Copy link
Author

I have tried this command to activate the bms, but no joy:

Send: 4E57 0013 00000000 01 00 00 00 00000000 68 00000121

and this one to get ALL data, still no joy:

Send: 4E57 0013 00000000 06 00 00 00 00000000 68 00000129

Contacting seller again.
Fingers crossed.

@jblance
Copy link
Owner

jblance commented May 16, 2021 via email

@CRaccani
Copy link
Author

CRaccani commented May 17, 2021

I've used both a program called Windmill comDebug and the following python script from your test script.
Do you have this BMS and are you able to test with RS485.
I'm no expert at all with this, so another tester would be good.
Also, may buy a different USB to RS485 dongle. Not sure if this one does Master/Slave automatically.

Here is the code:

import serial
import time

# Checksum 4bytes, bytes 1-2 0000 not used, bytes 3-4 cumulative total 
def crc(byteData):
    CRC = 0
    for b in byteData:
        print(("{0:02x}".format(b)))
        CRC += b
    crc_byte4 = CRC & 0xFF
    crc_byte3 = (CRC >> 8) & 0xFF
    print(("{0:02x}".format(crc_byte3)))
    print(("{0:02x}".format(crc_byte4)))
    return [crc_byte3, crc_byte4]

# 4.2.4 COMMAND codes
command_ACTIVATE = b'\x01'
command_WRITE = b'\x02'
command_READ = b'\x03'
command_SEND_PASSWORD = b'\x05'
command_READ_ALL_DATA = b'\x06'

# FRAME SOURCE 0 BMS Data box 1 Bluetooth 2 GPS 3 PC Host Computer
source_BMS_DATA_BOX = b'\x00'
source_BLUETOOTH = b'\x01'
source_HOST_PC = b'\x03'

# Transmission type
tx_type_READ_DATA = b'\x00'
tx_type_REPLY_FRAME = b'\x01'
tx_type_WRITE_DATA = b'\x02'

# 4.2 Frame Format
frame_STX = b'\x4E\x57'
frame_LENGTH = bytearray(2)
frame_BMS_ID = bytearray(4)
frame_Command = bytearray(1)
frame_SOURCE = bytearray(1)
frame_TX_Type = bytearray(1)
frame_INFO_READ = bytearray(1)
frame_REC_NUM = bytearray(4)
frame_END_FLAG = b'\x68'
frame_CRC_HIGH = b'\x00\x00'
frame_CRC_LOW = bytearray(2)

# Initialise read request
# For READ req. LENGTH = 19, 0x0013
frame_LENGTH = b'\x00\x13'
frame_BMS_ID = b'\x00\x00\x00\x00'

frame_Command = command_READ_ALL_DATA
#frame_Command = command_ACTIVATE

#frame_SOURCE = source_BMS_DATA_BOX
frame_SOURCE = source_HOST_PC

frame_TX_Type = tx_type_READ_DATA

frame_INFO_READ = b'\x00'

frame_REC_NUM = b'\x00\x00\x00\x00'

# Make request frame
request_FRAME = bytearray()
request_FRAME[0:2] = frame_STX
request_FRAME[2:2] = frame_LENGTH
request_FRAME[4:4] = frame_BMS_ID
request_FRAME[8:1] = frame_Command
request_FRAME[9:1] = frame_SOURCE
request_FRAME[10:1] = frame_TX_Type
request_FRAME[11:1] = frame_INFO_READ
request_FRAME[12:4] = frame_REC_NUM
request_FRAME[16:1] = frame_END_FLAG

crc_byte3, crc_byte4 = crc(request_FRAME[0:17])
frame_CRC_LOW[0] = crc_byte3
frame_CRC_LOW[1] = crc_byte4

request_FRAME[17:2] = frame_CRC_HIGH
request_FRAME[19:2] = frame_CRC_LOW

port = "COM9"
baud = 115200
########################

with serial.serial_for_url(port, baud) as s:
    s.timeout = 1
    s.write_timeout = 1
    s.flushInput()
    s.flushOutput()
    print (f"sending command: {request_FRAME.hex()}")
    bytes_written = s.write(request_FRAME)
    print (f"wrote {bytes_written} bytes")
    for _ in range(5):
        response_line = s.readline()
        time.sleep(1)
        print (f"Got response: {response_line}")

@CRaccani CRaccani reopened this May 17, 2021
@jblance
Copy link
Owner

jblance commented May 18, 2021

What response do you get? Nothing or \x00 ?

It looks like you are running this on windows? Do you have a linux type system to test on?

@CRaccani
Copy link
Author

CRaccani commented May 18, 2021

Sorry I butchered your Python script.

Response is always 0x00
I have both, Win 10 (COM9) and Linux Debian 10 machines (/dev/ttyUSB0).
Both respond the same: 0x00.

tried:
BMS_ID: 0x00000000, 0x00000001 presume this allows multiple BMS. May start from 1 or 0
REC_NUM: 0x00000000, 0x00000001 don't know how this is used.

Tried:
ACTIVATE first, then READ_ALL
Just READ_ALL

Seller says this should work:
4E 57 00 13 00 00 00 00 06 03 00 00 00 00 00 00 68 00 00 01 29

My comments:
1. STX: 4E 57
2. LENGTH: 19 bytes
3. BMS_ID: 00 00 00 00
4. Command: 06, READ_ALL
5. FRAME_SOURCE: 03 PC Host computer
6. TX_TYPE:  00 Read request
7. FRAME INFO: 00 set 00 when command : 06
8. REC_NUM: 00 00 00 00
9. END flag: 68
10. Checksum: 00 00 01 29

but again returns 0x00

Should receive this other USB to RS485 converter tomorrow:

https://www.amazon.co.uk/gp/product/B082D5PXJ4/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

@CRaccani
Copy link
Author

CRaccani commented May 27, 2021

Progress,

READ ALL:

4E 57 00 13 00 00 00 00 06 03 00 00 00 00 00 00 68 00 00 01 29

RESPONSE (my indenting):

4E 57 01 1B 00 00 00 00 06 00 01 
79 2A 
 01 0E ED 
 02 0E FA 
 03 0E F7 
 04 0E EC 
 05 0E F8 
 06 0E FA 
 07 0E F1 
 08 0E F8 
 09 0E E3 
 0A 0E FA 
 0B 0E F1 
 0C 0E FB 
 0D 0E FB 
 0E 0E F2 
80 00 1D 
81 00 1E 
82 00 1C 
83 14 EF 
84 80 D0 
85 0F 
86 02 
87 00 04 
89 00 00 00 00 
8A 00 0E 
8B 00 00 
8C 00 07 
8E 16 26 
8F 10 AE 
90 0F D2 
91 0F A0 
92 00 05 
93 0B EA 
94 0C 1C 
95 00 05 
96 01 2C 
97 00 07 
98 00 03 
99 00 05 
9A 00 05 
9B 0C E4 
9C 00 08 
9D 01 
9E 00 5A 
9F 00 46 
A0 00 64 
A1 00 64 
A2 00 14 
A3 00 46 
A4 00 46 
A5 FF EC 
A6 FF F6 
A7 FF EC 
A8 FF F6 
A9 0E 
AA 00 00 00 0E 
AB 01 
AC 01 
AD 04 11 
AE 01 
AF 01 
B0 00 0A 
B1 14 
B2 31 32 33 34 35 36 00 00 00 00 
B3 00 
B4 49 6E 70 75 74 20 55 73 
B5 32 31 30 31 
B6 00 00 E2 00 
B7 48 36 2E 58 5F 5F 53 36 2E 31 2E 33 53 5F 5F 
B8 00 
B9 00 00 00 00 
BA 42 54 33 30 37 32 30 32 30 31 32 30 30 30 30 32 30 30 35 32 31 30 30 31 
C0 01 
00 00 00 00 68 00 00 54 D1 

@jblance
Copy link
Owner

jblance commented May 27, 2021

awesome news, what changed?
did you change the communications code ?

@CRaccani
Copy link
Author

Not using their TTL-RS485 dongle. Seems to be a faulty one.
Instead, connected a TTL-USB dongle directly to RX, TX, GND of BMS TTL-RS485 socket.
Protocol has a transmission source of Bluetooth, could you do a quick python script to send this protocols READ ALL command, via Bluetooth?

@CRaccani
Copy link
Author

CRaccani commented May 28, 2021

Machine readable list of Codes extracted from protocol document:

5.1 BMS Read/Write data identification code

RW Code Name Bytes Type Info
R 0x79 Individual Cell voltage 3*n HEX The first byte is the cell number, the next two bytes is the voltage value MV. When reading all the data at the same time, 0x79 is followed by one byte length data, n as shown above, and then a group of three bytes represents the electricity Cell voltage.
R 0x80 Read power tube temperature 2 HEX 0--140 (-40 to 100) The part exceeding 100 is negative temperature, such as 101 is negative 1 degree (100 Benchmark)
R 0x81 Read the temperature in the battery box 2 HEX 0--140 (-40 to 100) The part exceeding 100 is negative temperature, the same as above (100 reference)
R 0x82 Read battery temperature 2 HEX 0--140 (-40 to 100) The part exceeding 100 is negative temperature, the same as above (100 reference)
R 0X83 Total battery voltage 2 HEX 0.01V 3500*0.01=35.00v minimum unit 10MV
R 0X84 Current data 2 Hex 10000 (10000-11000)*0.01=-10.00a (discharge) (10000-9500)*0.01=5.00a (charging) Accuracy 10MA unit: 0.01A Note: C0:0x01 redefine 0x84 current data, the unit is 10MA, the highest bit is 0 Means discharging, 1 means charging If discharging 20A, the data transmitted will be 2000 (0x07D0) If charging 20A, the transmission data is 34768 (0x87D0)
R 0X85 Battery remaining capacity 1 HEX SOC, 0-100%,
R 0X86 Number of battery temperature sensors 1 Hex Two battery temperature sensors,
R 0X87 Number of battery cycles 2 Hex
R 0X89 Total battery cycle capacity 4 HEX Anshi
R 0x8a Total number of battery strings 2 HEX
R 0X8b Battery warning message 2 hex Note1
R 0X8c Battery status information 2 Bit code 0 bit charging MOS tube state 1 on 0 off This is for upload prompt 1 bit discharge MOS tube state 1 on 0 off This is for upload prompts. 2-position balance switch state 1 on, 0 off, this is for uploading prompts 3 battery dropped 1 is normal. 0 is offline, this is the upload prompt, Bits 4-15: reserved example: 00 01: Indicates that the charging MOS tube is turned on
RW 0x8e Total voltage overvoltage protection 2 HEX 1000-15000 (10 MV) Minimum unit 10MV
RW 0x8f Total voltage undervoltage protection 2 HEX 1000-15000 (10 MV) Minimum unit 10MV
RW 0X90 Single overvoltage protection voltage 2 Hex 1000--4500 MV,
RW 0x91 Cell overvoltage recovery voltage 2 HEX 1000-4500MV
RW 0x92 Single overvoltage protection delay 2 HEX 1-60 seconds
RW 0x93 Single undervoltage protection voltage 2 Hex 1000--4500 MV
RW 0x94 Monomer undervoltage recovery voltage 2 HEX 1000-4500MV
RW 0x95 Single undervoltage protection delay 2 HEX 1-60S seconds
RW 0x96 Cell pressure difference protection value 2 Hex 0-1000MV
RW 0x97 Discharge overcurrent protection value 2 Hex 1-1000A
RW 0x98 Discharge overcurrent delay 2 Hex 1-60S seconds
RW 0x99 Charging overcurrent protection value 2 Hex 1-1000A
RW 0x9a Charge overcurrent delay 2 HEX 1-60S
RW 0x9b Balanced starting voltage 2 Hex 2000-4500MV
RW 0x9c Balanced opening pressure difference 2 hex 10-1000 MV
RW 0x9d Active balance switch 1 Hex 0 off or 1 on
RW 0x9e Power tube temperature protection value 2 Hex 0--100
RW 0x9f Power tube temperature recovery value 2 Hex 0-100
RW 0xa0 Temperature protection value in the battery box 2 Hex 40--100
RW 0xa1 Temperature recovery value in the battery box 2 Hex 40--100
RW 0xa2 Battery temperature difference protection value 2 Hex 5-20
RW 0xa3 Battery charging high temperature protection value 2 HEX 0-100
RW 0xa4 Battery discharge high temperature protection value 2 HEX 0-100
RW 0xa5 Charging low temperature protection value 2 Hex -45 /+25 (no reference-signed data)
RW 0xa6 Charging low temperature protection recovery value 2 Hex -45 /+25 (no reference-signed data)
RW 0xa7 Discharge low temperature protection value 2 Hex -45 /+25 (no reference-signed data)
RW 0xa8 Discharge low temperature protection recovery value 2 Hex -45 /+25 (no reference-signed data)
RW 0xa9 Battery string setting 1 Hex 3-32
RW 0xaa Battery capacity setting 4 Hex AH (Amp Hour)
RW 0xab Charging MOS tube switch 1 Hex 0 off 1 open
RW 0xac Discharge MOS tube switch 1 Hex 0 off 1 open
RW 0xad Current calibration 2 Hex 100MA-20000MA
RW 0xae Protection board address 1 Hex is reserved for use when cascading,
RW 0xaf Battery Type 1 HEX 0: lithium iron phosphate, 1: ternary, 2: lithium titanate
RW 0xb0 Sleep waiting time 2 Hex second data, temporarily for reference,
RW 0xb1 Low volume alarm value 1 Hex 0--80%
RW 0xb2 Modify parameter password 10 hex is temporarily used as a reference, fix a password,
RW 0xb3 Dedicated charger switch 1 Hex 0 off or 1 on
RW 0Xb4 Device ID code 8 character Example 60300001 (60-nominal voltage level: defined by the voltage level, for example, 60 is 60V. Series 48 is 48V series; 3-material system: according to the system definition of battery materials such as iron. Lithium code is 1 manganic acid code 2 ternary code 3; 00001-production serial number: according to manufacturing. The Nth group of the model produced by the manufacturer that month is numbered N (for example: a certain type The first group of the number, then N is 00001)) characters
RW 0Xb5 Date of manufacture 4 character Example 2004-production year: take the last two digits according to the actual production year; list the production in 2020, Battery, year code 20; Production month: 01-12 months;
RW 0xb6 System working hours 4 HEX is cleared when leaving factory, unit minute
R 0xb7 Software version number 15 character NW_1_0_0_200428
RW 0xb8 Whether to start current calibration 1 HEX 1: Start calibration 0: Close calibration
RW 0xb9 Actual battery capacity 4 HEX AH (Amp Hour)
RW 0xBA Manufacturer ID naming 24 character Note2
W 0xBB Restart the system 1 HEX 1: Restart the system
W 0xBC reset 1 HeX 1: Restore ( only restore the factory reference parameters  )
W 0xBD Remote upgrade logo 1 HEX Start of HeX 1 ( wait for logo response when issuing documents )
W 0xBE Battery low voltage turns off GPS 2 Hex unit: mv ( turn off the power to GPS when low voltage is detected )
W 0xBF Battery low voltage recovery GPS 2 Hex unit: mv ( turn on the power to the GPS when the recovery voltage value is detected )
R 0xC0 Protocol version number 1 Hex Default value: 0x00 0x01: Redefine 0x84 current data, the unit is 10MA, and the highest bit is 0 for discharging. 1 means charging If discharging 20A, the data transmitted will be 2000 (0x07D0) If charging 20A, the transmission data is 34768 (0x87D0)

*** Note 1

Bit 0: Low capacity alarm 1 alarm 0 normal. Only warning 
1 bit: MOS tube over-temperature alarm
1 alarm 0 normal, alarm
2 digits: charging over-voltage alarm
1 alarm 0 normal, alarm
3 bits: Discharge undervoltage alarm
1 alarm 0 normal, alarm
4 bits: battery over temperature alarm
1 alarm 0 normal, alarm
5 bits: charging overcurrent alarm
1 alarm 0 normal, alarm
6 bits: Discharge overcurrent alarm
1 alarm 0 normal, alarm
7-bit: Cell pressure difference alarm
1 alarm 0 normal, alarm
8 bits: over-temperature alarm in the battery box 1 alarm 0 normal, alarm
9 bits: Battery low temperature alarm
1 alarm 0 normal, alarm
10 bits: monomer overvoltage alarm
1 alarm 0 normal, alarm
11 bit: monomer undervoltage alarm
1 alarm 0 normal, alarm
12 bits: 309_A protection
1 alarm 0 normal, alarm
13 bits: 309_B protection
1 alarm 0 normal, alarm
14 bits: reserved
15 bits: reserved
example:
0x0001: indicates the low capacity alarm value
0x0001 ----&gt; Low capacity alarm
0x0002 ----&gt; Power board over temperature alarm
0x0003 ----&gt; Low capacity alarm and power board over temperature alarm

Note2

Column: "BT3072020120000200521001"
*Product name: BT for battery
*Material system: iron-lithium code 1; manganese acid code 2; ternary code 3
*Voltage level: 48 for 48V series; 60 for 60V series; 72 for 72V series
*Capacity grade: 20 for 20AH specification
*Cycle life: 400 cycles use 04 mark, 1200 cycles use 12 mark
*Manufacturer code: Low-speed vehicle battery manufacturer's English code, if the manufacturer's English code is insufficient
Four bits, complemented by the character 0
*Production year: take the last two digits according to the actual production year; list the year of the battery produced in 2019
Part code "19"
*Production month: 1 — — December
*Production date: 01-31
*Production serial number: According to the Nth group of the model produced on the day of the manufacturer’s production date,
The number is N (for example: the first group of a certain model, then 001)

@Scotty-89
Copy link

Scotty-89 commented Jun 14, 2021

Hello,

i see this issue here and have some important informations for you ;)

and i got the Rs485 working but this was a lot of trouble...

first the Documentation you have is an very old one ... i got an "newer" version after some discussion with the distributer ;) they send me the protocol in Chinese but i but it into an translate .... i see you already have this also ;)

for Example they Change the Baudrate up to 115200 instead off 9600 ;) and even more ...

second the USB to RS485 dongle you use, you can but this into the trash on my side this wans working fine it received alswasy "random" byte sometime ...
my actual test bench you can see here: https://forum.drbacke.de/viewtopic.php?f=8&t=982

but now the Problem with the RS485...

I am able to read out the available values form the BMS but you cant write something and the response from the distributer was the RS485 is only for read not for write ...
and also it is not possible to read out the Current "Balance current" .... that sad :(

so with this i would say the Rs485 is not an alternative to the Bluetooth app ... and there fore i am currently searching for the Bluetooth protocol ... did someone have this ? or how the impl here was done ??? or is it the same and i only need to connect via BL ? what is whit UUID´s ???
maybe some one can help me here ?

@jblance
Copy link
Owner

jblance commented Jun 14, 2021

I have not seen a bluetooth protocol document - the current implmentation was from reverse engineering the comms between app and unit.
The BLE code is pretty rough at the moment, someone on https://diysolarforum.com/ has done a heap of investigation of the set commands for the bluetooth connection, but i havent had a chance to look at them in any depth

@Scotty-89
Copy link

Hey @jblance
where i can find the BLE Communication which is impl here ? maybe we will find something out ..

@jblance
Copy link
Owner

jblance commented Jun 15, 2021

The jkbms command with a port that is a MAC address will default to ble comms. There's some details in the usage doc

@logmod
Copy link

logmod commented Sep 19, 2022

I will test it when I finally receive my BMS. If it works I will share the results.

@bloddy
Copy link

bloddy commented Oct 18, 2022

@logmod Yes all their bms goes with vbat on the connector, because they have their own external uart<>rs485/can box .. and they need to power it :)

The implementation is not bad .. but they could have added a damn fast fuse on the pcb for the connector ...

@syssi You want uart<>uart opto or to other proto ?

If you need uart<>RS485

DFRobot Isolated RS485 to UART Signal Adapter Module tested it at 4KV this is my max limit .. and it was ok.

In my case I'm going on isolation from rs485 to RJ45, I'm using Industrial serial server, RS485 to RJ45 Ethernet from waveshare.

For the comm you only need rx/tx/gnd .. and gnd if you don't want to really couple it you can add an resistor over 10K and it should be in the safe spot.

Because for my need's I'm doing dynamic, voltage control, amperage control, base on some thresholds, all implementation goes between RS485 protocol.. mqtt(raspberry)<>HASS, and I like to have an history of the bank's ... and remote access :)

image
image

@logmod
Copy link

logmod commented Oct 18, 2022

Actually a nice idea to convert the serial output to IP, but I wanted to get rid of the RS485 converter and keep the connection to my board as simpel and safe as possible. Not sure to understand the remark about the 100k resistor, usually a 1k resistor is used to protect TTL inputs. Could you elaborate on that?

@bloddy
Copy link

bloddy commented Oct 18, 2022

I wanted to say 10K .. too many 0 :), edited, well think like this you have one isolation from uart<>rs485 and another one from rs485 to ether IP.

Advantage on this is that you can do whatever automation you want after with any kind of equipment .. and it's wire .. only rats can affect it :)

@logmod
Copy link

logmod commented Oct 20, 2022

@syssi I have found a cheap ready-made isolator board that would fit your requirements to get the TTL signal directly from the Bluetooth interface. Its from Hailege based on an ADUM1201 Dual Channel Digital Magnetic Isolator (available e.g. on Amazon). You can power it from inside the BMS board with the available 3.3V suppy. On the outside you can directly connect it to your GPIO and the outside 3.3V. Adding a DIP switch in the connector cable to pull down RST you could have a dual-solution (BLE/serial) in parallel.

isolator2

@MHunzalaAwan
Copy link

Got response from seller: I sent them this screenshot of Version information from Android App: Screenshot_20210513-144051

They sent back yet another protocol document in CHINESE.

BMS Protocol V2.5 CHINESE.pdf

I then put this through GOOGLE Translate:

BMS Protocol V2.5 ENGLISH (GOOGLE Translate).pdf

This protocol seems radically different to any other I have seen so far.

I gladly hand it over to you to take a bite at it. Let us know what you think. Kind regards.

Hi, I just wanted to know if this android app you used, runs on Bluetooth or it can also work with USB to otg connected to the mobile? If it can work using the USB to otg with the mobile, then can you please share the app? Thanks.

@abc2006
Copy link

abc2006 commented Dec 31, 2022

No need to reopen, just want to mention that this issue was same for me.
Communication didn't work, also got 0x00 as Answer.
Got rid of this Dongle and connected directly via RS485 TTL, and everything works fine.
Matching Plug is the Molex PicoBlade 1.25, but some JST 1.25 are also inbound, i will share the results as soon as they arrived.
And yeah, pay attention to the VCC-Pin, as there is full battery Voltage available.
Cheers,
Stephan

@abc2006
Copy link

abc2006 commented Jan 20, 2023

1.25mm 1.25 Micro JST Stecker 15cm Kabel
https://www.ebay.de/itm/183283879151?var=690577026311
^^These are the right ones, fit a little better than the Molex.
Could sb drop a Link to a TTL-USB-Converter over here? I'm struggeling with a bunch of not-working ones..
Maybe someone can also drop the specifications ...

@logmod
Copy link

logmod commented Jan 20, 2023

Try searching for ICQUANZX ADUM4160 on Amazon, specs for the BM board interface are in this thread.

@kadzsol
Copy link

kadzsol commented Feb 12, 2023

As I had no JST 1.25 connector at hand and did not want to cut the one from the RS485 converter, I have figured out how to use the converter with an ESP8266 to query the BMS.

As I use NODEMCU (LUA) for prototyping, first I had an issue with the RX serial buffer overflowing when receiving ALL the data at once at 115200 baud. So I had to figure out how to query only a certain value to receive less data and avoid the overflow:

voltage
4E57001300000000030300830000000068000001A9
current
4E57001300000000030300840000000068000001AA
capacity
4E57001300000000030300850000000068000001AB

The only stuff you have to change in the commands above is the code (83, 84, 85) and the CRC (sum of all values) to create your own query. See 5.1 BMS Read/Write data identification code in the table above to find your query code.

After this I still did not receive the data on the ESP but I was able to receive it with a PC using an RS485-to-USB converter. It turned out that the TTL-to-RS485 converter interfacing with the ESP was not able to switch back to receiving mode fast enough. So it missed the response of the BMS. I added a second TTL-to-RS485 module for separate sending and receiving and now it works just fine with the official converter.

The only drawaback of this approach is that I am also receiving my own command in front of the BMS response, but it is easy to filter it out in the software.

Hope this helps someone.

@SeByDocKy
Copy link

SeByDocKy commented May 10, 2023

Hello,

Seems with new hardware V11x, there are now both the UART-TTL (on GPS port) and RS485 on CAN bus. There are new options available on the appz

image

Anyone tried to communicate via RS485 (modbus RTU ?), especially now there is an option to select the (modbus) address....

image

I hope it means we can have several JKBMS v11x on the same bus...

@AD-Codex
Copy link

As I had no JST 1.25 connector at hand and did not want to cut the one from the RS485 converter, I have figured out how to use the converter with an ESP8266 to query the BMS.

As I use NODEMCU (LUA) for prototyping, first I had an issue with the RX serial buffer overflowing when receiving ALL the data at once at 115200 baud. So I had to figure out how to query only a certain value to receive less data and avoid the overflow:

voltage 4E57001300000000030300830000000068000001A9 current 4E57001300000000030300840000000068000001AA capacity 4E57001300000000030300850000000068000001AB

The only stuff you have to change in the commands above is the code (83, 84, 85) and the CRC (sum of all values) to create your own query. See 5.1 BMS Read/Write data identification code in the table above to find your query code.

After this I still did not receive the data on the ESP but I was able to receive it with a PC using an RS485-to-USB converter. It turned out that the TTL-to-RS485 converter interfacing with the ESP was not able to switch back to receiving mode fast enough. So it missed the response of the BMS. I added a second TTL-to-RS485 module for separate sending and receiving and now it works just fine with the official converter.

The only drawaback of this approach is that I am also receiving my own command in front of the BMS response, but it is easy to filter it out in the software.

Hope this helps someone.

As I had no JST 1.25 connector at hand and did not want to cut the one from the RS485 converter, I have figured out how to use the converter with an ESP8266 to query the BMS.

As I use NODEMCU (LUA) for prototyping, first I had an issue with the RX serial buffer overflowing when receiving ALL the data at once at 115200 baud. So I had to figure out how to query only a certain value to receive less data and avoid the overflow:

voltage 4E57001300000000030300830000000068000001A9 current 4E57001300000000030300840000000068000001AA capacity 4E57001300000000030300850000000068000001AB

The only stuff you have to change in the commands above is the code (83, 84, 85) and the CRC (sum of all values) to create your own query. See 5.1 BMS Read/Write data identification code in the table above to find your query code.

After this I still did not receive the data on the ESP but I was able to receive it with a PC using an RS485-to-USB converter. It turned out that the TTL-to-RS485 converter interfacing with the ESP was not able to switch back to receiving mode fast enough. So it missed the response of the BMS. I added a second TTL-to-RS485 module for separate sending and receiving and now it works just fine with the official converter.

The only drawaback of this approach is that I am also receiving my own command in front of the BMS response, but it is easy to filter it out in the software.

Hope this helps someone.

what is the BMS response for this request ?
Is the response like 4E570013000000000303008317A4000068000001A9

@kadzsol
Copy link

kadzsol commented May 10, 2023

what is the BMS response for this request ?
Is the response like 4E570013000000000303008317A4000068000001A9

4E57001300000000030300830000000068000001A9

@AD-Codex
Copy link

4E57001300000000030300830000000068000001A9 is the command to get voltage value from the BMS. I need the an example that what kind of reply (receiving data ) from the BMS.
Is it like the same request command but after /x83 first 2 hex numbers represent the value of voltage.

request - 4E57001300000000030300830000000068000001A9
received data - 4E570013000000000303008317A4000068000001A9

@Woodstockskipper
Copy link

I made a translation file in excel from my project:
BMS commands and receives.xlsx
I hope this helps

@Maikel-K
Copy link

Hello,

Seems with new hardware V11x, there are now both the UART-TTL (on GPS port) and RS485 on CAN bus. There are new options available on the appz

image

Anyone tried to communicate via RS485 (modbus RTU ?), especially now there is an option to select the (modbus) address....

image

I hope it means we can have several JKBMS v11x on the same bus...

Anybody tried this? I need comms with 9 BMSes!

@lucize
Copy link

lucize commented Feb 9, 2024

Hello,
Seems with new hardware V11x, there are now both the UART-TTL (on GPS port) and RS485 on CAN bus. There are new options available on the appz
image
Anyone tried to communicate via RS485 (modbus RTU ?), especially now there is an option to select the (modbus) address....
image
I hope it means we can have several JKBMS v11x on the same bus...

Anybody tried this? I need comms with 9 BMSes!

it works on native Modbus but can't seems to find the registers on the internet and jk never replyed to my request, there are some here:

addr,meaning
0,battery voltage
1,number of cells
2, percent
3,capacity
4,charging ampere
5,?discharging?
6,temp1
7,temp2
8,tube temp
9,cell1
10,cell2
11,cell3
12,cell4
13,cell5
14,cell6
15,cell7
16,cell8
17,cell9
18,cell10
19,cell11
20,cell12
21,cell13
22,cell14
23,cell15
24,cell16
25,cell17
26,cell18
27,cell19
28,cell20
29,cell21
30,cell22
31,cell23
32,cell24

also found some on 1000+10 but don't know the meaning of them and still trying to scan all registers, I guess that an automation would we faster

@lukolszewski
Copy link
Contributor

Does anyone know if there is any software that can parse this protocol yet? They issue was closed twice, but I'm not seeing any solution. I can send byte series mentioned and receive replies, but I was wondering if there already is a parser that works?

@lucize
Copy link

lucize commented Aug 18, 2024

now that esphome has modbus server support should be very easy to implement, use a modbus sniffer and see what address the inverter is asking and then use the address to query the jk-bms inverter to see what actual data is sent on those addresses, maybe I'll do a map as now I have one of those bms.
Or I think you can use only esphome as it will show in the logs what address is being asked

@kadzsol
Copy link

kadzsol commented Aug 18, 2024

Does anyone know if there is any software that can parse this protocol yet? They issue was closed twice, but I'm not seeing any solution. I can send byte series mentioned and receive replies, but I was wondering if there already is a parser that works?

https://github.com/stamina84/jk-bms/blob/main/serial/read_bms.py

@syssi
Copy link
Contributor

syssi commented Aug 18, 2024

Please keep in mind we are probably talking about different device models / modbus register addresses / ports of the BMS here. On pretty new device models the protocol of the different UARTs is configurable now.

These are the modbus registers of the JK-BMS PB (inverter) series:

https://github.com/syssi/esphome-jk-bms/blob/main/docs/pb2a16s20p/BMS%20RS485%20Modbus%20V1.1.pdf
https://github.com/syssi/esphome-jk-bms/blob/main/esp32-jk-pb-modbus-example.yaml

This protocol is called GPS protocol:

Request >>> 4E:57:00:13:00:00:00:00:06:03:00:00:00:00:00:00:68:00:00:01:29
Response <<< 4E:57:01:18:00:00:00:00:06:00:01:79:27:01:0F:FC:02:0F:CF:03:0F...

@lucize
Copy link

lucize commented Aug 18, 2024

I'm talking about the most easy way, as in the new inverter bms there is the pylon modbus protocol as option and I think this ia the standard on many inverters so nothing fancy should be needed there, just the registers, and yes the data could be gained by using the gps port or ble and maybe the limited can/rs485 has enough data to be used also, of course with all that charging algorithm

@lucize
Copy link

lucize commented Aug 18, 2024

Please keep in mind we are probably talking about different device models / modbus register addresses / ports of the BMS here. On pretty new device models the protocol of the different UARTs is configurable now.

These are the modbus registers of the JK-BMS PB (inverter) series:

https://github.com/syssi/esphome-jk-bms/blob/main/docs/pb2a16s20p/BMS%20RS485%20Modbus%20V1.1.pdf https://github.com/syssi/esphome-jk-bms/blob/main/esp32-jk-pb-modbus-example.yaml

This protocol is called GPS protocol:

Request >>> 4E:57:00:13:00:00:00:00:06:03:00:00:00:00:00:00:68:00:00:01:29
Response <<< 4E:57:01:18:00:00:00:00:06:00:01:79:27:01:0F:FC:02:0F:CF:03:0F...

the registers presented are useful only as a bms monitor not actually what the inverter is asking on the battery side

as an off-topic, I'm using this method to read the bms data but some values from time to time are with errors, like 4s valid data 2s some aproximate value, did someone has this issue or it's my modbus adapter is at fault, tried also the new 9600 bit rate available on the new firmware

@syssi
Copy link
Contributor

syssi commented Aug 18, 2024

Let's have a look into the supported protocols of this project (mpp-solar):

JK232

Request frame: 0xDD 0xA5 0x03 0x00 0xFF 0xFD 0x77

https://github.com/jblance/mpp-solar/blob/master/mppsolar/protocols/jk232.py

This protocol was the protocol of the BMS firmware version <4.

JK485

equest frame: 0x55 0xAA 0x01 0xFF 0x00 0x00 0xFF

https://github.com/jblance/mpp-solar/blob/master/mppsolar/protocols/jk485.py

This is the protocol of a pretty old Active Balancer called JK-DZ11-B2A24S.

JK02/JK02_32/JK04

Request frame: 0xAA 0x55 0x90 0xEB ...

https://github.com/jblance/mpp-solar/blob/master/mppsolar/protocols/jk02.py
https://github.com/jblance/mpp-solar/blob/master/mppsolar/protocols/jk02_32.py
https://github.com/jblance/mpp-solar/blob/master/mppsolar/protocols/jk04.py

This is the BLE communication (jk04 is the oldest one, jk02 was used up to firmware version 11, jk02_32 is currently used protocol).

JKSERIAL

Request >>> 4E:57:00:13:00:00:00:00:06:03:00:00:00:00:00:00:68:00:00:01:29
Response <<< 4E:57:01:18:00:00:00:00:06:00:01:79:27:01:0F:FC:02:0F:CF:03:0F...

This is the UART-TTL / GPS port protocol.

https://github.com/jblance/mpp-solar/blob/master/mppsolar/protocols/jkserial.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests