• Have you tried out dark mode?! Scroll to the bottom of any page to find a sun or moon icon to turn dark mode on or off!

diy solar

diy solar

DIY BMS design and reflection

Accuracy wise, say down to 1 mV

Well, I have a resolution of a fraction of a mV but the accuracy is closer to 10-20 mV than to 1 mV, it's hard (well, not that hard but super expensive, especially when you add space and power constraints) to measure 3 V down to the mV when it's sitting on top of 50 V...

But that's the basic accuracy so if we calibrate each cell voltage we should be able to have single digit accuracy, something like 5 mV.

Also, that's at 25 °C, put the BMS at -30 °C or +50 °C and you'll see the accuracy be twice as worse.

For charging, on a battery pack of say 200Ah, with a 1C (200A)max charge/discharge, but user setting a 0.25C rate, and assuming the CC input is maxing out the 50A input, then on the first 1/50th second, all 16 cells measured and the amperage on 15 of the cells diverted through a gate/resistor/whatever to 0.1A and the rest of the 48.5A sent through the outlier.

So for this we would need to have a switch capacity of 50 A per cell (and we would need wires who can handle that to each cell BTW), two 50 A switches per cell actually, and at least one 50 A DC/DC converter (and conversion means losses, probably at least 5 to 10 % for this application) so even if it's feasible we are looking at hundreds of dollars and a really really big board.

Maybe in my case too little knowledge is dangerous, or else costs would be too prohibitive, but if i had you guys depth of knowledge/experience, i would be having a whole world of fun.

So, as you've guessed it, it's far too expensive.

Good luck with your developement. I cant add anything, but i simply love this and will follow silently from now on....no wish to spoil a fantastic thread.

Thanks a lot ;)

And keep proposing ideas (more feasible ones would be better though) ? more seriously, sometimes crazy ideas lead to good feasible ideas so don't hesitate to post.
 
So you asked for crazy ideas, here’s one!
There’s been a lot of discussion on the forum lately around keeping packs above their minimum recommended temperature by placing a resistive heat pad under the pack. Why not kill two birds with one stone by using resistive heat pads as balancing dump loads? This would be most useful in colder climates. For warmer climates, substitute incandescent automotive “turn signal” bulbs for the dump loads. For holiday appeal, apply a light coat of paint to the bulbs for colorful festive flash!
 
@cass3825 I'm currently researching what's the best option for the timers so if you have any ideas then speak now or forever hold your peace ?
The LMC555 has a parasitic power drain of 300kohm from V+ to Gnd, vs. the original LM555 whose internal resistance is 15kohm. Still researching, but the LMC555 is the best option I’ve found so far for power consumption vs. price.

 
Well, not that crazy actually :)

The problem is the variability of the resistance of those pads. I bet they are something like +/- 50 % so, yeah...

But as @nosys70 said here we can have resistors like this one bolted to the bus bars (plus it's a perfect match with the one resistor/2 cells design).

Now the problem is for when you don't want the heat... I mean we can have some code to only balance when cold enough but that's far from good design IMHO :rolleyes:

NB: I had to change the 78M05CDT by 78M05BDT's because the C version can't go under 0 °C. Now the whole BMS should be able to go from -40 °C to 60 °C (should be able to go up to 85 °C as is but the HW over temp protection will trigger around 58 °C so no point designing for going higher).

BTW the NE555 suck 5 mA just sitting here doing nothing... you can go to the moon on 5 mA! like Dave would say :P well, I really need to find something else for the timers...

Edit: will look at the LMC555 to see if it's a viable option, thanks ;)
 
@cass3825 Ok so the LMC555 is perfect as it has a low supply current and very low current for the inputs (important for the long delays so high value resistors) but it is 30 % more expensive by 10 pcs than the TLC555 which has, at first glance, the same characteristics. Did I miss something?

Edit: added most recent version of the schematic.
 

Attachments

Last edited:
Apologies for the confusion, I attached the TLC555 data sheet, but discussed the LMC555 in my post. I had looked at them both and agree they are functionally equivalent. Lowest price wins!
 
@cass3825 do you know any 5 V linear regulator with an output current of 50 mA or more without heat-sinking, a Vin max of at least 35 V (36 V or more would be better) and a low quiescent current (let's say max 1 mA)?

I'll explain a bit why: yesterday when I looked for the -40 °C version of the 78M05 I saw it had a 4 to 6 mA quiescent current. The load on the first one is 2.33 mA (worst case) and for the second one it's 8.5 mA (worst case) so, yeah, the total consumption would be half quiescent current and half loads...

The +5V_TOP (old name: +5V_HI) regulator must be directly fed from the battery (floating ground) so it must handle at least 35 V, and same for the +5VA regulator as I avoided feeding it from the +12V DC/DC converter because I want a very clean supply (ADC, Vref, ...).

The cheapest one I could find is this one: https://www.mouser.fr/datasheet/2/196/Infineon-TLS850B0TB_V50-DS-v01_10-EN-1732412.pdf (30 µA max Iq) but it's almost 4 times the price of the 78M05...

I'm half tempted to put a 5 V zener for the +5V_TOP as it's only 2.33 mA and to keep the 78M05 for the +5VA but feeding it from the +12V rail (not sure about the ripple and noise though...).
 
Last edited:
Ok, but those aren't linear regs, they are DC/DC converters and I can't use them because of the ripple and noise.

What I think I'll do is use a zener for the +5V_TOP rail and find another regulator for the +5VA but instead of using the battery I'll use the +12V so that should widen the models available as the Vin will be far lower.
 
Pretty good but it doesn't go higher than 28 V.

I found this one it goes up to 100 V (yeah I know, overkill, but it's the less expensive one that fits what I need...), it has a typical Iq of 0.3 mA (0.5 max), pretty tight regulation (20 mV) and cost only $0.2 more than a 78M05 so that's perfect :D
 
Yep, the good news is we'll be able to stay close to $100 for the BMS but the bad news it's only for the BMS board, not including the balancing board or the disconnect/precharge board. Well, we're talking about a 16s 300 (real)A continous BMS with redundancy for nearly all the protections and with good quality components, it can't be the same price than a 8s 100 (fake)A chinese BMS.

The ultimate goal for the disconnect is to be able to handle and break a direct short on a 16s string made with the 280 Ah Xuba cells... (and you were thinking you had a crazy idea with the heating pads...?)

If the 250 µOhm internal resistance per cell figure is true that's a 4 mOhm total internal resistance and with the worst case voltage of a fully charged battery at 57.6 V (3.6 V/cell) that's 14400 A... Let me tell you even the best mosfets will not be able to handle that for a long time (that's "only" 830 kW) ?

I do my best to minimise all the delays, propagation time, slew rates, etc... on the HW OCP. The BMS side of things is currently at 4.0 µs worst case (in theory... I'd prefer to have real numbers but that's not for right now...), the only last thing to keep fast is the isolated gate driver on the disconnect board.

The HW protections have their own control wire on the disconnect board connector and it'll have priority on everything else (the fire input will have the same priority too) and directly force the gate driver input to low, by-passing the "slow" logic and co of the other controls.

I didn't look about the mosfets and drivers yet so I don't even know if it can work in theory. And I don't know what's the usual time required for a 500 A MRBF fuse to blow with a 14 kA current so I don't know if the fuse will blow before the disconnect break the current.
 
Last edited:
I’ve been studying your latest schematic more, and have a few questions and thoughts:
What are your plans for J3 Aux input?
I really like the way you nested the muxes! Expanding on this idea, would you consider moving some input signals from IC240 (Ibatt,Vbatt,preChg signals) to a separate mux (much like IC250 is connected) in order to allow nested expansion? This would allow duplicating the IC210/Q220/IC230 cell monitoring circuit for additional cell strings. You could even move this circuit onto a stackable daughter board with power,A0/1/2, and jumper selectable input pins to multiple IC240 input pins. This would also help to keep the mcu pcb footprint smaller. 16S3P string monitoring would consume 6 inputs on the inner mux, leaving 2 inputs on IC240 for IC250 plus the new mux for Ibatt/Vbatt/preChgx. 16S4P string monitoring would require a third nest or 4-bit muxes. Wishing I had gone with 280Ah cells instead of 50Ah cells in 4P!

I’ll keep studying. Amazing work so far!
 
I’ve been studying your latest schematic more, and have a few questions and thoughts:

Don't hesitate to ask if you have other questions as usually there has been a lot of thinking (actually, I take more time thinking than placing components and wires...) and sometimes it's not clear why something is the way it is on the schematic.

What are your plans for J3 Aux input?

It's a user input usable for whatever you want as long as it's between -2.050 V and + 2.050 V between the two wires and no more than 8.5 V (either + or -) of common mode voltage from B-. It's just that I had a spare input on the mux and it wasn't hard to find a spare op-amp... It's very similar to the shunt input but with a unity gain instead.

Same for the aux temp sensor (well, there was two aux sensors but I had the idea to add a temp sensor directly on the BMS so only one aux left), I had a spare input on the mux and as it's only one trace and 3 more pins on the connector...

I really like the way you nested the muxes! Expanding on this idea, would you consider moving some input signals from IC240 (Ibatt,Vbatt,preChg signals) to a separate mux (much like IC250 is connected) in order to allow nested expansion? This would allow duplicating the IC210/Q220/IC230 cell monitoring circuit for additional cell strings. You could even move this circuit onto a stackable daughter board with power,A0/1/2, and jumper selectable input pins to multiple IC240 input pins. This would also help to keep the mcu pcb footprint smaller. 16S3P string monitoring would consume 6 inputs on the inner mux, leaving 2 inputs on IC240 for IC250 plus the new mux for Ibatt/Vbatt/preChgx. 16S4P string monitoring would require a third nest or 4-bit muxes. Wishing I had gone with 280Ah cells instead of 50Ah cells in 4P!

I like the idea but at this point you've duplicated half the BMS (and lost the redundancy of multiple independent batteries) and there's some problems like the temp sensors; in theory you can use the redundant battery sensors to monitor two other strings of cells but you loose the redundancy...

Also it's a pretty big modification to make on the schematic as the mux is in the middle and more importantly I don't have the use for this modification, nor a lot of people would, I think. But what you can do is alter the design (the project KiCad files will be available) and make it fit your needs. It's the problem with a project like that: you can't please everyone as you can't include all the ideas of everyone even if you try to.

I think a better approach in your case would be to simply use this design but don't populate all the Vbatt, Ibatt and HW protections components on the other 3 boards, and don't populate the arduino on any of the 4 boards but use a bigger arduino or other MCU instead.

You can parallel the A0/A1/A2 of all the boards, same with A3/A4/A5, and same with D12/D13 (SPI) but need to have separate I/Os for each SS (D9) so you can talk to each ADC separately. All the other I/O for the disconnect and co just need to be taken from the first board where you connect the disconnect, HMI, ...

The PCB itself isn't expensive, it's the components and assembly time that are, so you'll be able to have a cheap solution without heavy modifications (TLDR: don't put some components, plug some bigger external MCU wires where the arduinos would go).

Another approach would be to do a 4P16S pack, that way you just have one battery to monitor, far simpler :)

I’ll keep studying. Amazing work so far!

Thanks ;)


Your discussion ealier about the dump resistors and light bulbs gave me the idea to have a heater output (well, an output for a relay for a heater more exactly). Actually, the question is why I didn't think about adding that earlier? a lot of people are adding external temp controllers when the BMS they use has already one or more temp sensors and can't control a simple heater... we need to change that...

Also, @FilterGuy sent me a PM about having a dedicated I/O for the BMS to tell other devices it disconnected the battery, and for other devices to tell the BMS to disconnect the battery. It would be the same as the fire I/O in regards to the technical aspects: input all the time with a pull-up resistor, changed to an output to pull the line low when needed.

At the beginning of the thread there was a similar request, so I guess it's a pretty popular need.

Now, as you're following you know I've run out of I/Os on the arduino...well, that's not totally true, there's still D0 and D1 available but they are shared for the USB com so there's some limitations. I need to look in more details about that.

What do you think about those I/Os usage? (because after that we are really out of available I/Os, we can't add more things, so we better use them wisely...)


Edit: added the most recent version of the schematic. Not much has changed, I didn't had time to add the 555 but I changed the 5V regs and replaced the HI/LO by TOP/BTM in the power labels names which is less confusing.
 

Attachments

Last edited:
My current pack configuration is 4P16S. Top balancing has been less than successful, so now I’m in the process of capacity testing 64 cells one at a time with a 10A cycler. Yes, tedious. This has led to my fascination with active balancing, which should (somewhat) compensate for a weak cell in xPyS pack. Plan B is to reconfigure cells to 16S4P with individual BMS per string. Following this project has given me inspiration to reload KiCAD and knock the dust off of my pcb CNC router.
Regarding I/O usage, the limited I/O count of the Nano and Pro Mini is what turned me to the Teensy boards from PJRC. Definitely worth a look!
 
Ok, I think you definitely have a bad cell because history shown even without balancer packs stays well balanced for months for solar usage. I'll too have to test 64 cells in a few weeks...

The thing is you need a pretty high current balancer to compensate for a bad cell. I'm pretty sure it would be better and more or less the same price to replace the bad cell by a new one.

You can also do 2P16S2P, that's a good compromise; only two batteries to manage and you have redundancy too, so you can work on one of them while the other stay in use for example.

The needed one would be the Teensy++ 2.0 but it's expensive, the arduino (from a reputable source) is half that: https://www.mouser.fr/ProductDetail/Arduino/ABX00028?qs=sGAEpiMZZMve4/bfQkoj%2BKY2I/nMYlvjaCJuj24/eQs= (and that's the Every version with less EEPROM but more RAM and flash, perfect for what we need) of course you can also pick one on ebay for 2 or 3 $ (which is what I usually do in fact) but I'm not ready to put any safety trust in a cheap clone from ebay... last thing you want is save a few $ to then see thousands go up in flames...
 
Last edited:
I'm pretty sure it would be better and more or less the same price to replace the bad cell by a new one.
Agreed.
You can also do 2P16S2P, that's a good compromise; only two batteries to manage and you have redundancy too, so you can work on one of them while the other stay in use for example.
Great idea!
The needed one would be the Teensy++ 2.0 but it's expensive, the arduino (from a reputable source) is half that: https://www.mouser.fr/ProductDetail/Arduino/ABX00028?qs=sGAEpiMZZMve4/bfQkoj%2BKY2I/nMYlvjaCJuj24/eQs= (and that's the Every version with less EEPROM but more RAM and flash, perfect for what we need) of course you can also pick one on ebay for 2 or 3 $ (which is what I usually do in fact) but I'm not ready to put any safety trust in a cheap clone from ebay... last thing you want is save a few $ to then see thousands go up in flames...
Did you consider the Teensy-LC?
 
The main issue I see is this: "The I/O pins are not 5V tolerant." all the BMS is 5 V (and -/+ 12 for some analog ICs) so that's a big problem. And I wonder what's the power consumption is too (at 48 MHz it can't be super low).

BTW I'll not use the 555 for the long term OCPs... Yeah I know, but it'll still be useful for the watchdogs and whatever we need elsewhere (I've some ideas for the HMI board which will require timers...) so all the research we've done is not useless ?

Why? because I've 2 spare comparators (and I need 2 timers, how convenient... ?) so far less board space needed, and also because the 555 is a PITA to configure the way I need for this (and I might even need some logic gate in addition to the 555...).

Moreover the comparator based timer has a nice side effect in its behaviour which will be far better at protecting the mosfets from an over temp condition if we are bouncing in an out of the OCP faster than the preset delay (it'll trigger where the 555 wouldn't because it would reset the timer each time instead of having an accumulative behaviour).
 
You’re correct, the Teensy 3.2 would be needed for 5V tolerant pins. $8 more than the LC. I didn’t look at power consumption, but should have prior to making the recommendation.
I am envious of your knowledge of opamps, I need to brush up on them!
 
Thanks :) but I don't know much, I just know the basics and most of the traps (no caps directly on output, don't use below unity gain, don't neglect input offset and biais currents, same for input offset voltage, how close to the rails the inputs can go, same for the output, limits of GBW product, ...), then if you need a special config you look it up, same for the formulas.

You can learn all that in one or two afternoons if you already know electronics, you just need to find a good resource (w2aew and EEVblog are very good ones) ;)

Edit: another great resource: http://www.ti.com.cn/cn/lit/an/sboa092b/sboa092b.pdf
 
Last edited:
As previously promised, here’s a quick sketch for bit-wise manipulation of a 3-byte array written to shift registers:

Code:
#define clockPin 3
#define dataPin 4
#define latchPin 5
#define watchdog_led &flags[0],0 // nickname for bit 0 in the first byte of array 'flags'
#define power_led &flags[0],1 // nickname for bit 1 in the first byte of array 'flags'
#define a_led &flags[0],2 // nickname for bit 2 in the first byte of array 'flags'
#define b_led &flags[0],3 // nickname for bit 3 in the first byte of array 'flags'
#define c_led &flags[0],4 // nickname for bit 4 in the first byte of array 'flags'
#define d_led &flags[0],5 // nickname for bit 5 in the first byte of array 'flags'
#define e_led &flags[0],6 // nickname for bit 6 in the first byte of array 'flags'
#define f_led &flags[0],7 // nickname for bit 7 in the first byte of array 'flags'
#define cell_01 &flags[1],0 // nickname for bit 0 in the second byte of array 'flags'
#define cell_02 &flags[1],1 // nickname for bit 1 in the second byte of array 'flags'
#define cell_03 &flags[1],2 // nickname for bit 2 in the second byte of array 'flags'
#define cell_04 &flags[1],3 // nickname for bit 3 in the second byte of array 'flags'
#define cell_05 &flags[1],4 // nickname for bit 4 in the second byte of array 'flags'
#define cell_06 &flags[1],5 // nickname for bit 5 in the second byte of array 'flags'
#define cell_07 &flags[1],6 // nickname for bit 6 in the second byte of array 'flags'
#define cell_08 &flags[1],7 // nickname for bit 7 in the second byte of array 'flags'
#define cell_09 &flags[2],0 // nickname for bit 0 in the third byte of array 'flags'
#define cell_10 &flags[2],1 // nickname for bit 1 in the third byte of array 'flags'
#define cell_11 &flags[2],2 // nickname for bit 2 in the third byte of array 'flags'
#define cell_12 &flags[2],3 // nickname for bit 3 in the third byte of array 'flags'
#define cell_13 &flags[2],4 // nickname for bit 4 in the third byte of array 'flags'
#define cell_14 &flags[2],5 // nickname for bit 5 in the third byte of array 'flags'
#define cell_15 &flags[2],6 // nickname for bit 6 in the third byte of array 'flags'
#define cell_16 &flags[2],7 // nickname for bit 7 in the third byte of array 'flags'

byte flags[2]; // placeholder array for shift register data
byte lastFlags[2]; // data change monitor

void setup() {
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
flags[0] = 0x00; // initialize flag array
flags[1] = 0x00;
flags[2] = 0x00;
setFlag(power_led);
}
void loop() {
toggleFlag(watchdog_led);
// update shift registers if flags have changed
if (flags != lastFlags) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, flags[0]);
shiftOut(dataPin, clockPin, MSBFIRST, flags[1]);
shiftOut(dataPin, clockPin, MSBFIRST, flags[2]);
digitalWrite(latchPin, HIGH);
for (byte i=0; i<3; i++) {
lastFlags[I] = flags[I]; } }
}

// function to clear the nth bit in bite
void clearFlag(byte *bite, byte n) {
*bite &= ~(1 << n); }

// function to set the nth bit in bite

void setFlag(byte *bite, byte n) {
*bite |= (1 << n); }

// function to toggle the nth bit in bite
void toggleFlag(byte *bite, byte n) {
*bite ^= (1 << n); }

// function to query the nth bit in bite
byte checkFlag(byte *bite, byte n) {
byte flag = (*bite & (1 << n));
return flag; }

// function to get the bit position of a bit
byte getBitPosition(byte dataByte) {
for (int i=0; i<8; i++) {
if (dataByte & (1<<i)) {
return i;
}
}
return 255; // Otherwise return an error
}
 
Last edited:
Thanks ;)

Can you put it in a code tag or use pastebin though? because the way it is it takes a lot of page size and we may copy some weird characters.

Also the variable "bite" has an interesting name to say the least (use a french->english translator...) ?
 
Edited post above to use code tags and cleaned up unnecessary blank lines. Hopefully that looks better. I also realized I forgot a delay in the loop.
I had to laugh at the French translation of bite! English also uses ‘nibble’ to express a 4-bit chunk of data, which also translates funny!

Edit#2: changed ICODE to CODE tags for a cleaner post.
 
Last edited:

diy solar

diy solar
Back
Top