EcoModder.com

EcoModder.com (https://ecomodder.com/forum/)
-   Fossil Fuel Free (https://ecomodder.com/forum/fossil-fuel-free.html)
-   -   DIY open source lithium BMS (battery management system) (https://ecomodder.com/forum/showthread.php/diy-open-source-lithium-bms-battery-management-system-20445.html)

Daox 02-07-2012 10:51 PM

DIY open source lithium BMS (battery management system)
 
2 Attachment(s)
I've made enough progress with my lithium BMS that I think its time to post up what I have so far. I am posting the info for others to use as well as get some feedback.

Let me preface this all with the fact that I am by and far no expert in this. I know some programming and a little bit about electronics. That and a lot of googling and help from others has lead me to developing this.

The BMS is currently setup to work with the plugin kit for my Prius. So, right now its very simple. For example, where you see dc-dc converter it would be the controller in an EV. However, it was developed while keeping in mind that I'd like to use a similar version on an EV.

With that I'd like to go over generally how it works without having to dive into code:

Charging protection is pretty simple. All the cells voltages are individually monitored via a series of celllog devices. The celllog can measure up to 8 cells at once. If more cell monitoring is needed you need another celllog and the tiny circuit that accompanies it. My circuit diagram shows 2 celllogs which is what I am using. The celllog has a user settable high voltage alarm that is used. Once the alarm goes off, the arduino cuts power to the charger.

Discharge protection is taken care of via a current sensor. You have to enter in the amp hours your batteries are rated for and the max DOD you want them to see. From there the current sensor will keep track of amp hours used. For my plugin kit it automatically shuts the kit off after I hit my max DOD. For a full EV you could simply not use that part of the circuit. I have added an 8 LED bar graph that tracks SOC of the pack as a 'fuel gauge'.

Balancing is currently not done with the BMS. It is designed to have the batteries balanced at the low end of their charge and then put into use. I have yet to find a good way to keep track of the SOC of each cell and balancing makes that much more complicated.

Thermal protection is not currently done either. The plugin kit doesn't even pull 1C on the batteries so its not an issue. However, I would be interested in adding this.

Here is the schematic:

http://ecomodder.com/forum/attachmen...1&d=1340904482

And here is the code (NOT UP TO DATE):
Code:

/*
  Lithium BMS
  This is a simple BMS system for lithium ion batteries.
*/

#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>

// Pins
const int OnSwitchPin = 2;  // pin to read on switch status
const int ChargerRelayPin = 3;  // pin to control the charger relay
const int Pin110V = 4;  // pin to read if charger is plugged in
const int OnSwitchRelayPin = 5;  // pin to control the on switch (dc-dc pwr)
const int AlarmPin = 6;  // pin to read celllog alarm signal
const int latchPin = 8;  // pin to connect to latch pin on shift register
const int dataPin = 11;  // pin to connect to data pin on shift register
const int clockPin = 12;  // pin to connect to clock pin on shift register
const int CurrentPin = 1; // analog pin to read the current sensor

// Variables
volatile float CurrentRead = 0;  // holds CurrentPin analog read
volatile float AHused = 0; // holds amp hours used
float BatteryAH = 0; // holds usable battery amp hours
int AlarmPinStatus = 0;  // holds AlarmPin status
int OnSwitchPinStatus = 0;  // holds the OnSwitchPin status
int Pin110VStatus = 0;  // holds the Pin110V status
unsigned long DelayTimer = 0;  // variable to hold disconnect time
float SOC = 0;  // holds state of charge

// User defined variables
const int RatedBatteryAmpHours = 78;  // rated amp hours of the batteries
const float DOD = .7;  // maximum depth of discharge allowed


void setup() {
  pinMode(AlarmPin, INPUT);
  pinMode(ChargerRelayPin, OUTPUT);
  pinMode(Pin110V, INPUT);
  pinMode(OnSwitchRelayPin, OUTPUT);
  pinMode(OnSwitchPin, INPUT);
  pinMode(CurrentPin, INPUT);
  digitalWrite(AlarmPin, HIGH);  // set AlarmPin high
  digitalWrite(ChargerRelayPin, LOW);  // turn charger relay off
  digitalWrite(OnSwitchRelayPin, LOW);  // turn on switch off
 
  BatteryAH = RatedBatteryAmpHours * DOD;  // calculate usable Ah
 
  // initialize Timer1
  cli();          // disable global interrupts
  TCCR1A = 0;    // set entire TCCR1A register to 0
  TCCR1B = 0;    // same for TCCR1B
  // set compare match register to desired timer count
  OCR1A = 16001;
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10
  TCCR1B |= (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  // enable global interrupts
  sei();
}

void loop() {

  // SOC gauge code
  // calculate SOC
  SOC = (BatteryAH - AHused) / BatteryAH;
  // write SOC to led bargraph
  if (SOC > .875) {
    // 8 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);
  }
  else if (SOC > .75) {
    // 7 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 127);
    digitalWrite(latchPin, HIGH);
  }
  else if (SOC > .625) {
    // 6 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 63);
    digitalWrite(latchPin, HIGH);
  }
  else if (SOC > .5) {
    // 5 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 31);
    digitalWrite(latchPin, HIGH);
  }
  else if (SOC > .375) {
    // 4 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 15);
    digitalWrite(latchPin, HIGH);
  }
  else if (SOC > .25) {
    // 3 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 7);
    digitalWrite(latchPin, HIGH);
  }
  else if (SOC > .125) {
    // 2 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 3);
    digitalWrite(latchPin, HIGH);
  }
  else if (SOC > 0) {
    // 1 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 1);
    digitalWrite(latchPin, HIGH);
  }
  else {
    // 0 leds lit up
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 0);
    digitalWrite(latchPin, HIGH);
  }

 
  // Charger connect code
  // read pin110v status
  Pin110VStatus = digitalRead(Pin110V);
  // if 110V power is plugged in
  if (Pin110VStatus == HIGH) {
    digitalWrite(ChargerRelayPin, HIGH);  // turn charger on
  }
 
 
  // Charger disconnect code
  // read alarm pin status
  AlarmPinStatus = digitalRead(AlarmPin);
  // if alarm turns on set a timer to detect false alarms
  if (AlarmPinStatus == LOW && millis() - DelayTimer < 10) {
    DelayTimer = millis();  // set timer
  }
  // if alarm stays on
  if (AlarmPinStatus == LOW && millis() - DelayTimer > 2000) {
    digitalWrite(ChargerRelayPin, LOW);  // turn charger off
    AHused = 0;  // reset amp hours
    DelayTimer = 0;  // reset delay timer
  }
 
 
  // DC-DC connect code
  // read on switch status
  OnSwitchPinStatus = digitalRead(OnSwitchPin);
  // if dc-dc switch is on && battery has capacity left
  if (OnSwitchPinStatus = HIGH  && AHused < BatteryAH) {
    digitalWrite(OnSwitchRelayPin, HIGH);  // turn dc-dc converter on
  }
 
 
  // DC-DC disconnect code
  // if amp hours used exceeds usable amp hour capacity
  if (AHused > BatteryAH)
  {
    digitalWrite(OnSwitchRelayPin, LOW);  // turn dc-dc converter off
  }
 
 
  // DC-DC power down code
  // if dc-dc converter switch is off enter sleep mode
  if (OnSwitchPinStatus = LOW) {
  // enter sleep mode
  sleepNow();
  }
}


// sleep mode code
void sleepNow() {
  attachInterrupt(0,loop, RISING);  // set interrupt to on switch
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  sleep_enable();
  digitalWrite(latchPin, LOW);  // turn off SOC gauge
  shiftOut(dataPin, clockPin, MSBFIRST, 0);
  digitalWrite(latchPin, HIGH);
  sleep_mode();  // enter sleep mode
  sleep_disable();  // resume code after exiting sleep mode
}


// interrupt to count amp hours used
ISR(TIMER1_COMPA_vect)
{
    CurrentRead = analogRead(CurrentPin);
    // Convert currentread to amps
    CurrentRead = (CurrentRead - 512) * .78125;
    // Convert to AH & add to total
    AHused = AHused + (CurrentRead * .001);
}

Here is a list of the components:
http://ecomodder.com/forum/attachmen...1&d=1340907190

I've been using the charging protection for a few months with my plugin kit and it has worked great. I have just finished working on the discharge protection and haven't yet assembled the circuit.

Anyway, thanks for reading if you got this far. Its a lot to look at, but I'd really appreciate some feedback.

Daox 02-08-2012 07:42 AM

I added the bill of materials to the 1st post.

moonmonkey 02-20-2012 10:42 PM

doax that is impressive, i build microcontroller circuits and write code in assembly. if it works well and does not fail its a good design!. for thermal protection you probably already know that you could use negitive or positive temp coefficent thermisters and an op amp to trigger where ever you calibrate it. we use them on our lasertag vests charging systems. im interested in these kits for the pruis,,, i dont have one yet but i am eyeballing them, because of the avalibility of kits to up their mpg. my echo is getting long in the tooth at 199k. and 70 mpg is promised on some of these kits,

Daox 02-21-2012 07:58 AM

Thanks for the idea moonmonkey. I've used lm35 temperature sensors on different arduino projects before. I think if I were going to use some for this project I'd go with a 1-wire type because you could have multiple sensors and I don't have a huge abundance of pins left if I want to keep doing more and more.

moonmonkey 02-25-2012 11:48 PM

doax the pic microcontroller is easy to learn and there is alot of code examples out there to do just about anything you want. the programmers are cheap and tech support ,,,fair. the 16f84 is the one everyone learns on . but i use the 16f877 for most of my stuff because it has 33 I/O that you can program to be any combanation of inputs and outputs, i dont know if you write in assembler but this chip is a risc (reduced instruction set) and has only around 33commands, and cost around $10.00 dollars,then you just need a few resistors,a crystal and a few caps. i have used these chips in some very complex machines, they are rock solid and easy to use once you get used to them.i will be happy to help if you want to switch over to them.im not that knowledgable about arudino, it was'nt out when i started with pic.

skeeterb 03-07-2012 11:39 AM

Quote:

Originally Posted by moonmonkey (Post 289219)
doax the pic microcontroller is easy to learn and there is alot of code examples out there to do just about anything you want. the programmers are cheap and tech support ,,,fair. the 16f84 is the one everyone learns on . but i use the 16f877 for most of my stuff because it has 33 I/O that you can program to be any combanation of inputs and outputs, i dont know if you write in assembler but this chip is a risc (reduced instruction set) and has only around 33commands, and cost around $10.00 dollars,then you just need a few resistors,a crystal and a few caps. i have used these chips in some very complex machines, they are rock solid and easy to use once you get used to them.i will be happy to help if you want to switch over to them.im not that knowledgable about arudino, it was'nt out when i started with pic.

I like to work with PIC uCs too, especially since I can speed the coding using a program called Flowcode to generate the code. The free version is pretty good even though it has a 4 macro 16 icon/macro limit. It won't generate code for the EEPROM or a few other devices. I've registered my copy so I have full use. You can also get free samples of the PIC uCs too at microchip. :) If you want to try using PICs, download the free versions of MPLAB and Flowcode and experiment. If you like them, you can start using them for your projects. I'm not really familiar with coding an arduino, but I would like to recommend PICs as a user of that line of uCs. I started using PICs by using assembly, but when I was introduced to Flowcode, I was hooked. :cool: If I can get enough money together, I hope I can start converting an ICE Car to an EV. User friendly BMS' are good to have, especially if it was created by a fellow EV user/fan.

Daox 06-24-2012 05:08 PM

I've evaluated all the cells in my pack now, and I know all of their capacities. That means the batteries are ready to go back in the car. So, its back to working on the BMS system to ensure nothing else bad happens again.

This weekend I worked on tweaking the current sensor setup. Its still not perfect, but after a few tests it seems to be accurate enough that I won't be over-discharging anything.

I also worked on getting the SOC meter. I got it wired up and tweaked the code a bit to get everything working correctly. I even made a quick video to show how its working. I do have another bargraph on order that is linear instead of having LEDs side by side. We'll see what one I like when that one gets here.

http://www.youtube.com/watch?v=30kfzrZImoI

ecomodded 06-24-2012 06:02 PM

I like the bar graph your using, with its 1/8 drop off.
The circuity and electronics are foreign to me , but I know a good meter when i see it !

I think your onto a money maker, must be more then one model of hybrid that would benefit from your lithium BMS meter.

Maybe your not trying to make money with it, i see a lot of marketable talent here on ecomodder.

:turtle: Sales Section here on ecomodder could do well..

Daox 06-24-2012 06:08 PM

Thanks!

I have designed the BMS with the thought in mind that it could fairly easily be scaled and tweaked to be used in a full EV. I do have a future project in mind, but its on the back burner at the moment.

A money maker it will not be though. I'd really like to keep it as an open source project. The commercial BMS systems are fairly expensive and I haven't found a good alternative myself, so this is the route I am taking. Being open source also allows me to get help from others! I'm far from an expert, and I've already had a bunch of useful input from the guys here and local EV club. Its great to get useful criticism and feedback so it can be further improved upon.

Daox 06-27-2012 08:47 PM

1 Attachment(s)
I got the new bar graph and I think I'm liking it better. As you can see all the LEDs are in a line so its a bit more straight forward. The size of the two is identical. The only downside to using this graph is that it has 10 LEDs and my shift register only has 8 output pins so I can only drive 8 of the LEDs with it. There are many ways to deal with this, but the fact that you do have to deal with it is something to think about, especially if you want things to look real nice.

http://ecomodder.com/forum/attachmen...1&d=1340844395

Daox 06-28-2012 02:08 PM

I have updated my schematic and the bill of material. I've added a bunch of small components to take care of a few issues. I also added a field for cost per cell which comes out to a pretty decent $7.34/cell (before shipping), if you go up to a 48 cell system you're down to under $3.70/cell.

The code is not updated. It has quite a few changes and I am fairly sure nobody has browsed through it in depth yet because I haven't had comments about how this and that won't work. :) I've fixed most of it with individual testing of one part here and there. I'm sure there will be bugs to fix once I try to get everything working properly together. I'll repost the code at that point.

Daox 07-12-2012 01:35 PM

Looking ahead to putting this system into an EV (or something not PHEV related), I'd like to find a way to eliminate one of the more expensive components of the system, the celllog. I was thinking I might be able to use a multiplexing chip to increase the number of analog pins I have. Since cell voltages are well under 5V, I can read them all into an array or something. With that raw data I'll have much more data to work with and be able to do more with it. However, I've never used a multiplexing chip, and pulling individual voltages off a bank of many cells is also presents problems. Mainly, I have to move the ground reference every time I jump to the next cell. Currently, I'm not even grounded to the high voltage pack, just the 12V system. So, if anyone has any ideas I'm all ears.

thingstodo 07-13-2012 02:33 AM

Ideas are cheap ...
 
Quote:

Originally Posted by Daox (Post 316641)
Mainly, I have to move the ground reference every time I jump to the next cell. Currently, I'm not even grounded to the high voltage pack, just the 12V system. So, if anyone has any ideas I'm all ears.

My experience in hardware design is from many many years ago, so take this information with a grain of salt and check it out before doing any circuit work ....

The BMS topic does interest me, so I did some digging and this is what I found ...

Most of the circuits that are out there for analog isolation use a voltage to frequency converter, then go through an optoisolator, and back through a frequency to voltage converter. Some use a transformer for isolation, but those circuits are pretty old.

The isolated side, the voltage to frequency converter, needs it's own isolated power supply. That also powers one half (the input side) of the optoisolator.

The other side of the optoisolator is powered from the microprocessor side as well as the frequency to voltage converter (if you use one). The frequency to voltage converter makes the frequency signal back into an analog signal 0 - 5VDC.

An elegant solution would be to power the (small and pretty trivial) V to F from the battery that it is measuring, then have the frequency put through the optoisolator. The resulting frequency, or train of pulses, comes out of the output of the optoisolator and is powered from the microprocessor. From there, the frequency can be read directly into the micro, or put through a mux so that fewer micrprocessor pins are used up as frequency counters, or converted back to analog by a frequency to voltage converter, and put through an analog mux ... you get the idea.

Each battery would have it's own small circuit with just a V to F and an optoisolator ... about 10 ma, depending on which chips you choose and how good you are at soldering surface-mount.

However ... I can locate no Voltage to Frequency converter that will accept the voltage drop that each cell can experience during acceleration ... I'm assuming a low of about 2.0V for acceleration when the batteries are low and someone stomps on the accelerator to a high of about 4.2V for charging. I can't locate such a thing for sale ... so the next idea makes things a bit more complicated ...

Use another chip to boost the power supply from your battery voltage of 2V - 4.2V to a solid 3.3V, which can be used to power the V to F and the optoisolator.

- TPS60240 boost power supply. This will take the 2 - 4.2V (in fact, it will go as low as 1.8V and as high as 5.5V) from your cell and put out a regulated 3.3V for the rest of the circuit. 50 microamps standby, so it won't unbalance your pack.
- AD7740 voltage to frequency converter has a supply voltage of 3 - 5.25V, so 3.3V is fine. 1.5mA supply current is pretty low. under a dollar for an 8-lead msop (I hate soldering surface-mount stuff). The input voltage from the battery will have to be divided since the max input voltage is 2.5V - maybe 2 10K resistors in series would keep the current down under 1 mA. You also need a crystal for a clock and to set the max output frequency of the output, which is up to 1 Mhz.
- and you need an optoisolator, say a NTE3086 - no pricing on that one.

As with any circuit, component selection is very important. The minimal research that I did gave me only one boost power supply that would deal with a voltage dropping to 2.0V - that's why it's surface mount. It has one fixed output voltage of 3.3V. If the output voltage could be 5V there are dozens of Voltage to Frequency converters available. The AD7740 is one of 2 that I found that would work down to 3V.

The crystal at under 1 Mhz should not be a big problem. The optoisolator is only rated for about 100 Khz. Keeping the frequency as high as possible will give you a low time to sample (the micro can tell what the input voltage is within a few pulses) each channel. You'll need to put in a current limiting resistor to avoid saturating the optocoupler input.

Daox 07-13-2012 10:12 AM

With all the electric vehicle work that has been going on, there has to be a IC that does a lot of this. I think I need to do more digging.

Anyone with a leaf/volt want to rip apart their power inverter and take pics for me? :)

Daox 07-16-2012 01:44 PM

So, I've been working on the finishing things up before the BMS goes into the car. Lately, most of the work has been in trying to increase the accuracy of the current sensor. To test the sensor's accuracy I simply wired it up and set it on my desk with no wire or current flowing through it. I count the Ah and spit out out via the serial print command.

Leaving it uncalibrated showed unacceptable accuracy. After only 10 minutes of testing the sensor showed .61Ah had been used. This gives us an inaccuracy of .06Ah/minute. On a 60 minute trip the measurement would be off by almost 3.7Ah. If you only have a 40Ah pack you're looking at nearly a 9% inaccruacy which means you should reduce the usable capacity of the battery pack by 9% to compensate. That is a big chunk of SOC to loose.

Manual calibration has been somewhat more successful. My best result was a .009Ah/minute variation over a 1.5 hr test period. This means that after 60 minutes the amp hour reading would be .54Ah off. Again, considering the 40Ah capacity, we're talking a little over 1% inaccuracy which should mean that you loose 1% capacity to avoid damaging the batteries.

This is much better, however, manual calibration is a pain in the butt. Every current sensor would need to be calibrated and this should be able to be done automatically by the software. That is what I am currently working on. I should be able to take a voltage reading from the current sensor with no current passing through it and set that as my zero. So far I haven't been able to get it to work. I think I am having some power ripple issues. Once I figure out if/where they are, I should be able to smooth them out and get more consistent readings.

Daox 07-17-2012 07:56 AM

Last night I got the automatic calibration working pretty well. There is still some tweaking needed, but in my testing I saw .0058Ah/minute drift. Looking at the 40Ah example again this puts the BMS at .87% off after 1 hour of use. This is pretty darn good and should be more than adequate for the BMS. Still, I want to repeat the test, try a few different things, and do a longer test to verify info.

Daox 07-18-2012 08:40 AM

More testing was done last night. The results remain the same. .0055Ah/min is where we are at, and unless I get some feedback that is where it is going to stay. Not that that is bad, but I wouldn't mind getting it a little better if its possible. I just don't know how to make it any better at this point.

The problem is that my output signal is jumping around just enough to throw things off. I'm getting output voltages that randomly vary by ~.015V. Doesn't seem like much, but after 1 hour of monitoring it adds up. I'm guessing that it is my USB power supply that is jumping around a little and therefore causing my output to jump around. However, I don't have a scope to verify this. I have put a 10uF capacitor across the 5V input on the current sensor and tested it. I then put the capacitor across the sensor output and retested. The capacitor had no effect on sensor accuracy in either test. I was getting the same .015V variance from the aref and output.

I hope that is clear enough and I'd love some input.

thingstodo 07-19-2012 12:44 AM

5.5 mAh/min
 
The code does not mention calibration for an amp sensor - is this what you mean?

Quote:

// interrupt to count amp hours used
ISR(TIMER1_COMPA_vect)
{
CurrentRead = analogRead(CurrentPin);
// Convert currentread to amps
CurrentRead = (CurrentRead - 512) * .78125;
// Convert to AH & add to total
AHused = AHused + (CurrentRead * .001);
}
If that's your manual calibration, I have one suggestion. See what you think:

Arduino floating point has 6 - 7 digits of precision. Your scale constant of 0.78125 uses up 5 of those digits.

1023 Max reading - 512 = 511. * 0.78125 and *.001 gives 0.39921875, which is already over the significant digits on the Arduino. Use another variable, let's call it AHusedLow, to keep track of some extra significant digits. Since your calculated number can't go over 0.4, we'll use 0.4 as the rollover

Quote:

CurrentRead = analogRead(CurrentPin);
// Convert currentread to amps
CurrentRead = (CurrentRead - 512) * .78125;
// Convert to AH & add to low partion of total
AHusedLow = AHusedLow + (CurrentRead * .001);
// Update AHused
if (AHusedLow > 0.4) {
AHused = AHused + 0.4;
AHusedLow = AHusedLow - 0.4;
}
I've used this technique of chaining together variables to fake double-precision floating point (and triple, and quad) before (and I likely will again) and it has served me well.

This needs to be well documented so that anyone changing the code knows about the method and how it works, to make sure that the rollover is high enough that it will not be exceeded in one call and as low as possible.

That's the only code issue that jumps out at me.

Depending on how many times per second your ISR is called (I could look it up from your code ... but I'm lazy) this could be a source of error ... but as far as I can see, this should not have anything to do with your observed .0055 Ah/minute drift.

thingstodo 07-19-2012 12:58 AM

5.5 mAh/min
 
I worked out the .015V or 15 mV that you list is 3 counts on the A/D. It is pretty much impossible to have your numbers vary by less than 1 count, so 4.9 mV is expected.

You say that the output changes by 15 mV ... so you've already made sure that the error is not 5 mV several times in a row, it's 15mV a few times.

You saw the same error in the Aref measurement as in the measurement from the sensor. That points to something on your board dragging down the power supply, or to the power supply. The Aref is not changing - staying constant is what it is there for.

Do you have a USB hub with external power that you can use to power the Arduino? The older hubs that I have will put out a solid 500 mA per port ...

Remember to use good wiring techniques, good grounding, and catch all the issues that have bit you before. After that, it's luck as much as skill, experience or perseverance.

thingstodo 07-19-2012 03:09 AM

I guess there is ...
 
Quote:

Originally Posted by Daox (Post 316783)
With all the electric vehicle work that has been going on, there has to be a IC that does a lot of this. I think I need to do more digging.

Linear has a few specialized chips that seem to do the job much nicer than anything that I was thinking about:

LTC6802-2 - Multicell Addressable Battery Stack Monitor - Linear Technology
Less than $15 each. Not sure how close they are to end-of-life though.

LTC6803-2 and -4 - Multicell Battery Stack Monitor - Linear Technology
This one looks newer and is $16 each.

Daox 07-19-2012 09:42 AM

Thanks a lot for taking the time to look through this thingstodo! I appreciate it very much.

My code that is in the first post is quite dated. I have updated a fair amount of things from testing different portions of the code. However, I haven't put it all back together yet, thus I haven't reposted it.

I'm very glad you brought up the limitations of the float variable as it may be an issue. This is the latest code for the interrupt that I have been using. RawCurrentRead, CurrentRead, and AHused are all float type variables.

Code:

// interrupt to count amp hours used
ISR(TIMER1_COMPA_vect)
{
    // read sensor output
    RawCurrentRead = analogRead(CurrentPin);
   
    // calibrate sensor
    CurrentSensorCalib = analogRead(CurrentSensorCalibPin);
   
    // Convert currentread to amps
    CurrentRead = (RawCurrentRead - CurrentSensorCalib) * .78125;
   
    // Convert to AH used and add to total
    AHused = AHused + (CurrentRead * 0.0000002777);
}



I have yet to hook the arduino up to a more noise proof power source. I was going to do this but I am depending on the arduino's serial output to get feedback on the variables. I'm not sure how to connect the arduino to the computer without using the USB to power it. This is where a scope would come in quite handy.


Thanks for finding those chips! I'll have to take a look at them once I get the BMS in the car and running things properly.

thingstodo 07-19-2012 02:25 PM

Floating point
 
Quote:

Originally Posted by Daox (Post 317733)
Thanks a lot for taking the time to look through this thingstodo! I appreciate it very much.

I'm on holidays - this is the kind of thing that I enjoy.

Since your CurrentRead can now be somewhere between 511 and 1023, 1023 - 0 (potentially worst case) = 1023 * 0.78125 *.0000002777 gives 0.000221943046875 so I've changed the 0.4 rollover to 0.0003.
I chose a single digit of precision to maximize the total A-h you are calculating.

After you get your code updated, you may want to re-run one or two tests and see if your AHused is still tracking.

This
Code:

    // Convert currentread to amps
    CurrentRead = (RawCurrentRead - CurrentSensorCalib) * .78125;
   
    // Convert to AH used and add to total
    AHused = AHused + (CurrentRead * 0.0000002777);

would become something like this
Code:

    // Convert currentread to amps
    CurrentRead = (RawCurrentRead - CurrentSensorCalib) * .78125;
   
  // Convert to AH & add to low portion of total
  AHusedLow = AHusedLow + (CurrentRead * 0.0000002777);

  // Update AHused
  if (AHusedLow > 0.0003) {
      AHused = AHused + 0.0003;
      AHusedLow = AHusedLow - 0.0003;
  }

This is the simplest and fastest code change - I hesitate to put too much extra code in the ISR.

With 6 digits of precision, adding .0003 would give you good accuracy up to 99.9999 A-h for sure. Likely a bit higher but I've lost a lot of the details on floating point accuracy ... I'd have to re-learn some of that.

thingstodo 07-19-2012 02:28 PM

Scopes and Arduino external power
 
Quote:

Originally Posted by Daox (Post 317733)
I have yet to hook the arduino up to a more noise proof power source. I was going to do this but I am depending on the arduino's serial output to get feedback on the variables. I'm not sure how to connect the arduino to the computer without using the USB to power it. This is where a scope would come in quite handy.

I sometimes find it difficult to get a scope to trigger on a small change in the measured signal. You are not expecting a periodic signal that can be triggered 10 or 100 times a second to give you a nice stable display, so how are you going to 'capture' the 15 mV change?

I thought that an externally-powered USB hub would still allow you to plug your computer and the Arduino both in - but my computer tells me that the com port is not found. I guess you already knew that!

thingstodo 07-19-2012 03:49 PM

Chips and the Battery Management or Monitoring System (long-winded)
 
Quote:

Originally Posted by Daox (Post 317733)
Thanks for finding those chips! I'll have to take a look at them once I get the BMS in the car and running things properly.

I was looking for myself - your comment that others have done this and some of the work should be packed into a chip struck a cord. And you were right. It's only fair that I share the info.

I've been looking through the various Battery Management Systems for the past couple of days. The Open source projects I can find seem to use PICs of some sort. A lot of them used quite a few discrete components so they had PCBs fabricated.

Many people seem to find PICs easy to use. I find the code pretty easy to read but have struggled to get anything running in the past. I've had trouble with missing libraries, the wrong version of libraries, with 'examples' that have errors and won't run, with defines for a specific chip that I can't locate so the code does weird stuff, and likely a whole lot of other stuff that I simply have not solved so far .... I must not be bright enough to use a PIC. I need this system to be RELIABLE.

I like the Arduino so far.

I'm not looking for a Management system so much as a Monitoring system. If you monitor each battery in the whole pack you should be able to identify the weakest of the bunch. From there you can deal with it in any way that you like. The key for me is to IDENTIFY it.

I like what you have so far.

*Begin Rant*

The auto-balancing thing scares me a *LOT*. I find that few people know about Failure Mode and Effect Analysis (FMEA). Assuming that parts DO WEAR OUT eventually and designing a system to survive the failure and continue to do safe things in that failure mode seems like an almost-lost art.

It's my family at risk if a Battery Management System fails in some strange way that burns down the garage that my car is in, which is attached to my house. I may be a bit paranoid, but that has worked for me so far.

Heck, installing things backward is pretty common. On most systems, wiring it wrong causes immediate damage to core components - and they recommend throwing it away and ordering a new one. What happened to fuses? And Buffer chips? Having to order another one is a pretty extreme penalty for a simple wiring error, particularly when you are expecting people who don't understand the wiring to paint-by-number it together.

*End Rant*

I am building an experiment platform - SalvageS10 - and it will (at least initially) be running off a mixed bag of batteries. Pretty much anything that I can find and that is cheap. Well, not anything - it has to be safe to bolt onto a moving vehicle. I presently have about 80 old NiCd cells (1.2V each) from an old electrical substation in various states of ill repair (not likely safe to put in a highway vehicle, but OK to use on my yard for testing with some precautions), 4 used deep cycle Lead Acid flooded batteries (12V), an AGM battery (12V), around 40 Panasonic 7.2 Ah Gel-cells from a UPS in pretty bad shape ... and I expect to acquire a couple of large and heavy forktruck batteries that have been traded in for the core refund but *may* still have a couple of hours of running time in them.

So I would like to connect arbitrary batteries of widely differing voltages and chemistries together in any order I like and just monitor the heck out of them. The LTC680x chips allow up to 12 batteries and a total of 60V, so I won't be able to put the batteries in ANY order ... but the chips appear to be pretty flexible.

I would like to have the batteries numbered something like this:

10A1 in the format PPBC

PP -Pack - group of batteries in series. Force 2 digits

B - Battery - one of a series within a Pack, can contain more than one physical battery in parallel - a single Letter gives 26 maximum batteries in a pack

C - Cell - The smallest unit. Not used if there is only 1 battery in parallel. Used if 2 or more are in parallel. Single digit gives 9 maximum cells in parallel to make a battery.

I'd like to start with an Arduino reading a current sensor, like you have, and build from there.

If I can get the Arduino to read a configuration file (CSV file) from an SD card, which labels all of the batteries in all of the packs and specifies minimum, maximum, and alarm voltages ... that should be a good start.

The Arduino would then read all of the information from the LTC6803-2 chips (I will likely have at least 4 of them) and place that information into 4 arrays, I can log that data to csv files on the arduino and alarm when a cell went into alarm and for how long. That gives me history for each battery as long as I track it through whatever location in a pack that I put it. I have a small LCD module that I hope to connect to the Arduino that can give me some information. The alarm values will be guesses to start, but I can use the data to compute averages, show some discharge trends for the batteries and figure out min, max and alarm values (hopefully) pretty quickly.

There is another Arduino that will be connected to the PLC I'm using on SalvageS10 that will be logging speed, tach, amps, pack voltage, motor current, motor voltage, as well as every input and every output. That logging will also be to an SD card as a CSV file. After the test runs I will be loading all of the data together - likely into a spreadsheet - and correlating the timestamps. Weak batteries will be placed in parallel with other weak batteries or simply removed from the packs and replaced with stronger batteries - at least that's the plan.

The LTC680X chips will also measure temperature of the cells, ambient temperature, etc. I'm not interested in thermal management right now but could be in the future.

SOC is an interesting topic. The PLC on SalvageS10 will attempt to count coulombs to determine when it is time to shut down the test and recharge. It will be interesting to compare the coulombs measured by the truck and the coulombs measured by the Arduino.

A mixed set of a specific battery type (Flooded lead acid deep cycle, AGM, Gell cell, NiCd) would not likely work well with series charging of the whole pack since they self-discharge at different rates. Mixing chemistries will make that even more impractical, so I'm not sure how to charge this system. Some experimentation and a lot of manual charging with a maximum timer is likely the ticket initially.

That's where I'd like to be going in the near future. If that fits with your ideas (or at least - MOSTLY fits with your ideas) I can post the information to your thread.

Daox 07-25-2012 03:09 PM

That sounds like a lot of work! But it also sounds like you know what you're doing with the electronics side of things. I'm just bumbling through it working things out as I come across them. :) I'd love to hear how things progress and glad my project could help you with yours.

Daox 07-29-2012 09:01 AM

2 Attachment(s)
I've been talking with one of the local makerspace guys on ways to improve the BMS, but I also started building the BMS for my Prius' PHEV kit. All the components are back in the car and the only thing I'm waiting on now is the BMS.

I started building the 'bms shield' for the arduino yesterday. I'm not making it look super pretty, so I reused the little board (taped up one) that houses the opto-isolators. I had been using it for the charging side protection previously. So, I just wired it to the shield.

I also have to update my schematic a bit more as I went through and missed a few things. I had to add one resistor and remove a different one.

Building the shield is almost done. I still have to add the current sensor stuff, but that is what I have been talking to my friend at the makerspace about. Anyway, the main portion left to do is the 'front of the vehicle' section of the schematic that has the on/on switch and the SOC meter. There aren't many components there, but lots of wires off that 16 pin shift register chip.

Here are the pics so far.

http://ecomodder.com/forum/attachmen...1&d=1343566736

http://ecomodder.com/forum/attachmen...1&d=1343566736

Daox 07-31-2012 10:51 AM

The other night I borrowed an oscilliscope from work and took a shot at troubleshooting this current sensor issue. I found out the 5V going to the sensor varied a bit, but the vref and output from the sensor were pretty solid (+/- 1mV). I put a capacitor on the 5V input to the sensor and it smoothed things out a bit. I also tried running the arduino off of a 12V battery. Each time the 5V input got a little better, but through the whole thing the sensor output was still very steady.

So, now I am wondering why the arudino is reading a voltage fluxuation on the vref and sensor output pins. According to the serial feedback on the arduino, I'm seeing voltages of 2.519V to 2.539V. The scope showed a pretty consistent 2.513V. So, not only is it showing a voltage fluxuation that isn't there, it is also reading an incorrect voltage.

Daox 08-01-2012 01:30 PM

1 Attachment(s)
Going back to the current sensor issue. I heard that the open revolt controller is using some filtering on that sensor. So I looked it up and sure enough its there. I'll probably start by just copying what Paul has done. If that doesn't do the trick I'll start tweaking things.

http://ecomodder.com/forum/attachmen...1&d=1343842196

ericbecky 08-12-2012 01:59 AM

Tim,
In place of the $27 SSR in your diagram, I made a snubber circuit using three components. Total cost $6.83.

* Triac S216S02F Sharp Microelectronics | 425-2414-ND | DigiKey S216S02F $6.26
* 47 ohm resistor ULW3-47RJA1 TT Electronics/Welwyn | 985-1009-1-ND | DigiKey ULW3-47RJA1 $0.28
* 0.22µF capacitor B32922C3224M189 EPCOS Inc | 495-4200-2-ND | DigiKey B32922C3224M189 $0.29

And here is a link to my crude drawing of the snubber circuit. http://bit.ly/MO0qXb

Daox 08-12-2012 11:27 AM

Woohoo, great. Thanks for getting me that info Eric. That'll help bring down the cost of the BMS for sure. :thumbup:

Make sure to post the final version of your BMS when you get it all put together. AFAIK you're the only other person building one based off my design.

ericbecky 08-12-2012 03:34 PM

Thanks for getting this project so far along. It's been a lot of fun and good challenge for my brain.

For now I'm not sure how much farther I'll be going since this fits my needs.

Probably won't think about it until the end of September when I get a bit more free time.

Daox 08-13-2012 08:12 AM

I made some progress on my BMS this weekend. I worked on the electronics up in the front of the car. This mainly just is the SOC meter and on/off switch. The pain is trying to fit everything I want into a blanked out dash insert. I think I have it all laid out so it'll work, but it took some time to put together.

Here is the blanked out dash insert with a hole cut in it for the SOC gauge.

http://tercelreference.com/downloads/prius082.jpg

http://tercelreference.com/downloads/prius083.jpg




Here is half of the circuit board that will mount up to the dash insert. The other half will have the shift register and voltage regulator on it. The toggle switch is for the plugin kit. The momentary switch is to put the Prius into EV mode.

http://tercelreference.com/downloads/prius084.jpg

Daox 08-15-2012 09:32 AM

2 Attachment(s)
I've been working on the second board for this section of electronics. Its been interesting trying to cram everything on the board, and I still have a little ways to go...

Here is the second board with most of the components on it.

http://ecomodder.com/forum/attachmen...1&d=1345037411




Here is how it will attach to the first board.

http://ecomodder.com/forum/attachmen...1&d=1345037412

skeeterb 08-15-2012 10:38 AM

It's been a while since I've posted on this thread, but I'm thrilled by the progress that you are making Daox. If I were to convert I'd probably use one of Paul's designs for a motor controller and your BMS to keep the batteries managed, that would probably really keep the costs down. It would mainly be the batteries, the motor, and the few other important bits like the fuses and contactor that would make it pretty costly. Keep up the good work and keep us informed :D

shauger 08-18-2012 06:31 PM

Great thread! I have quite a few 60 amp-hr LFP large format cells leftover from a school project. They are new - we never used them. Send me a PM if you're interested.

Daox 08-19-2012 11:55 AM

Thanks skeeterb and shauger. I can't wait to get the full system into the car and try it out. There just always seems to be one more thing to do before that can happen!

skeeterb 08-19-2012 06:27 PM

Quote:

Originally Posted by Daox (Post 322505)
Thanks skeeterb and shauger. I can't wait to get the full system into the car and try it out. There just always seems to be one more thing to do before that can happen!

Doesn't it always seem that way?

Daox 08-27-2012 08:16 AM

Haha, yes it certainly does.

The soldering on the display/switch panel is all done except for connecting the wires that go back to the arduino. I also have it mounted in the plastic dash piece. Sorry, I didn't snap any pictures of it yet.

One thing I am questioning is how to attach the wires to the board and stress relieve them. The wires are only phone/ethernet line, so they're probably 28 gauge or so (tiny). I need a way to hold them in place so they don't break over time.

Daox 08-31-2012 07:23 AM

1 Attachment(s)
Just a small update. I finally snapped a picture of the mostly done SOC gauge and on/off switch. I still have to pop a hole in it for the EV button switch. The LED bargraph is a bit more inset than I had hoped. I'm contemplating unsoldering it and adding a socket under it to bring it up a bit more, but I'll probably just live with it.

http://ecomodder.com/forum/attachmen...1&d=1346412152

skeeterb 08-31-2012 03:45 PM

Looks pretty good Daox.


All times are GMT -4. The time now is 10:25 PM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Content Relevant URLs by vBSEO 3.5.2
All content copyright EcoModder.com