Giter Site home page Giter Site logo

libresolar / bms-firmware Goto Github PK

View Code? Open in Web Editor NEW
134.0 14.0 67.0 3.52 MB

Firmware for LibreSolar BMS boards based on bq769x0, bq769x2 or ISL94202

Home Page: https://libre.solar/bms-firmware/

License: Apache License 2.0

C 98.01% CMake 1.66% Shell 0.32%

bms-firmware's Introduction

Libre Solar BMS Firmware

build badge

This repository contains the firmware for Libre Solar Battery Management Systems based on Zephyr RTOS .

Development and release model

The main branch is used for ongoing development of the firmware.

Releases are created from main after significant updates have been introduced to the firmware. Each release has to pass tests with multiple boards.

A release is tagged with a version number consisting of the release year and a release count for that year (starting at zero). For back-porting of bug-fixes, a branch named after the release followed by -branch is created, e.g. v21.0-branch.

Documentation

The firmware documentation including build instructions and API reference can be found under libre.solar/bms-firmware.

In order to build the documentation locally you need to install Doxygen, Sphinx and Breathe and run make html in the docs folder.

License

This firmware is released under the Apache-2.0 License.

bms-firmware's People

Contributors

ananyaaynana avatar case06 avatar garaminowicz avatar jalinei avatar krzysztof9nowak avatar martinjaeger avatar pasrom avatar xsider avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bms-firmware's Issues

API source code

We want to add the following recovery features to the firmware:
Short circuit recovery, discharge overcurrent recovery and charge overcurrent recovery.
`

uint8_t dis_sc_recovery_s; ///< Discharge short circuit recovery time (s)

uint8_t dis_sc_scdl_dec_delay_s; ///< Discharge short circuit latch delay (s)

uint8_t dis_sc_scdl_latch_limit;    ///< Discharge short ciruit latch limit (s)

int16_t dis_sc_scdl_recover_time_s; ///< Discharge short circuit recover time(s)

int16_t dis_sc_scdl_recovery_threshold_mA; ///< Discharge short circuit latch recovery limit (mA)`

int16_t dis_oc_recovery_current_mA;     //< Recovery current of discharge overcurrent(mA)

uint8_t recovery_time_s;                //< Recovery time of discharge overcurrent(s)

uint8_t dis_oc_counter_dec_delay_s;     //< Delay for detection of discharge overcurrent.(s)

uint8_t dis_oc_latch_limit;             //< Latch limit for discharge overcurrent.

int16_t dis_oc_latch_recovery_mA;       //< Latch limit recovery current for discharge overcurrent.(mA)

uint8_t dis_oc_latch_recovery_time_s;   //< Latch limit revcovery time for discharge overcurrent.(s)`

In the firmware to set these values the API
static inline int bms_ic_configure(const struct device *dev, struct bms_ic_conf *ic_conf, uint32_t flags)
is called.

After adding these recovery modifications to the struct bms_ic_conf structure the configure(dev, ic_conf, flags) will apply the changes to the appropriate register address indicated by the BMS_IC_CONF_CURRENT_LIMITS flag. Is my understanding correct?

The source code for the configure(dev, ic_conf, flags), I am not able to find it.

I can share the code for the recovery modifications added to this commit: https://github.com/LibreSolar/bms-firmware/tree/cb89c75b74e85a036b7c6243424e31c68b3b3018 written for the 0.3v BMS code.

Please let me know where to access the configure(dev, ic_conf, flags) source code to add the recovery modifications to the firmware.

BQ76952

Hi @martinjaeger ,

Do you have any plan to support BQ76952?

The BQ76952 has several differences from the BQ76940. The voltage and current measurement accuracy are improved, the measurement speed is much faster, the BQ76952 drives high-side FETs, it supports additional communication protocols, it includes automated cell balancing and automated FET control to recover from protection faults. If the BQ76940 meets your needs, it is a good device and may be simpler to understand its limited features. The BQ76952 is our newest industrial battery monitor with better performance and features.

TI

BMS communication error

Hi again,

Long time passed but, as you might remember i rolled my own hardware based on your "15s80" and "switch n sense" in here: LibreSolar/bms-15s80-sc#6
I solved all my hardware problems as far as i am aware but i am having issues with recent bms firmware. Here is some 3d pictures for playing along at home:

3D

Pack1

Pack2

Pack3

I will open source all of this work on my github when i test pack enough.

Anyway first of all i setted up a new virtural machine and created new enviroment to compile new firmware and started from fresh.
I will use this battery pack in electric go kart (for my kid) with hooverboard motor and ESC. It is in 9s2p configuration, my battery specs are:

Each Cell Capacity: 2900 mAh
Battery Pack Total Capacity: 5.8Ah
Battery Pack Voltages: Max Nominal Min: 37,8V 33,12V 22,5V
Chemistry: Lithium nickel manganese cobalt oxide (Li-NMC)

I cloned "main" repository and build firmware with following changes to fit it on my hardware design which is almost identical with "15s80" hardware design. Same MCU same pinouts etc.

I changed "Max number of cells" to 10 (I believe bms firmware auto detects cell count.)

"Max number of thermistors" to 2,

"Battery nominal capacity" to 10, (I cannot set to 5.8Ah for my battery firmware doesn't allow me to set it?)

"Cell type" to NMC/Graphite 3.7V nominal 4.2 max, (Only for testing i choose this. My cells are supporting more than this range but for testing it's enough i believe)

"Default period (s) for live metrics" to 2 seconds,

then i changed as below:

SS4

board-max-current to 10

shunt-resistor-uohm to 4000

used-cell-channels to 0x3FF (My hardware have 76930)
( bq76920 (3-5s): 0b0000_0000_0001_1111 = 0x001F
bq76930 (6-10s): 0b0000_0011_1111_1111 = 0x03FF
bq76940 (9-15s): 0b0111_1111_1111_1111 = 0x7FFF)

and changed some parameters for my eeprom model.

Also i changed thermistor beta value to 3950.

The problem is when i compile firmware and upload to board ant test this out i get below errors:

"Loading data from storage failed"
and
"BMS coommunication error"
then i cannot see any voltages from battery and it doesn't work obviously.

Here is a screenshot of this error:
SS2

I believe MCU cannot speak with bq chip, but as you may see on screenshot it gives battery tempratures how this is possible if it cannot communucate with it?

I tested with an older firmware which i compiled before with same hardware:

SS3

Which is working OK. But i want to use more recent version because of for example "cell temps","ic temps", "mosfet temps" etc. and it compiles and works without modifying prj.conf file for "newlibc nano" and "heap" size parameters.

Also another question you might call me a newbie but i cannot decode "error flags","bms state" or "balancingstatus" codes i mean for example 0x00000280 error code mean?or bms state 3 means? I am not good at coding but I checked and read source code (bms_common.h, bms_ic.h, bq769x0.c) many times but i cannot figure it out. Is there any easy way to decode this codes?

Regards all.

Re-arrange OLED-display output to support max. cell-number

The current version supports up to 12 cells so far. For showing the output of the max possible number of 15 cells, its necessary to re-arrange the layout, to gain one more row, which is needed to display all 15 cells in 3 columns and 5 rows. This will be some fizzy work (i'll do it later, when i deploy my BQ40 board) but should be in general possible on a 128x64 display: we need 7 rows in total, which gives us 9 points per row; that is 8 points font-size/height plus 1 point for a separation line between the rows.

Add hardware or software watchdog

The firmware should get a watchdog to supervise the threads and BMS control.

Maybe a single hardware watchdog supervising the main thread is sufficient. Otherwise the task watchdog should be used.

add timer for logging-output frequency

The logging-output happens way more faster than it is necessary for this kind of application and therefore generates too much traffic, which also means a (little) waste of energy. A timer should be added to the calls within main.cpp, so the user can define an appropriate period by settings. As default value i recommend a period of 10s .

QEMU Build Target

I'm working on a project where I would like to be able to use a VM to run this BMS. I know ZephyrOS supports QEMU VMs as targets, but I'm not sure of the steps required to get a LibreSolar BMS VM. I tried just building it using west build -b qemu_x86 but a series of errors from #define statements in devicetree.h cause the build to fail. I'm going to start working through the errors and see how far I get but wanted to check on here to see if anyone already has some knowledge that might help me out. Thanks!

Edit: forgot to mention, I'm building against v23.1, I noticed that commit f0ff664 from two weeks ago does some refactoring and the error messages are different between v23.1 and f0ff664, perhaps someone with more insight can weigh in and point me in the right direction here?

Regarding Potential RS485 Support

Are there any plans to incorporate RS485 functionality in future releases?
If such plans exist, is there a rough timeframe or priority level associated with their implementation?

The inclusion of RS485 capabilities would greatly enhance the project's versatility for applications requiring communication over longer distances or in multi-drop configurations.

Thingset Synchronization with bq76952 Initialization

Description:

Feasibility of using semaphores to synchronize the execution of the Thingset with the initialization of the bq76952. Currently, when the live publication is enabled thingset executes before bq76952 is initialized. This leads to the publication of incorrect values.

Current Approach:

A few changes made by us to the code currently employ semaphores to ensure data consistency between the PC-provided current, voltage, and temperature inputs, and the SOC (State of Charge) output received from the board. This approach guarantees that the Thingset operates with synchronized data sets.

Proposed Synchronization with bq76952:

Would a semaphore-based synchronization method ensure the Thingset only starts execution after the bq76952 has finished initializing be feasible? This would prevent the Thingset from using potentially invalid or incomplete data during its initial execution phase.

Can semaphores be effectively utilized to achieve synchronization between the Thingset and bq76952 initialization?
Are there any potential drawbacks or limitations to this approach?

ISL94202: Auto-detect number of cells

The number of cells is currently still hard-coded and set in bms_init_hardware() in bms_isl94202.c.

The ISL94202 does not automatically detect the number of cells. It has to be written to a register.

Possible algorithm:

  • Start with 8 cells enabled.
  • Measure voltages and find out actual number of cells (including plausibility-check with pack voltage)
  • Set number of cells in chip.

How to use serial port used by thingset for data download

We want to download to the BMS C1 cell characterization data (that is a few kilo bytes in size) over the same serial port used by thingset.

The cell characterization data consists of 19 arrays of type double. Each array has different number of elements typically exceeding 200.

How will we do this?

Error flag 1 on connecting the board to a battery pack

Description:
When the BMS is brought up an error flag 1 is always present. Error flag 1 indicated cell Undervoltage. None of the cells are below the value of 2.5V for LFP cell. Here is a picture on the thingset app:
WhatsApp Image 2024-04-04 at 5 59 35 PM

Once I run the west espressif monitor the error flag is cleared like in this picture:
WhatsApp Image 2024-04-04 at 7 10 16 PM

Double-checked the connections and it looked fine. This happens every time the BMS is brought up.

Questions Regarding using Multifunctional Pin controls as thermistors

I'm reaching out with a few questions regarding the Battery Management System (BMS) configuration in the codebase.

Shunt Temperature Measurement:
I'm exploring the bms_c1.dts file to understand shunt temperature measurement. I couldn't locate the configuration for the DFETOFF pin. Is shunt temperature currently measured and used to trigger alerts in the BMS system?

Default Values in BQ769X2_INIT Macro:
I'm curious about the configuration of temperature and discharge pins in the BQ769X2_INIT macro. While ts1_pin_config has a default value of 0x07, ts3_pin_config and dchg_pin_config seemingly don't. Could you explain the thinking behind this distinction?

DCHG Pin Configuration:
In the code, dchg_pin_config is set to the default value (0x07). The BQ769X2 datasheet (section 6.4) recommends 0x0F for FET temperature measurement. I'm curious to understand the reasoning behind using the default value in this case.

Understanding these points would be very helpful.

Function `bms_soc_update` no longer called post-zephyr bms driver update

After the recent Zephyr driver update (commit f0ff664), the bms_soc_update function seems to have stopped being invoked. This has led to the State of Charge (SoC) no longer being calculated. Prior to this update, the function was regularly called at this location:

void bms_update(Bms *bms)
{
bms_read_voltages(bms);
bms_read_current(bms);
bms_soc_update(bms);
bms_read_temperatures(bms);
bms_update_error_flags(bms);
bms_update_balancing(bms);
}

Could you advise on the best location for invoking bms_soc_update in the current code framework to maintain precise SoC measurements?

Warning when sending CAN data

Testing the CAN interface on a custom board similar to 0.4v of BMS C1.
On the serial interface getting this as the output:
Screenshot from 2024-03-16 14-19-53
With a warning saying that unable to send CAN frame since it is too large.
The output of the CAN software was this:
image
What can be the cause of this warning?

Firmware used: 50b5bc5

BMS C1: LEDs Turn Off, 'No Serial Data Received' Error, and Flashing Problems

Issue:
I tried updating to the latest firmware version "v23.1-1-g55c2ea2-dirty," but encountered two issues:
The red and green LEDs switch off and get the error "A fatal error occurred: No serial data received." when attempting to flash the code and the LEDs can only be turned on using the S2 button.

Steps Taken:
I created an overlay file (as in https://libre.solar/bms-firmware/src/dev/customization.html) in the app folder with the following code:
{
chosen {
thingset,serial = &usb_serial;
};
}

I then built and flashed the code using the "west flash" command. When attempting to monitor the board using the "west espressif monitor" command, I encountered the following output:
Screenshot from 2023-11-10 18-45-03

Additionally, when I tried to flash the code again, red and green leds turn off but there is voltage at the bat+, bat-, pack+ and pack-.
Screenshot from 2023-11-10 19-11-57

When the leds are off the "west espressif monitor"command gives this:
Screenshot from 2023-11-10 19-18-07

On exiting the espressif monitor not able to flash code again. On holding down the S2 button the leds turn back on after blinking for a few seconds.

Any guidance on resolving these issues. Specifically, I need help with:

  1. Understanding why the code flashing is not happening and why the LEDs are turning off.

Additional Information:

Board Model: Libre Solar BMS C1 (v0.3)
Firmware Version: v23.1-1-g55c2ea2-dirty.

ISL94202: Balance only when not measuring voltages

The cell voltage measurements are obviously very noisy if measured during balancing:

image

Unfortunately, the settings for automatic balancing don't seem to allow measurements only when not balancing (unless balancing period is kept very short).

ToDo: Further investigations. Maybe balancing has to be controlled via the MCU.

Inaccurate battery voltage detection accuracy

During the test, I found that the error of battery 1 was a little large. The voltage measured by the multimeter is 3.83V. How should this be adjusted?

{"rBat_V":22.38,"rBat_A":0.00,"rBat_degC":-58.8,"rSOC_pct":100.0,"rErrorFlags":320,"rBmsState":0,"rCells_V":[3.696,3.826,3.819,3.828,3.829,3.821,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":3.803,"rCellMin_V":3.696,"rCellMax_V":3.829,"rBalancingStatus":0}

I2C error

Hardware used:
Using a custom board with the same I2C configuration as the 0.4v bms_c1 board. GPIO8 is SDA and GPIO9 is SCL.
Screenshot from 2024-02-29 14-14-53

Description of the issue:
We are using the bms_c1 firmware(code for 0.3v BMS board) at this commit https://github.com/LibreSolar/bms-firmware/tree/cb89c75b74e85a036b7c6243424e31c68b3b3018. An app.overlay file that updates the I2C pins to match the I2C configuration of the 0.4v bms_c1 board.
A few modifications have been done to the BMS firmware such as recovery for overcurrent in charge and discharge, short circuit and current calibration. We want to test these modifications in the lab before pushing the code to the bms_firmware repository.

When the firmware is flashed on the custom board getting this error:
Screenshot from 2024-02-29 14-08-50

Probing test points 12 and 13 revealed no observable signal waveforms on SDA and SCL lines.

app.overlay:
Screenshot from 2024-02-29 14-57-59

Impact:
Not able to execute the firmware with and without recovery modifications.

Zephyr version: v3.4
commit: b7e659cdd3088609c1e0b9d7f925a811c006f6bd

project build issue

I want to test this code, but I can't create it. I successfully tested other similar codes, but this code is not. Is it caused by the environment? Here is my error code. What can you do to help me solve it? Thank you!!!
Error: unrecognized opcode csrrc a5,mstatus,8' Error: unrecognized opcode csrw mtvec,t0'
unrecognized opcode `csrs mstatus,s2'

OV/UV_TRIP config kind of return probaly off by 1000 * (set im V return in mV)

sorry very short

ic_conf->cell_uv_limit =
(1U << 12 | uv_trip << 4) * dev_data->adc_gain / 1000 + dev_data->adc_offset;

of by a factor of 1000 (adc_gain is in µV/LSB)

ic_conf->cell_uv_limit =
    ((0x1000UL | (uv_trip << 4)) * dev_data->adc_gain / 1000.0 + dev_data->adc_offset) / 1000.0;

ic_conf->cell_ov_limit =
(1U << 13 | ov_trip << 4) * dev_data->adc_gain / 1000 + dev_data->adc_offset;

of by a factor of 1000 (adc_gain is in µV/LSB)
and
for ti manual SLUSBK2I – page 22 OV trip level is mapped to “10-XXXX-XXXX–1000”.

therefor the (1U << 13 | ov_trip << 4) should probaly be (1U << 13 | ov_trip << 4|0x8) to match the effective value

ic_conf->cell_ov_limit = 
   ((0x2008UL | (ov_trip << 4)) * dev_data->adc_gain / 1000.0 + dev_data->adc_offset) / 1000.0;

BMS current limit values configuration via thingset

When updating the nominal capacity of the battery pack using thingset the discharge overcurrent limit, discharge short circuit limit and charge overcurrent limit is not updated according to the updated nominal capacity of the battery pack.

Discharge overcurrent limit, discharge short circuit limit and charge overcurrent limit are modified according to the nominal capacity of the pack in the bms_init_config function but when the nominal capacity is updated via thingset these threshold values are not updated according to the updated nominal capacity of the pack.

In bms_init_config function the short circuit limit is calculated as bms->ic_conf.dis_sc_limit = bms->ic_conf.dis_oc_limit * 2; where bms->ic_conf.dis_oc_limit = bms->nominal_capacity_Ah;.

When bms.nominal_capacity_Ah is updated via thingset dis_sc_limit value is calculated based on the old nominal_capacity_Ah since in bms_ic_bq769x2_configure function the bms.nominal_capacity_Ah is not updated.

The discharge overcurrent limit, discharge short circuit limit and charge overcurrent limit has to be entered separately.

When the bms.nominal_capacity_Ah value is updated via thingset how to update it in the bms_ic_bq769x2_configure function?

This feature can be used to test the BMS board using battery simulator and electronic load tester.

Flashing of firmware for BMS with ESP32-C3 MCU

Depending on the version of the factory programmed firmware on the ESP32-C3 it may have a bug that leads to frequent disconnects of the USB serial and re-enumeration of the device.

The solution is to try multiple times to flash firmware built with most recent ESP-IDF (e.g. the hello world example from ESP-IDF or directly the BMS firmware) until it succeeds. After a new custom firmware is flashed once, the error should be gone.

BMS with BQ769x0 does not recover from overvoltage/undervoltage

There is an issue when the battery is complete full or complete empty at BMS15S80.
If overvoltage/undervoltage occurs, the MOSFETs remain open and do not switch on again. A reset of BMS is needed to recover from that state. Pull request already created.

The board stops working

I finished a board last week and is testing its performance. But it's strange. It starts for a while and then reports an error. After it restarts, it will be fine again. I can't understand this error. Can you help me to read it? In addition, I found that when it was just started, there would be no detection data. This is the result of the shutdown after pressing S1, and then the restart after pressing S1.The following is my error message:
#mSerial {"rBat_V":8.46,"rBat_A":0.00,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":2,"rBmsState":2,"rCells_V":[0.651,0.136,0.124,0.350,1.058,6.060,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x15 (USB_UART_CHIP_RESET),boot:0xf (SPI_FAST_FLASH_BOOT)
Saved PC:0x4201ac50
SPIWP:0xee
mode:DIO, clock div:2
load:0x3fcd6100,len:0x15e4
load:0x403ce000,len:0x920
load:0x403d0000,len:0x2c4c
SHA-256 comparison failed:
Calculated: f92edd0762896a9fa673795fc470e6fa77cf833e5c0950e4978b697f167c1bb4
Expected: 5575fe58924c1e08c5eadfa2ba7862131ebe09b778e446c7d1ed87641a26bbfa
Attempting to boot anyway...
entry 0x403ce000
�[0;32mI (43) boot: ESP-IDF 2cb20ac6c 2nd stage bootloader�[0m
�[0;32mI (43) boot: compile time 14:42:43�[0m
�[0;32mI (43) boot: chip revision: 3�[0m
�[0;32mI (45) boot.esp32c3: SPI Speed : 40MHz�[0m
�[0;32mI (49) boot.esp32c3: SPI Mode : DIO�[0m
�[0;32mI (54) boot.esp32c3: SPI Flash Size : 4MB�[0m
�[0;32mI (59) boot: Enabling RNG early entropy source...�[0m
�[0;32mI (64) boot: Partition Table:�[0m
�[0;32mI (68) boot: ## Label Usage Type ST Offset Length�[0m
�[0;32mI (75) boot: 0 nvs WiFi data 01 02 00009000 00006000�[0m
�[0;32mI (83) boot: 1 phy_init RF data 01 01 0000f000 00001000�[0m
�[0;32mI (90) boot: 2 factory factory app 00 00 00010000 00100000�[0m
�[0;32mI (98) boot: End of partition table�[0m
�[0;32mI (102) esp_image: segment 0: paddr=00010020 vaddr=00000020 size=0001ch ( 28) �[0m
�[0;32mI (110) esp_image: segment 1: paddr=00010044 vaddr=3fc88d80 size=00758h ( 1880) load�[0m
�[0;32mI (119) esp_image: segment 2: paddr=000107a4 vaddr=3fc894d8 size=00418h ( 1048) load�[0m
�[0;32mI (127) esp_image: segment 3: paddr=00010bc4 vaddr=40380000 size=05160h ( 20832) load�[0m
�[0;32mI (141) esp_image: segment 4: paddr=00015d2c vaddr=00000000 size=0a30ch ( 41740) �[0m
�[0;32mI (153) esp_image: segment 5: paddr=00020040 vaddr=3c000040 size=02724h ( 10020) map�[0m
�[0;32mI (155) esp_image: segment 6: paddr=0002276c vaddr=00000000 size=0d8ach ( 55468) �[0m
�[0;32mI (172) esp_image: segment 7: paddr=00030020 vaddr=42010020 size=16cf8h ( 93432) map�[0m
�[0;32mI (195) boot: Loaded app from partition at offset 0x10000�[0m
�[0;32mI (195) boot: Disabling RNG early entropy source...�[0m
*** Booting Zephyr OS build zephyr-v3.2.0-9-g8625a40ec488 ***
Hardware: Libre Solar BMS C1 (v0.3)

Firmware:

E: BMS hardware initialization failed, retrying in 10s
#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}#mSerial {"rBat_V":0.00,"rBat_A":0.00,"rBat_degC":0.0,"rSOC_pct":0.0,"rErrorFlags":0,"rBmsState":0,"rCells_V":[0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":0.000,"rCellMin_V":0.000,"rCellMax_V":0.000,"rBalancingStatus":0}I: detected bq device number: 0x7695
#mSerial {"rBat_V":8.45,"rBat_A":0.05,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.661,0.144,0.129,0.361,1.067,6.060,-0.001,0.000,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.596,"rCellMin_V":0.661,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.44,"rBat_A":0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.657,0.136,0.125,0.358,1.067,6.060,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.595,"rCellMin_V":0.657,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.45,"rBat_A":0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.545,0.221,0.141,0.318,0.944,6.060,0.000,0.000,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.516,"rCellMin_V":0.545,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.45,"rBat_A":0.05,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.630,0.173,0.130,0.355,1.046,6.060,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.579,"rCellMin_V":0.630,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.46,"rBat_A":0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.650,0.146,0.118,0.347,1.046,6.060,-0.001,0.001,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.585,"rCellMin_V":0.650,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.45,"rBat_A":-0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.654,0.137,0.122,0.354,1.061,6.060,0.000,0.000,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.592,"rCellMin_V":0.654,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.45,"rBat_A":0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.665,0.143,0.128,0.356,1.057,6.060,-0.001,0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.594,"rCellMin_V":0.665,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.45,"rBat_A":0.00,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.552,0.216,0.140,0.322,0.950,6.060,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.521,"rCellMin_V":0.552,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.45,"rBat_A":0.00,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.627,0.170,0.129,0.353,1.039,6.060,0.000,0.000,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.575,"rCellMin_V":0.627,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.45,"rBat_A":0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.655,0.152,0.124,0.352,1.047,6.060,0.000,0.000,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.587,"rCellMin_V":0.655,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.45,"rBat_A":0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.656,0.139,0.121,0.351,1.054,6.060,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.590,"rCellMin_V":0.656,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.44,"rBat_A":-0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.660,0.137,0.122,0.350,1.051,6.060,-0.001,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.590,"rCellMin_V":0.660,"rCellMax_V":6.060,"rBalancingStatus":0}#mSerial {"rBat_V":8.44,"rBat_A":-0.03,"rBat_degC":-58.8,"rSOC_pct":0.0,"rErrorFlags":322,"rBmsState":0,"rCells_V":[0.558,0.218,0.140,0.321,0.943,6.060,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000],"rCellAvg_V":2.520,"rCellMin_V":0.558,"rCellMax_V":6.060,"rBalancingStatus":0}E:
E: mcause: 1, Instruction Access fault
E: mtval: e69b8b86
E: a0: d196c8c4 t0: cf478fcb
E: a1: db5067ed t1: 616bb785
E: a2: a1c1f5a4 t2: ae13db79
E: a3: 1deda449 t3: 128a90d2
E: a4: b551c932 t4: f0dbeb04
E: a5: e5070e22 t5: 54ec9f26
E: a6: c89959b8 t6: 4b3fe0f8
E: a7: 50068842
E: ra: 3fc88400
E: mepc: e69b8b86
E: mstatus: 00000091
E:
E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
E: Current thread: 0x3fc85760 (main)
E: Halting system

Accessing an array out of bound on bms_apply_dis_scp at bms_bq769x0.c:257

Hello, thanks for making this repository open-source as it is very beneficial for renewable energy enthusiasts community.

I found some issues when trying to set SCD_THRESH and other setting bits on PROTECT1, 2, 3 registers. The firmware is able to write to those registers, but upon closer look, there is a mistake in what the firmware write to those registers.

My investigation leads to something peculiar in how SCD_THRESH is chosen over SCD_threshold_setting in bq769x0_registers.h.

In bms_apply_dis_scp() at bms_bq769x0.c:

    for (int i = sizeof(SCD_threshold_setting)-1; i > 0; i--) {
        if (conf->dis_sc_limit * conf->shunt_res_mOhm >= SCD_threshold_setting[i]) {
            protect1.bits.SCD_THRESH = i;
            break;
        }
    }

In above snippet, sizeof(SCD_threshold_setting) is expected to give the array length. But in reality, sizeof() returns the array size in bytes. And because @SCD_threshold_setting is composed of uint16_t elements, sizeof(SCD_threshold_setting) returns 2 bytes * array length.

Is this a mistake or there is actually a reason for using sizeof(SCD_threshold_setting) instead of sizeof(SCD_threshold_setting) / sizeof(SCD_threshold_setting[0]) ?

Of course I am not an expert in C programming as I have never taken formal education on this matter, so pardon me if I was wrong.

Reference
https://stackoverflow.com/questions/671703/array-index-out-of-bound-in-c

LiPo Float Charge & SOC settings

Hi Martin,
Thanks for all your work on this project.
Just a couple of question;

  1. Does the firmware support a float mode setting?
    Float mode with say an 8 hour timer would allow the mppt to stay on and feed any loads without reseting to a bulk charge. This would also pretty much guarantee that the batteries are fully charged, despite any usage throughout the day, when the sun has set.

  2. Is the state of charge (SOC) configurable so that 100% can be set at say 3.45V/cell?

Cheers

Move SOC estimation to common BMS implementation

The coulomb counting for SOC estimation is currently implemented in the bms_read_current functions in each individual chip.

Example:

coulomb_counter_mAs += status->pack_current * (now - last_update);
float soc_delta = coulomb_counter_mAs / (conf->nominal_capacity_Ah * 3.6e4F);
if (fabs(soc_delta) > 0.1) {
// only update SoC after significant changes to maintain higher resolution
float soc_tmp = status->soc + soc_delta;
status->soc = CLAMP(soc_tmp, 0.0F, 100.0F);
coulomb_counter_mAs = 0;
}

It should be moved to the code common to all BMS ICs in order to make the firmware more modular and ease implementation of more sophisticated SOC algorithms (e.g. with Kalman filters).

Change settings over Thingset, settings are not stored in EEPROM

Tried to save settings over thingset (serial) in EEPROM failed. After reboot, EEPROM still seems to be empty. Tested on current git main trunk.

Workflow: started with a new EEPROM, tried to change config parameter over serial thingset connection. After parameter changed, reboot the hardware, readback config

Debug terminal output, no EEPROM mounted (recognized correctly):

I: Init of CAN_1 done
*** Booting Zephyr OS build zephyr-v20500  ***
Hardware: Libre Solar BMS 5S50 SC (v0.1)
Firmware: unknown
E: failed to read EEPROM (err -5)
EEPROM: read error: -5

Soldered EEPROM, first boot:

*** Booting Zephyr OS build zephyr-v20500  ***                                  
Hardware: Libre Solar BMS 5S50 SC (v0.1)                                        
Firmware: unknown                                                               
EEPROM: Empty or data layout version changed

Read config and change parameter over serial Thingset connection, then reset device:

Received Request (5 bytes): ?conf                                               
Received Request (24 bytes): =conf {"BatNom_Ah":60.0}                           
EEPROM: Data successfully stored.                                               
Received Request (11 bytes): !exec/reset 

After reboot, EEPROM still seems to be not initialized, readback of conf returns default parameter, not changed one.

...
EEPROM: Empty or data layout version changed 
Received Request (5 bytes): ?conf

The explicit command for save settings does not work either.

Received Request (24 bytes): =conf {"BatNom_Ah":80.0}                           
EEPROM: Data successfully stored.                                               
Received Request (5 bytes): ?conf                                               
Received Request (19 bytes): !exec/save-settings                                
EEPROM: Data successfully stored.
Received Request (11 bytes): !exec/reset 
I: Init of CAN_1 done                                                           
*** Booting Zephyr OS build zephyr-v20500  ***                                  
Hardware: Libre Solar BMS 5S50 SC (v0.1)                                        
Firmware: unknown                                                               
EEPROM: Empty or data layout version changed 

Cells_V in CAN publication message

TS_NODE_ARRAY(0x80, "Cells_V", &cell_voltages_arr, 3,
ID_OUTPUT, TS_ANY_R, PUB_SER),

What would be the better solution to publish the individual cell voltages over CAN

  • create a DataObject for every cell voltage
  • create a CBOR array with all voltages (one array is implemented in text mode) and expand the publication message for multi frame messages?

bq769x0: repeat read due to crc fail might read different bytes an might led to wrong data read

line 140 will probably try reading a different byte after the crc check failed -> there might be wrong date

while (true) {
err = i2c_read_dt(&dev_config->i2c, buf + 1, 2);
if (err != 0) {
return err;
}
else if (crc8_ccitt(0, buf, 2) == buf[2]) {
break;
}
else if (attempts >= BQ769X0_READ_MAX_ATTEMPTS) {
LOG_ERR("Failed to read data at 0x%02X after %d attempts", reg_addr,
BQ769X0_READ_MAX_ATTEMPTS);
return -EIO;

you might want to extend the loop to include a reg-addr write before the read retry

Control flow of code using thingset.

Set an infinite loop that waits for a variable to be set through thingset in the main function.
This is done to control the flow of the main function using thingset.
Below is the code snippet:
Screenshot from 2024-02-03 19-37-45

The program does not enter the infinite loop, and wait for the value to be changed via thingset but proceeds to the next function. The output is:
Screenshot from 2024-02-03 19-39-31

Not able to understand why this is happening.

Tested the BMS C1 v0.3 using a load tester and tested for cell level protection.

The tests were done in two parts.

Part 1

The first test was done using a load tester. The electronic load tester used is RePower Battery Test System with a capacity of 120V, 100A.
A LFP battery pack of 52V and 6 Ah capacity having the configuration of 16s1p was used. The BMS was mounted on a heat sink. Each cell in the battery pack was connected to the BMS’s cell connector and the battery pack’s positive terminal was connected to the BAT+ of the BMS and the battery pack’s negative terminal was connected to the BAT- of the BMS. The electronic load was connected to the to PACK+ and PACK- of the BMS. The board was connected to a linux system using USB to UART connector.

The following tests were conducted:

Discharge overcurrent protection

Test procedure: The amount current drawn by the load was initially set to 6 A. The current drawn by the load was increased to 15 A. The cutoff value was set to 13.3A.
Result: The discharge overcurrent is detected correctly and the BMS flags a discharge overcurrent error (8). The discharge MOSFET is disabled and the BMS is put in state 1 in which discharging is disabled and charging is enabled.
Issue: The thingset command "!Device/xReset" causes the BMS to become unresponsive. Had to reflash the code to return to normal execution.

Charge overcurrent protection

Test procedure: The charge current given to the battery was initially set to 6 A. The charge current given to the battery was increased to 15 A. The cutoff value was set to 13.3A.
Result: The charge overcurrent is detected correctly and the BMS flags a charge overcurrent error (16). The charge MOSFET is disabled and the BMS is set in state 2 in which charging is disabled and discharging is enabled.
Issue: The same issue with Discharge overcurrent protection.

Short Circuit protection

Test procedure: The discharge current given to the battery was initially set to 6 A. The charge current given to the battery was increased to 15 A. The short circuit limit set was 33.3A.
Result: The short circuit is detected correctly and the BMS flags a short circuit error (4). The discharge MOSFET is disabled.
Issue: Same as with Discharge overcurrent protection.

In all these tests reset was an issue. This board will be used in an Electric Vehicle and recovery method for charge overcurrent, discharge overcurrent does not seem feasible as its difficult to send a current of the opposite direction when the vehicle is in use.

Part 2

The second test is the individual cell protections.
The cell connectors of the BMS are connected to the pack simulator. Cell 16’s positive terminal and battery packs positive terminal are connected to the BMS tester. Cell 1’s negative terminal and battery pack's negative terminal are connected to the BMS tester. B+ of the BMS tester is connected to BAT+ of the BMS.

Equipment used:

  • Battery pack simulator.
  • BP8858 Power Battery Protection Board Tester v2.7.3
  • BMS C1 v0.3

Cell Overvoltage Protection

Test method: Each cell is given a voltage of 3.3V and voltage is increased to 3.6V gradually. At the end, voltage is brought down to 3.5V which is the recovery voltage.
Result: The overvoltage is detected correctly and the BMS flags a cell overvoltage error(2). The charge MOSFET is disabled and the BMS is in state 2 in which discharging is enabled and charging is disabled. After reaching voltages below the reset threshold of 3.5 V again, the BMS goes back to normal operation (state 3).

Cell Undervoltage Protection

Test method: Each cell is given a voltage of 3.3V and voltage is decreased to 2.5V gradually. At the end, voltage is increased to 2.6V which is the recovery voltage.
Result: The undervoltage is detected correctly and the BMS flags a cell undervoltage error(1). The discharge MOSFET is disabled and the BMS is in state 1 in which charging is enabled and discharging is disabled. After reaching voltages above the reset threshold of 2.6 V again, the BMS goes back to normal operation.

Cell Overtemperature Protection

Test method: The cell temperature sensor is heated up by dipping in hot water heated above the required temperature threshold.
Result: The overtemperature is detected correctly and the BMS flags a discharge and charge overtemperature (512 + 128). Both MOSFETs are disabled and the BMS is in state 0 where both charging and discharging is disabled.

Cell Undertemperature Protection

Test method: The cell temperature sensor is cooled down by placing it in ice.
Result: The undertemperature is detected correctly and the BMS flags a charge undertemperature (256). Charge MOSFET is disabled and the BMS is in state 2 where charging is disabled and discharging is enabled.

Pictures

A few pictures from the test:

WhatsApp Image 2023-11-30 at 16 42 59
Snapshot of the individual cell protection test values.
WhatsApp Image 2023-11-30 at 16 43 46
Connection of the board to the test system.

Tracking issue for TI bq769x2 support

This issue gives an overview of the implementation status for the Texas Instruments bq76952 / bq76942 BMS IC support in the BMS firmware.

  • Communication interface: Direct commands
  • Communication interface: Subcommands
  • Voltage reading
  • Current reading
  • Temperature reading
  • Error reading
  • Charge/discharge MOSFET switching
  • Balancing
  • Short-circuit protection
  • Overcurrent protection in discharge direction
  • Overcurrent protection in charge direction
  • Cell undervoltage protection
  • Cell overvoltage protection
  • Temperature protection

I2C communication with ESP32-C3 based board

I'm currently unable to talk to the bq76952 chip on the BMS 16S100 SC populated with the ESP32-C3. With the STM32 it works fine. It may be a hardware problem. However, @JochenKr experienced exactly the same issue, so it may also be a software problem.

*** Booting Zephyr OS build zephyr-v3.0.0-8-gc1a8af9fa93c ***
Hardware: Libre Solar BMS 16S100 SC ESP32C3 (v0.2)
Firmware: v21.0-78-g30b5496
E: I2C transfer error: -14
E: I2C error for subcmd_read: -14
I: detected bq device number: 0x4248
E: I2C transfer error: -14
E: I2C error for subcmd_read: -14

Here two screenshots of the (working) I2C communication with STM32G0B1:

SCR276

SCR277

And the same communication (with missing ACKs and responses) with the ESP32-C3:

SCR278

SCR279

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.