diy solar

diy solar

Coulomb counter for DIY BMS

Good news, there's hope for offset thermal drift correction. It was simple to add a Dallas temperature sensor (DS18B20) to the data logger. Didn't put the unit in fridge, freezer, or oven. Just placed the unit in the RV and let the normal temperature swings take place over the course of almost 24 hours. I'm surprised how linear the thermal drift is.

TemperatureVsCurrent.jpg

x-axis is temperature in C
y-axis is current in Amps

The shunt was not connected during this test. A jumper wire took the place of the shunt. Shunt current should be zero.

I thought I would need to epoxy a temperature sensor on top of the op amp. It doesn't look like that's necessary. I only have the larger water proof temp sensors in my possession. Got the smaller transistor sized sensor on order.

1600295437801.jpeg
 
Ok that must be the most linear curve describing a real measurement I've seen in my life... :love:

I thought I would need to epoxy a temperature sensor on top of the op amp. It doesn't look like that's necessary. I only have the larger water proof temp sensors in my possession. Got the smaller transistor sized sensor on order.

Ambient temp near the circuit should be good enough, of course the closer to the op-amp the better ;)
 
I also logged the raw adc output data. The temperature drift equation is:

adc raw value = 17026.57 - 1.485 * deg.C

I'll use the y-axis intercept (17026.57) as the base offset value in the current correction calculation.

I_shunt = (adc raw value - 17026 - 1.48 * C) * gain
 
Last edited:
Thermal drift is under control. We got thermal drift regulation! Here's a plot of quiescent current over a time period of 900 minutes (15 hours). Current remains around -0.7A. The temperature probe has a granularity of 0.5 deg.C. The plot shows some "sawtooth" action where thermal drift ramps current in the positive direction until the sensor changes temperature. The current is then corrected by a -50 mA step.


CorrectedQuiescentCurrent.jpg
 
Nice ;) but you should be able to get an even better correction if you use a better temp sensor (well, just a normal one actually ^^).

What is this sensor with 0.5 °C steps? that's very weird (and annoying)...
 
ds18b20 is my favorite temp sensor. It uses the I2C bus (only 3 wires: power, ground, data). The a/d is internal to the chip.

When requesting temperature, data comes back in deg.C. Each sensor has its own address. That means you can attach as many sensors as you want to one Arduino port.

The resolution is programmable. Right now it's set to 9-bits which results in 0.5 deg.C resolution. I'll change it to 10-bits (0.25 deg.C). Hey, don't want to annoy you. ;)

ds18b20 datasheet
 
Ah that explains it...

Also, I hate dallas chips and I hate I2C... :ROFLMAO: SPI FTW \0/

More seriously you'll not annoy me because of that, it's just that if you get into the trouble of putting a temp sensor it's sad to see a 0.5 °C resolution one.

I mean there's lots of I2C temp sensors with a far better resolution than that for pretty cheap ?

Edit: my goodness, the DS is really expensive for what it is ?
 
Last edited:
I erred in describing the temp sensor using I2C. There's no clock involved. Just a one-wire bus. I love it! So simple, yet powerful. I changed sensor resolution to 0.25 deg.C. Could even drop down to 0.125 C, but there's no point in doing that. 0.25 C resolution will drop the thermal drift regulation down in the current measurement noise level.

They aren't that expensive. About $1. a piece.
From China
 
Ok, should be good enough then ;)

Ah yea, from china, but you don't know if you get the real ones or not (probably not...).
 
Looking at access times.

I'm taking the average of 20 current measurements. That takes 180 ms. In addition I inserted a 2 ms delay between measurements. Don't know if that's necessary. Total time = 180 ms + 40 ms = 220 ms.

It takes 97 ms to acquire one temperature measurement from the ds18b20. I'll be adding 2 more sensors. Total time = 300 ms. That sensor is slow!

I don't know if the 4-cell voltage measurements require averaging?? Any opinion on the resistor values for cell voltage measurements? I saw one design where the resistor divider factor is: 0.25, 0.125, 0.083 and 0.0625. They used 10k ohm as the upper resistor in the 4 divider networks. Sounds reasonable. Probably need a filter after the resistor divider. Any thoughts?

Right now the total measurement loop is set at 2 seconds. I've also been datalogging at that rate. But a spreadsheet that has 24 hours of 2-second data becomes too large. I've reduced datalogging to once every 30 seconds (every 15th measurement is logged). If current exceeds +/- 50A, logging speeds up to every 2 seconds. I don't intend to log data forever. It's a troubleshooting/verification tool right now. Right now I'm logging time, current, AH, board temperature.
 
I'm taking the average of 20 current measurements. That takes 180 ms. In addition I inserted a 2 ms delay between measurements. Don't know if that's necessary. Total time = 180 ms + 40 ms = 220 ms.

It's always a good idea to leave some time for the ADC to stabilize even if it's not strictly necessary in theory ;)

It takes 97 ms to acquire one temperature measurement from the ds18b20. I'll be adding 2 more sensors. Total time = 300 ms. That sensor is slow!

Yeah, that's one of the main reasons why I don't like them, they are slow as hell.

I don't know if the 4-cell voltage measurements require averaging?? Any opinion on the resistor values for cell voltage measurements? I saw one design where the resistor divider factor is: 0.25, 0.125, 0.083 and 0.0625. They used 10k ohm as the upper resistor in the 4 divider networks. Sounds reasonable. Probably need a filter after the resistor divider. Any thoughts?

Averaging just gives you more ENOB, if the ADC base resolution is good enough for you then you don't need it.

I used 100 k as my base resistor for everything relating to the voltage measurement because it was the highest value I could confortably use without having the accuracy degraded by input leakage currents, etc. and because it's a nice base value for any ratio I would need to set (i.e. don't choose a value like 47 k because the ratios vill get very not round...).

For the ratio it's easy: divide the max voltage you want to be able to measure by the max voltage you can convert with the ADC (of course taking into account your Vref, any prescaling set on the ADC, etc.), that's your min ratio so you just have to select the divider ratio to be equal to that or just higher (NB: using the X:Y convention, if you use the 1/X convention then the ratio will need to be equal or lower). That will give you the maximum precision possible while being sure to not saturate the ADC. Don't forget to take into account the resistors tolerances so calculate the ratio for the worst case values (for example with 100 k and 10 k giving you a theoretical ratio of 11:1 and they are 10 % (I would recommend 1 % resistors or better BTW) you need to use 90 k and 11 k giving you a ratio of only 9.18:1).

A filter is easy to add as you already have the R part of it via the divider so you just need a capacitor ;)
 
  • Like
Reactions: Cal
Trying to follow your suggestion. Max cell voltage is 4.2V. I don't expect to charge at greater than 3.55V. We can set max measure voltage to 4V, 8V, 12V and 16V for the 4 cells. I may use a ADS1115 adc at 2x gain. adc full scale voltage is 2.048V. For simplicity, I'll use 2.0V.

The 4 resistor divider ratios are: 2/4 = 0.5, 2/8 = 0.25, 2/12 = 0.167 and 2/16 = 0.125. I understand the ratios should be lower to account for tolerances.

You suggest using 100k ohm as the "base" resistor. Not sure what that means. Is 100k connected to the top of each cell (in other words, is 100k the upper resistor in each divider)? Then the lower resistor of the dividers are 100k, 33.3k, 20k, 14.3k. Is that what you mean?

Will require a different filter capacitor for each divider since the corner frequency is calculated as if the resistors are in parallel. Got a suggestion for fc?
 
Last edited:
When I said "base resistor" I was talking more about "my go to resistor" than its placement in the divider.

But yes, the 100 k should be the high-value one. NB: 100 k is valid only for my op-amps. You need to check your op-amp (or ADC if you don't use amps) input leakage current so you can choose a resistor value accordingly*

Those values looks correct ;)

What topology did you chose? mux? multiple ADCs? with/without op-amps?

Fc should be as low as possible but without compromising the desired measurement speed. And it must absolutely be under the aliasing frequency of the ADC (usually we choose the sampling frequency / 5 with a max of the sampling frequency / 2) but that shouldn't be a problem here anyway.

*choose a maximum voltage error you can accept (for example 1mV) and divide it by the input leakage current (for example 20 nA) to find the maximum value resistor you can use (for example 0.001 / 0.00000002 = 50 k) ;)
 
I don't know why an op amp is needed. It's probably better to use a mux. I have some DG408 parts available. The 4 cell voltages can be multiplexed. The current shunt voltage also needs to be accounted when calculating cell voltage. The ads1115 has 4 adc inputs. The shunt gets a direct input to the adc while the 4 cell voltages get multiplexed.

I don't think using a "set" upper resistor (like 100k) for all the dividers is the correct approach. The input impedance to the adc is the Thevenin equivalent impedance. Using the resistors mentioned above, cell 1 impedance is 50k (100k//100k), while cell 4 has 12.5k (100k//14.3k). Perhaps the resistors should be sized to obtain identical impedance? The input leakage current errors will now be equal. One filter capacitor at the output of the mux will give identical corner frequencies for all 4 dividers.

Designing adc circuits is uncharted territory for me. I wasn't planning on doing any cell voltage averaging. But that may change after getting real data. My goal is to get a voltage measurement that is as good or better than Chargery's. Their granularity is 1 mV. With ADS1115 full scale at 2.048V and 32768 bits, voltage resolution is 62.5 uV. That should be a significant improvement over Charger.
 
I don't know why an op amp is needed. It's probably better to use a mux. I have some DG408 parts available. The 4 cell voltages can be multiplexed. The current shunt voltage also needs to be accounted when calculating cell voltage. The ads1115 has 4 adc inputs. The shunt gets a direct input to the adc while the 4 cell voltages get multiplexed.

It's not needed per se.

Without a mux you'll need an ADC per cell, so yeah, usually it's far simpler and easier to use a mux ;)

You then have 2 ADC inputs free... and 4 on the mux... that begs to add things to be measured ?

I don't think using a "set" upper resistor (like 100k) for all the dividers is the correct approach. The input impedance to the adc is the Thevenin equivalent impedance. Using the resistors mentioned above, cell 1 impedance is 50k (100k//100k), while cell 4 has 12.5k (100k//14.3k). Perhaps the resistors should be sized to obtain identical impedance? The input leakage current errors will now be equal. One filter capacitor at the output of the mux will give identical corner frequencies for all 4 dividers.

Well, it's not the perfect approach but a good enough one as else the BoM complexity and cost increases, but as you'll probably just make one it's not a big deal.

The impedance is non-critical as long as it's lower than the max calculated (that's why I ignore the other resistors) and same with the corner frequency, really not critical. Then you can be anal about it and use different resistors, that's ok too :)

I used the high BoM re-use approach because I have a lot of those resistors and they are pricey because they are precision ones. That's also part of why I chose to use op-amps instead of dividers (and because the accuracy degrades for the higher cells), that way I could use only one value instead of dozens of them. But for a 4S BMS all that is much less a problem than a 16S one ;)

NB: the mux has a pass resistance of 100 or 120 Ohms max IIRC, don't forget to account for that if needed.

Designing adc circuits is uncharted territory for me. I wasn't planning on doing any cell voltage averaging. But that may change after getting real data. My goal is to get a voltage measurement that is as good or better than Chargery's. Their granularity is 1 mV. With ADS1115 full scale at 2.048V and 32768 bits, voltage resolution is 62.5 uV. That should be a significant improvement over Charger.

Well, the good thing is that's just software so easy to change in the future if needed ;)

Well, their resolution is 1 mV but the accuracy is far less than that. Like you'll have a 62.5 µV resolution but I bet the accuracy will be 10x worse (which is still far better than the Chargery and what you might need so no problem).

NB: as you're new with ADCs I recommend to read about mixed signals PCB routing (basically you star ground with the ADC as the center and you avoid mixing analog and digital in the same vicinity on the PCB) as it's quite important when you're in the µV territory.
 
Last edited:
  • Like
Reactions: Cal
NB: as you're new with ADCs I recommend to read about mixed signals PCB routing (basically you star ground with the ADC as the center and you avoid mixing analog and digital in the same vicinity on the PCB) as it's quite important when you're in the µV territory.

Good point to utilize a star ground, centered at the adc. Not using a pcb. It's all hand wiring as seen in my last photo.

I decided to base the resistor dividers on a common impedance. The dividers will have an equivalent impedance of 16.66 k ohms.

The calculated resistances are:
33.3k, 33.3k for cell 1
66.6k, 22.2 k for cell 2
100k, 20k for cell 3
133.3k, 19.04k for cell 4

I'll use standard values for the lower resistor and a parallel resistor combinations to get as close as possible to the desired ratio for the upper resistor. The dividers will most likely require software calibration. Need to borrow a voltmeter that can measure down to 0.0001V.
1/4W, 1% metal film

The package comes with 20 resistors of listed values. When using different resistor values (and not just a base resistor) I don't deplete one value.

I'll add a 10 nF capacitor to each divider to provide a 955 Hz corner freq. I doubt there's any noise coming out of the battery. It's all picked up on the way to the adc.

I don't expect the mux 100 ohm pass resistance to affect measurements. After all, in series with that is 16.6k ohm.

Got any good suggestions what can be connected to the empty mux lines to feed the adc?

I'm not going to do cell balancing on this BMS. Can you imagine what the heat caused by dissipative balancing can to the sensitive-to-heat instrumentation amp? I'll provide a signal when a commercial balancer should operate. Likewise, low voltage and high voltage disconnects will just be a signal. That's all what's needed. Keep it simple.
 
I'll use standard values for the lower resistor and a parallel resistor combinations to get as close as possible to the desired ratio for the upper resistor. The dividers will most likely require software calibration. Need to borrow a voltmeter that can measure down to 0.0001V.
1/4W, 1% metal film

The package comes with 20 resistors of listed values. When using different resistor values (and not just a base resistor) I don't deplete one value.

Yep, software calibration needed anyway ;)

I'll add a 10 nF capacitor to each divider to provide a 955 Hz corner freq. I doubt there's any noise coming out of the battery. It's all picked up on the way to the adc.

That's pretty high. I'd chose something more in the dozens of Hz max. Especially to filter the mains 50 or 60 Hz. There's noise on the battery but it'll comes from loads and EMI, not the battery itself ;)

I don't expect the mux 100 ohm pass resistance to affect measurements. After all, in series with that is 16.6k ohm.

Yep, no problem here.

Got any good suggestions what can be connected to the empty mux lines to feed the adc?

I'd say temp sensors but as you use digital ones that's already taken care of...

The full battery voltage would be a good idea.
 
Last edited:
So, I realize this discussion has moved over to the Cal's DIY BMS thread, but I had some question specifically about the coulomb counting aspect of this project. Specifically, 1) at what frequency (ie, time interval) are you planning to calculate coulombs, 2) what are you planning to use for the 'clock' in your calculations? 3) are you planning to use current or power in your SoC calculations (ie, amp-hr or watt-hr based estimates)?

For the last point, I had assumed that SoC based on power (adjusted for as-measured pack voltage) was better, but I'm realizing that my TinyBMS is just using amp-hours.

Any other details about how you plan to specifically count and update the coulomb count would be appreciated.

Thanks in advance.
 
I'm planning on counting amp-hrs (AH). The battery is rated in AH and SOC is based from AH. I have no need for WH.

Coulomb counting accuracy is a function of current measurement accuracy, time base accuracy and measurement intervals. I'm assuming microcontroller crystal time base accuracy is not an issue.

Would like to keep measurement intervals as short as possible. But I don't see much gains when intervals are less than half a second.

I think the dominant error is due to current measurement. Current resolution (and accuracy) is important. I've reduced resolution from 32 mA/bit (from this thread) to 6 mA/bit when using a dedicated (INA226) current measurement chip with a 300A @ 75 mV shunt. I'm satisficed with that.
 
I'm planning on counting amp-hrs (AH). The battery is rated in AH and SOC is based from AH. I have no need for WH.
Makes sense.
Coulomb counting accuracy is a function of current measurement accuracy, time base accuracy and measurement intervals. I'm assuming microcontroller crystal time base accuracy is not an issue.

Would like to keep measurement intervals as short as possible. But I don't see much gains when intervals are less than half a second.
I noticed that my BMS is currently tracking current and updating SOC at intervals of 100ms, but that does seem a bit overkill. I was considering 500ms as well. Even if there was a high magnitude 'spike' in current shorter than 500ms, at that time scale, shouldn't have much impact on SOC.
I think the dominant error is due to current measurement. Current resolution (and accuracy) is important. I've reduced resolution from 32 mA/bit (from this thread) to 6 mA/bit when using a dedicated (INA226) current measurement chip with a 300A @ 75 mV shunt. I'm satisficed with that.
6 mA/bit w/ 300A range is impressive. I'm currently at 15mA/bit with a 150A range, which I think should be fine for my system. That's WAY better than what my TinyBMS is doing (it doesn't even register a measurement until it exceeds a +/- 800mA threshold), and after that, the values jump all over the place.

Thanks for the info Cal. Looking forward to seeing more details on your BMS build!
 
Back
Top