Simple DIY ESP8266 BMS

And there's already projects open sourced on GitHub ;) Do a search for BQ769x0
 
Ahh, found the libre solar. They have a large cell count version, but since it's based on that particular TI chip it only supports large cell counts. And then the issue with their BQ76920 setup is that it only supports from 3-5 cells, so it needs to be stacked to be useful for any real voltage. I'm also kinda amazed at how all of these projects are for such small battery packs and such low currents. What is someone supposed to do with 50amps max at 12v (600W)? Power a laptop, a fan, and a couple lights?

I'll probably base if off of the same chip (I'd rather use the 3-6s version, but why reinvent the wheel for an extra cell) but separate out the cell balancing to a separate board and over/undervoltage protection off to a separate latching relay so we can get some real currents going :) Can anyone think of a reason to use mosfets to get up to the current ranges we use? I'd think they would just be a PITA, another possible failure point, less efficient... etc

Also, Korishan, what sort of balancing current do you think would be appropriate for packs of our size? I'm going to be using new cells, but either way I want a separate higher amperage board to do balancing since if I'm going to go through the effort at least I should do something others can use.
 
I used them as a guide to design mine. Still working on it. I think it was LibreSolar I used. Might of been another. Been awhile since I started it.

The balancing circuit can be scaled. You just have to add in a few extra FETs, a diode, and another resistor. That allows you to move them off board to a secondary board.
I'm going to build mine with scalable discharge. Make a pcb with several resistor slots available. Maybe add some jumpers to enable/disable them. Haven't gotten that far yet with it.
 
So this whole time you've been holding out on us ehh? You've got the answer just sitting right there in your pocket! Haha, well, when I get around to starting my project I'll share the details here - probably EasyADA (although I would probably be doing this in Altium Circuitworks or Designer) and sharing code on Github. I don't know why people only share half of their project details - others could pick up where they left off and carry these things across the finish line , but instead they publish just one piece of the puzzle and drop off the face of the earth...
 
Well, not entirely. I've been working on it off/on over the past several months. It's not really ready yet. Plus I'm still learning the nuances of not only EasyEDA and the circuitry itself.
 
I've been looking into this for the last few weeks and have arrived at the following solution for myself (16s 48V LFP 100Ah).

- 16bit ADC (ADS1115, 4 channels) to measure cell voltages relative to pack negative via voltage dividers. Accuracy should be 2mV which I think is good enough.

-DS18B20 temperature sensors

- relays and resistors to balance each cell. I'm looking into what useful work I could do with this power, but I'll start with the basics and decide whether to change it based on how much power is actually being wasted.

- shunt to monitor current.

- 200A contactors to switch on/off charger and inverter.

- Arduino to control everything - possibly talking to a Pi or ESP8266 to connect with my home automation system.

- DC-DC buck converter to power it all. (probably a 48->12 and a 12->5 because I've got them already, and have a bunch of 12V things to power)

My requirements were that it was cheap, simple, and easy to understand. I think it'll cost about $50 excluding the shunt and 200A contactors, and I can build it myself on a strip board. I looked at designing pcbs for modular cell boards with optocouplers but it was getting too complicated with lots of components for something I'm probably only going to do once or twice.

I'm currently up to testing the ADS1115 ADCs and thinking how to program it all (voltage cut-offs and when to start balancing, etc).
 
@iscience: Nice. I'd go with an ESP32 or STM32 for the brains instead of an arduino. The main reason is that it has a more accurate clock cycle, is faster on an order of magnitude, more memory to utilize for program and buffer space (which lessens the likely that an external EEPROM would be needed).

The ADS1115 is a good choice, imho. I'm looking at using that one as well. I think instead of using voltage dividers, maybe use opto-couplers and reach each voltage independently using an attiny8. The opto's would be used for i2c coms from the attiny to the mcu.
Then on the attiny portion is where you can add part of your balancing ability. Maybe using a dbl wound inductor to move the power to the other side of the board and string them together.

That's kinda how I plan on doing it, anyways. Still learning before I attempt though
 
Using relays to balance cells has to be a reliability nightmare waiting to happen?
Mosfets are perfect for this type of thing, cheap, high current, reliable DC switching, easy to drive, etc, etc - can't imagine not using them!
 
I was thinking relays would be ok, because they're only switching a few times a day, and if they fail open the BMS will stop charging when the voltage gets too high. Failing closed would be a problem, but it should be detectable, and take many hours to cause any damage. That's probablyenough of a reason to consider MOSFETs though.

I got a bit overwhelmed by all the jargon and different specs, but I think this should be adequate:


image_pnsjvd.jpg


- N-channel MOSFET (Q1) to connect bleed resistor. Required specs: able to handle a few ampswith low power dissipation, and low gate threshold voltage (so it can be switched bythe cell voltage).IRLB8314PBF is the cheapest I could find.

- optocoupler to pass the digital signal from the controller (OK1) - suggested part: 4N35

- resistor on the optocoupler input (R1)~370Ohm = 10mA from 5V signal, which is what seems standard for the 4N35, but I'm guessing a larger resistor will probably do too?

- resistor to pull the gate to low when there's no input signal (R2) say 10kOhm

- bleed resistor (R3), 3 ohm (so about 1A balance current, but this could easily be made more if desired).


Anyone willing to check my circuit andspecs?

(My component choice is limited becauseI'm trying to get through-holecomponents that are in stock onRS Australiaand don't have minimum order quantities over 20)
 
Now you're on the right track :)
https://au.element14.com/ also do parts here in Aust.

Current in R1 would be (source V - opto's led drop)/R ie source might be 3.3V depending on the chip & also might sag a bit under load. Led is likely about 1.7V
So (3.3 - 1.7) = 1.6V For a led current = ~4mA, a 390 ohm resistor would be good.
If 5V source, then a 680 ohm would do it.
 
I had started a BMS version with the ESP in LUA on the ESP and postponed it due to the low memory left after adding the required libraries, that was until the recent update which moved the code and freed up a lot of memory.

The method was to have DC-DC convertes for each ESP device (boost for LTO and buck for other Lithium cells).
Each ESP would then lod the cell voltage once per second into memory and then send this to the base server every 60 seconds or so.
Each ESP would then listen for back commands from the server to switch in/out a balance/bypass load for a pre-determined duration.
The data would be time stamped so that each cell can then be syncronised to cope with voltage drop/increase seen when load is switched on/off. This is quite important and was starting to look at a higher frequency of data capture to analyse IR changes over time seen by observing different voltage drops per cell across the pack.

The issue with trying to implement on a 22s system (22 x ESP devices) was mainly due to WiFi and the limited ability of a cheap consumer hub to handle a lot of signals in parallel without messing around changing channels, reducing power, etc. The spread of a 60 second window self balances over time between all of the units due to collision retry wait. I was trying this out with 5 second window and a few devices to simulate a conjested wireless network to see how well each device time separated.

The data would be sent with MQTT as it cuts out a lot of data handling issues at the battery/server ends and allows a queue and return messaging per cell.

With all that said and done I like the idea from charlie144 of using a 14s BS just to get the cell voltages back and then switch balancing with an opto isolator/FET as above.... would still use an ESP though as most cheap RS232 implementations usually use just 5V or 3.3V so may be able hook it direct into the ESP....

Battery ESP device code
---------------------------------------------------------------------------

Code:
wifi.mode(wifi.STATION)
wifi.sta.sethostname("ESP001")
wifi.setphymode(wifi.PHYMODE_N)
wifi.start()
wifi.sta.connect() 

-- ADC config mode needs to be set 
if adc.force_init_mode(adc.INIT_ADC)
then
print('ADC set restarting.....')
node.restart()
return
end

myip={192,168,0,79}
mygate={192,168,0,1}
mysubnet={255,255,255,0}

wifi.config(myip,mygate,mysubnet)

mqt:on("connect", function(client)
print('MQTT Connected')
while adcpush > adcpop do
 kvp={mymac,advdata[adcpop]}
 mqmsg = sjson.encoder(kvp)
 client:publish("/adc", mqmsg, 0, 0, function(client)
 advdata[adcpop] = nil
 adcpop = adcpop +1
end 
print("MQTT Messages sent")
end)
end)

sendwifi = tmr.create()
sendwifi:register(5000, tmr.ALARM_AUTO, function() 
if not wifibusy then 
 wifibusy = true
 wifi.start()
end
end)
sendwifi:start()

local adcdata{}
local adcpush = 0
local adcpop = 0

getadc = tmr.create()
getadc:register(500, tmr.ALARM_AUTO, function() 
adcnew={}
adcnew[1]=timer.time
adcnew[1]=adc.read(0)}
adcdata[adcpush] = adckvp
adcpush = adcpush + 1
end)
getadc:start()

---------------------------------------------------------------------------


hahaha... guess I need a code text wrapper.
 
Added code tags to your code ;)
 
completelycharged said:
I had started a BMS version with the ESP in LUA on the ESP and postponed it due to the low memory left after adding the required libraries, that was until the recent update which moved the code and freed up a lot of memory.

The method was to have DC-DC convertes for each ESP device (boost for LTO and buck for other Lithium cells).
Each ESP would then lod the cell voltage once per second into memory and then send this to the base server every 60 seconds or so.
Each ESP would then listen for back commands from the server to switch in/out a balance/bypass load for a pre-determined duration.
The data would be time stamped so that each cell can then be syncronised to cope with voltage drop/increase seen when load is switched on/off. This is quite important and was starting to look at a higher frequency of data capture to analyse IR changes over time seen by observing different voltage drops per cell across the pack.

The issue with trying to implement on a 22s system (22 x ESP devices) was mainly due to WiFi and the limited ability of a cheap consumer hub to handle a lot of signals in parallel without messing around changing channels, reducing power, etc. The spread of a 60 second window self balances over time between all of the units due to collision retry wait. I was trying this out with 5 second window and a few devices to simulate a conjested wireless network to see how well each device time separated.

The data would be sent with MQTT as it cuts out a lot of data handling issues at the battery/server ends and allows a queue and return messaging per cell.

---snipped rest of post

Hello CompletelyCharged,

I was working on an Arduino/ESP32or 8266 based BMSin the fall, but other parts of my project got in the way, and work got real busy. I am just now revisiting the BMS design for my boat. Forgive me if I ask a question that has been answered in a another thread.

22 x ESP all trying to connect to a hub or servers sounds like a wifi nightmare to me, but maybe the MQTT protocall makes it more manageable? Is it possible to make one ESP a Master and all the others slaves, and connect all the ESPs through I2C or SPI and just use the Master ESP32 to transmitt and receiveall the data in onepacket through MQTT? That is my plan of attack when I start working on BMS later tonight.

Have any of you used a LTC6804-1 or LTC6804-2 chip to measure your batteries? I am planning on using an ESP32 or ESP8266 as the "Head Unit" and 4 LTC6804-2 chips (right now my chosen motors need40S or about 170V peak). I hope I can use these to monitor the voltages and turn on and off the cell balancing transistors.

I am also going to try to add a thermistor to each cell and use a multiplexor to read each cell temp and add that data to the data packet.

Any thoughts?
-Rip
 
Riplash said:
22 x ESP all trying to connect to a hub or servers sounds like a wifi nightmare to me, but maybe the MQTT protocall makes it more manageable? Is it possible to make one ESP a Master and all the others slaves, and connect all the ESPs through I2C or SPI and just use the Master ESP32 to transmitt and receiveall the data in onepacket through MQTT? That is my plan of attack when I start working on BMS later tonight.

I believe there is a way to make them so that the master mcu listens for bursts of data. I believe there is a way to make it so that there is no handshaking and the "slave" units would just broadcast their data at set intervals without continually connecting/disconnecting from a wifi hotspot. I can't remember if Andreas Spiess, Julian Ilett, Adam Welsh, or some other showed how this works. It's been a while since I've seen the video.

If going the IIC/SPI router, might as well go with something different than the ESP's, like going with an STM32 or even "dumber" like ATTiny or one of the larger Atmegas. Just would need to use opto's for the IIC connections (plus other hardware that I'm not aware of atm) to keep everything isolated.
 
In MQTT you can set type of priority
Running only 22 units is NOTHING towards a decent system. I got way over 50 units at my home where by many are ESP. And many of them sends 10+ messages per second over MQTT.

MQTT is from start made to just work with small messages but have been expanded and can do larger to. But for ESP and Arduino you generally keep it below 128bytes due to its buffer and that is wise i would say.

Doing Wifi is not an issue as such except you need a stable network.

I2C or SPI would work but you need to isolate the bus (The reason why Wifi is used)
 
The 22 separate ESP units each connect, MQTT send and then disconnect all within about a second so you end up with just nodes randomly connecting and disconnecting throughout the 60 second window.

Simultaniously around 2-4 can connect and above that collisions occur with one or more not connecting and then pausing before trying again. Eventually they time separate enough for them to connect (guessing this is how daromer has 50 active on his network).

Typical consumer hubs will not allow more than around 8 simultanious connections to be active and some have very low number of wifi registered connections held open.

Connecting the ESP units in series would require opto-isolators because the 0V line of the ESP need to be connected to the -ve terminal of the battery so that the ADC can measure the cell voltage. This was part of the the reason to go the WiFi route. RS485 would be the option here for distance, isolation and cheap off the shelf modules..

The MQTT packets are around 500bytes (from memory) and now that the memory issue is resolved I would probably increase these with more data captured and a variable 60-120 second window.

Basically the balancing of cells does not need to be second to second and more of a analyse, watch and act approach. When the action is taken the balancer should know how long a bypass resistor needs to be connected to dissipate the required energy imbalance...

Second main point (to me) is that a battery pack only needs all the cells to be the same voltage if your balancer works that way... balance the energy not the voltage... build your packs by randomly adding energy storage over time rather than adding finely balanced sets of packs at a time. Just my thoughts..
 
Are you talking about that you send MQTT messages between 1 ESP to another and that limits tyou to 2-4 messages at a time? The ESP should be able to handle up to 16 threads if im not mistaken (ESP32) Im not sure how many i have been running byt my heating system retrieves MANY messages to scale in temperature data from many clients and yet not seen an issue. With that said i keep size of message low and the connection takes ms.

On a normal server you can have 1000s of clients connecting and sending data at same. You can easy push 100k connections at same time on below 2GB ram... the 50 units i have sending data send data several time per second as I said. For instance my WatchmonUDPListener doing the batrium stuff sends like data 50x per second here ALONE :)

You state 8 connections at a time?! Where have you gotten that from? A cloud based free solution that limit or ? Or is it limitation implemented on ESP?

Currently i have 40 connections per second on my small machine and the large one handles around 200 connections per second. I cant reach work now but that one is 10x the size on the test env...

It uses TCP so collissions can only be software based and you can set priority between 0 and 2 to depending on type of data.
 
No, 1 ESP connects via wifi to separate station wifi adapter plugged into the lan and a separate server is runnign RabbitMQ with an MQTT adapter/gateway enabled.

The issue was with WiFi and the way the connections are handled by my router / wifi hub are what created the issue with many ESP units connecting at the same time and holding the conection open. The router had a limit less than 10, which is how many ESP I was trying to connect up when testing. The TCP stack is no issue and it is how the wireless connections are handled by the ESP and the Hub. A more up to date access point may well cope with 250 client connections. I was looking at options and a method that would cope with a worst case situation (an old wifi hub).

RabbitMQ by default config on Linux tends to get throttled by the log write which is constrained by disk writes so if your on a spinning disk then you end up stuck handling around 100-200 messages per second if they are persistent/logged. Few setting changes and your into the 1000's but will loose data/messages on a power outage. SSD's help but you end up with a lot of wirte commits to the allocation table pages and increase the wear rate.

The ESP could probably kick out a few hundred kB (100's of messages) before the ESP becomes the bottleneck.

Tibco was the first good messaging system I used back in 1998....

The ESP AP mode with NodeMCU also only copes with 4 simultanious connections which makes using an ESP as the hub a non starter.
https://nodemcu.readthedocs.io/en/dev/en/modules/wifi/ (wifi.ap.config.max)

I'm guessing your using a good wifi access point that can cope with 100+ connections rather than a cheap wifi hub..... :)
 
Yeah max AP clients to ESP is 4.

My experience with RabbitMQ is same... Its not the best performance per default. I run Mosquito on my servers for MQTT and it performs darn well default. though not compared them side by side.

To go OT a bit before we go on track. The 802.11 can handle a total of 2007 clients per AP. There are though aspects from WPA and WPA2 to hold keys and stuff that do lower it significally and there are APs out there not doing more than 30 clients or so. i have yet though not seen anyone doing lower than that and last years most of them do quite well.

But yeah Wifi stack it self can create issues if you have many nodes.
In my system at home the theoretical limit is around 2500++ clients (Wifi...) I have not tested it though since im just above 120 clients right now with hardly any load neither that much inteference.


For the work for this thread im pretty sure it will work just fine for 99% of the users as long as they are not outside the norm :p
 
I had started a BMS version with the ESP in LUA on the ESP and postponed it due to the low memory left after adding the required libraries, that was until the recent update which moved the code and freed up a lot of memory.

The method was to have DC-DC convertes for each ESP device (boost for LTO and buck for other Lithium cells).
Each ESP would then lod the cell voltage once per second into memory and then send this to the base server every 60 seconds or so.
Each ESP would then listen for back commands from the server to switch in/out a balance/bypass load for a pre-determined duration.
The data would be time stamped so that each cell can then be syncronised to cope with voltage drop/increase seen when load is switched on/off. This is quite important and was starting to look at a higher frequency of data capture to analyse IR changes over time seen by observing different voltage drops per cell across the pack.

The issue with trying to implement on a 22s system (22 x ESP devices) was mainly due to WiFi and the limited ability of a cheap consumer hub to handle a lot of signals in parallel without messing around changing channels, reducing power, etc. The spread of a 60 second window self balances over time between all of the units due to collision retry wait. I was trying this out with 5 second window and a few devices to simulate a conjested wireless network to see how well each device time separated.

The data would be sent with MQTT as it cuts out a lot of data handling issues at the battery/server ends and allows a queue and return messaging per cell.

With all that said and done I like the idea from charlie144 of using a 14s BS just to get the cell voltages back and then switch balancing with an opto isolator/FET as above.... would still use an ESP though as most cheap RS232 implementations usually use just 5V or 3.3V so may be able hook it direct into the ESP....

Battery ESP device code
---------------------------------------------------------------------------

Code:
wifi.mode(wifi.STATION)
wifi.sta.sethostname("ESP001")
wifi.setphymode(wifi.PHYMODE_N)
wifi.start()
wifi.sta.connect()

-- ADC config mode needs to be set
if adc.force_init_mode(adc.INIT_ADC)
then
print('ADC set restarting.....')
node.restart()
return
end

myip={192,168,0,79}
mygate={192,168,0,1}
mysubnet={255,255,255,0}

wifi.config(myip,mygate,mysubnet)

mqt:on("connect", function(client)
print('MQTT Connected')
while adcpush > adcpop do
 kvp={mymac,advdata[adcpop]}
 mqmsg = sjson.encoder(kvp)
 client:publish("/adc", mqmsg, 0, 0, function(client)
 advdata[adcpop] = nil
 adcpop = adcpop +1
end
print("MQTT Messages sent")
end)
end)

sendwifi = tmr.create()
sendwifi:register(5000, tmr.ALARM_AUTO, function()
if not wifibusy then
 wifibusy = true
 wifi.start()
end
end)
sendwifi:start()

local adcdata{}
local adcpush = 0
local adcpop = 0

getadc = tmr.create()
getadc:register(500, tmr.ALARM_AUTO, function()
adcnew={}
adcnew[1]=timer.time
adcnew[1]=adc.read(0)}
adcdata[adcpush] = adckvp
adcpush = adcpush + 1
end)
getadc:start()

---------------------------------------------------------------------------


hahaha... guess I need a code text wrapper.
May I ask why you would need 22pcs of ESPs instead of just one ESP + a multiplexer?
 
Back
Top