Close
0%
0%

JBD BMS protocol

In this project, I tried to deal with the BMS communication protocol, which is compatible with the JBDTool program.

Similar projects worth following
In this project, I tried to deal with the BMS communication protocol, which is compatible with the JBDTool program.
A part of the protocol is available from the manufacturer.
But this part describes only a request for common data.
The process of configuring BMS and writing / reading logs in the documentation is missed.

Standard requests to BMS in the form of a request for basic data, secondary voltage and names in the ASCII line are parsed in the file (from the manufacturer).
I will not analyze them.

Further, the deals with undocumented features in the form of reading / writing EEPROM.

BMS class.zip

See https://hackaday.io/project/162806-jbd-bms-protocol/log/166769-code-for-working-with-bms

x-zip-compressed - 6.15 kB - 08/08/2019 at 06:18

Download

LH_SP10S006 20180612-1.hex

Firmware for BMS

hex - 62.11 kB - 06/04/2019 at 08:23

Download

x-zip-compressed - 2.17 MB - 12/14/2018 at 10:16

Download

Adobe Portable Document Format - 635.63 kB - 12/14/2018 at 09:43

Preview
Download

x-zip-compressed - 325.18 kB - 12/14/2018 at 09:43

Download

View all 6 files

  • Code for working with BMS

    rahmaevao08/08/2019 at 06:40 0 comments

    Introduction

    The files below I used in my project to communicate with BMS.
    My project uses two types of BMS: JBD or Lithuanian BMS.

    I am using STM32F303.

    My implementation is very sophisticated. Therefore, I did not post it for a long time. But the people are asking, so hold on.

    How i worked with this class?

    1. Attached the header file:

    #include "BMS.hpp"

    2. I did create global variables (in main.cpp):

    //For BMS
    HAL_StatusTypeDef bufferHalStatus = HAL_OK;
    uint8_t * requestMessage = new uint8_t[9];
    uint8_t lenRequestMessage = 7; ///< 7 For China BMS. Change if used Tiny BMS. 
    uint8_t * dmaBuffer;
    uint16_t lenDmaBuffer = 34; ///< length message from Tiny BMS
    BmsData batteryData;

     2. Enabled DMA Fill and Timer Interrupts.

    // For BMS
    	HAL_NVIC_DisableIRQ(DMA1_Channel6_IRQn);
    	HAL_NVIC_DisableIRQ(TIM6_DAC_IRQn);

     3. In the thread, the BMS has defined a message that will be sent after a response from the BMS.

    	requestMessage[0] = 0xDD;
    	requestMessage[1] = 0xA5;
    	requestMessage[2] = 0x03;
    	requestMessage[3] = 0x00;
    	requestMessage[4] = 0xFF;
    	requestMessage[5] = 0xFD;
    	requestMessage[6] = 0x77;

     4. Defined a dma buffer, created an instance of the BMS class. Launched the mode of automatic sending requests to BMS.

    dmaBuffer = new uint8_t[lenDmaBuffer];
    BMS bms;
    bms.autoSenderModeEnable();

    5. I read data with bms in a loop. In the case of a successful read (batteryData.halStatus == HAL_OK), you can work with data.

    for (;;) { batteryData = bms.readBmsData(); if (batteryData.halStatus == HAL_OK) { telemetryMessage.ADC_battery = batteryData.chargePercentage; /*.more.*/ } else { /* error */ }

    6. Below stm32f3xx_it.c file:

    /**
     * @brief Handler interrupt DMA1 channel6.
     * 
     * 1. Resets timer 6 for reset timeout event BMS UART BUS.
     * 2. Sends a new request to the BMS.
     */
    void DMA1_Channel6_IRQHandler(void) {
    
    	if (((DMA1->ISR) & DMA_ISR_TCIF6) != 0)
    	{
    		// 1. Resets timer 6 for reset timeout event BMS UART BUS.
    		bufferHalStatus = HAL_OK;
    		timeout500msAlreadyBeen = 0;
    		__HAL_TIM_SET_COUNTER(&htim6, 0);
    
    		// 2. Sends a new request to the BMS
    		bmsInterruptedCountRxDMA++;
    		//HAL_UART_Transmit(&huartBMS, requestMessage, lenRequestMessage, 100);
    	}
    	
    	HAL_DMA_IRQHandler(&hdma_usart2_rx);
    }
    /**
     * @brief Handler interrupt TIM6
     * 
     * Intended for set timeout event if blank UART more 1 sec.
     * After 0,5 с - send requset message.
     * Thereafter 0,5 sec set timeout.
     */
    void TIM6_DAC_IRQHandler(void) {
        HAL_TIM_IRQHandler(&htim6);
        
        if (timeout500msAlreadyBeen == 1) {
            bufferHalStatus = HAL_TIMEOUT;
        }
        
        bmsInterruptedCountTim6++;
    //    HAL_UART_Transmit(&huartBMS, requestMessage, lenRequestMessage, 100);
    //    HAL_UART_Receive_DMA(&huartBMS, dmaBuffer, lenDmaBuffer);
        timeout500msAlreadyBeen = 1;
    }
    
    

     If you have questions, then write in telegram.

  • BMS current consumption

    rahmaevao06/11/2019 at 11:52 0 comments

    I measured the currents of the consumption of the BMS itself.

    The results are below.

    ModeCurrent consumption
    The load is not connected, the LED on the board is not on.70 uA, and every five seconds 150..200 uA
    The load is not connected, the LED on the board is not on, BMS connected to PC through UART100 uA, and every five seconds 200 uA
    LED on the board is on18 mA

  • Change of firmware

    rahmaevao06/04/2019 at 08:25 0 comments

    The manufacturer shared the firmware for BMS from 12.06.2018. We really liked this firmware, as it works adequately with the button. The images below show how the firmware changes. Firmware In here.

View all 3 project logs

  • 1
    Process of reading configs (EEPROM)

    1. To switch to the EEPROM mode, you need to send the first packet to write to the zero register of the value: 0x56 0x78.

    In response, zeros arrive (see figure below).

    2. Then read (0xA5) registers from 0x10 to 0xA2 and 0xAA.

    In figure below shown meaning registers (but I'm not sure about the accuracy of everything).

    3. After reading, the write command to the register 0x01.

    Without the start packet and the final, an error (0x80) is returned when the configuration registers are requested or changed.

  • 2
    Error counter

    1 BMS stores in memory the fact of errors that can be configured in JBD Tools.
    It is useful to read them every time you start a device with BMS to analyze past events. After reading them, you need to pack them up so that next time you can only read actual events.


    Reading is possible only in EEPROM reading mode (see step 1).

    2 The command to read the register 0xDD 0xA5 0xAA 0x00 0xFF 0x56 0x77.
    Register that stores error counters 0xAA. The table below shows the meaning of each byte in sending a reply from BMS to the request 0xAA. High byte in front.

    Byte in the packageMeaning
    4-5SC count
    6-7CHGOC (Charge Over Current)
    8-9DSGOC (Discharge Over Current)
    10-11COVP (Cell Over Voltage Protection)
    12-13CUVP (Cell Under Voltage Protection)
    14-15CHGOT (Charge Over Temperature)
    16-17CHGUT (Charge Under Temperature)
    18-19DSGOT (Discharge Over Temperature)
    20-21DSGUT (Discharge Under Temperature)
    22-23POVP (Pack Over Voltage Protection)
    24-25PUVP (Pack Under Voltage Protection)

    3 Reset errors
    Error reset occurs by writing to configuration register 0x01.
    The package: 0xDD 0x5A, 0x01, 0x02, 0x28, 0x28, 0xFF, 0xAD, 0x77.

View all instructions

Enjoy this project?

Share

Discussions

Dennis wrote 07/18/2019 at 00:07 point

Hello there. This page has been very helpful, thank you! But I have one problem. I updated my bms firmware and now it cannot read the cell voltages. Any idea whats wrong?

  Are you sure? yes | no

rahmaevao wrote 08/07/2019 at 06:34 point

Hello, my friend.
Hmm. What is your BMS. What firmware file?

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates