Linear Tech 12-cell battery monitor/BMS

For anyone interested, the schematic for the demo board Version C is here:

DC1221C Schematic & Quick start guide

Looks like they sprinkled CYA fairy dust all over the board for this version.
I am going to clear off as much of that cruft as possible and post my strip down (aka broke bastard) schematic in a few days
Hey... $0.25 diodes and $0.37 transistors add up fast with high channel count! :oops:

-methods
 
Wow, yea, there's a LOT that can be dropped there. I had do so that with the "other" chip I'm playing with too. At least 3/4 of the evaluation board parts list wasn't needed, even for a really robust system.

Looking forward to seeing the bare-bones setup! :)
 
I think I am going to drive my prototypes with this Arduino board.
It is the best - tiny, built in USB driver, built in 6-20V regulator, built in auto switching USB power, built in LED, reset button, & header -

Arduino Nano 3.0

There is no easier way to get up and running for $30 :p
They even have a nice little screw terminal shieldfor lazy people like me

currently I have the exact same setup in a larger form factor

-methods
 
I ordered samples:

4 x LTC6802IG-1#PBF
4 x LTC6802IG-2#PBF
1 x DC1221A (I pointed out to them that I thought I should get a C, not an A and I have not heard back. I am sure it will be a C.... :| )

I plan to D-test the DC1221X and that is what the extra chips are for.
I probably wont use them all so if anybody needs one let me know and I will mail it out to you.

First order of business is to lift the expensive ESD protection, half of those zener diodes, all of the RC filters, all of the shunt equipment, and anything that tries to crawl away. I will give it the ol'methods shuffle-foot treatment and see if it degrades. We will see how good those internal diodes are. :twisted:

I am going to photo-shop up a few versions of the schematic with my interpretation of what they are trying to do with the excessive components and my argument for why they can be eliminated. After reading the datasheet a few times and going over the schematic I think I understand most of what they were trying to achieve. Cruft!

-methods
 
Does anyone have an Eagle part for the LTC6802-1?

I am making one but it is a lazy-man version.

-methods
 
So the Demo board is now up to Rev D. When it arrives I will let you know what I find in terms of changes.
I did some advanced searching and found the entire database of Linear demo datasheets, schematics, and - drum-roll please..... Design files + GUI

Have a look -
Every Linear Demo board since the dawn of time (Manual + Schematic + GUI)

DC1331C - Demo Manual - dc1331C.pdf
DC1331C - Design Files - 1331C.zip (The GUI and all the design files)
DC1331C - Schematic - 1331csch.pdf

-methods

EDIT: Man - everything is in there down to the pick-n-place coordinates. Attached is the Ver.C BOM for lazy bums.
 
Rev D?
I'd love to hear what the differences are! I had to wait several months for my Rev C but my rep told me that the previous revs definitely needed a robustness upgrade and the wait would be worth it. :)

I thought I did an Eagle part for the LTC6802, but I checked and no joy. :cry:
 
I got tired of waiting for my demo board so I made my own strip down version.
All that is left to do is CLK, MISO, MOSI, and CS

This is a 12S lipo monitor + 1 temperature input + 1 interface to Shunt Current Amp
Configured to be always at the top of the stack
Bottom port easy to change from TTL to current

And will you look at how perfect those JST-XH 7P 90 headers plugged in :mrgreen:
In the morning I will solder up the last 4 communication wires and test it with a 12S 2P

This particular protoboard is awesome. The mask rides ABOVE the lands so when you set the chip down it locks into place. They are tinned very well so with the iron set to 800 you can just push the solder up onto the wings. This is an SSOP 44 pack on 0.5mm centers.

No protection diodes, no bypass caps, no ESD protection, no RC filtering, no current limiting resistors - nothing but what it needs to actually run for a communications test.
In the actual prototype I will be running all of the protection diodes & the RC filtering. After carefully reading the datasheet and listening to the failure modes that people experienced I am fairly sure the bypass diodes are necessary on the hot side. I was on the fence about the low pass filter but thinking about how noisy the brushless controllers probably are (and how high they switch) I decided to keep them.

By the end of this weekend I will have a functional prototype w/full communications to the host PC

View attachment 001_Proto001.jpg

-methods
 
Of course - half way through I missed 2 holes and ended up having everything staggered :roll: :roll: :roll: :roll: :roll: :roll: :roll: :roll: :roll:

Made the corrections, checked all the connections, wired up the SPI, downloaded the SPI libraries, ready to go.

All I have to do now is hook up 50V worth of lipo :|
To say I am apprehensive would be an understatement. I dont have any of the protection circuitry wired in - none of the diodes.....
I think instead of trying to actually monitor 12 cells I may make a 12 leg resistor ladder and measure that. The good thing is that I will be able to apply 50V across the entire ladder at once - eliminating several of the failure modes.

Yep - that is what I need to do. Perhaps I can use some clever resistances to give me predictable variance down the path.

View attachment 001_Proto002.jpg

-methods
 
Throw a couple of trimpots in your stack of resistors so you can "play" with the votages in realtime.
 
methods said:
I think instead of trying to actually monitor 12 cells I may make a 12 leg resistor ladder and measure that. The good thing is that I will be able to apply 50V across the entire ladder at once - eliminating several of the failure modes.

-methods
Great idea! I did the same thing for my testing of another chip. Saved me more than once. :D
 
Stayed up half the night - no dice.
Went to bed, tossed an turned, woke up, saw the mistake, GOT IT WORKING :p

View attachment 001_Proto003.jpg

The first test is to read the configuration registers.
There are 6 configuration registers. The default value for the first register should be 0xEF.

Here is what I drove it with:

0x02 // Command "Read Control Registers"
0x02 // Pump in 6 registers
0x02
0x02
0x02
0x02
0x02 // CRC

(Only the first byte matters, the rest are just placeholders. With SPI the master must always drive the clock so you are arbitrary pumping out data no matter what)

Here is what I got for a response:

FF // idle while driving command
E0 // First byte as expected!
0 // bytes 2-6 as expected
0
0
0
0
A1 // the CRC

CRC is 8 bit: x^8 + X^2 + X + 1

Checking this really quick with an online CRC calculator http://smbus.org/faq/crc8Applet.htm
A1 is in fact the correct checksum for E00000000000.

Here is the code I used. This is Arduino code.

The general idea is that I call an SPI library that sets up the SPI pins
I set up the port per the datasheet
I wait for the user to enter a command, convert it from ASCII to HEX, drive chip select, send the command, read back 6 bytes, read back the CRC, then print the results back on the USB port.

//*****************************************************************************
[pre]#include <Spi.h>

// Driver for the LTC6802-1
// Monitor only - 36 cells

//pin 13 SCK_PIN SPI clock
//pin 12 MISO_PIN SPI master in, slave out
//pin 11 MOSI_PIN SPI master out, slave in
//pin 10 SS_PIN SPI slave select

#define TALK digitalWrite(SS_PIN, LOW); // Chip Select
#define DONE digitalWrite(SS_PIN, HIGH); // Deselect

// LTC6802-1 Command Codes (short list)
#define WRCFG 0x01 // Write config
#define RDCFG 0x02 // Read config
#define RDCV 0x04 // Read cells
//#define RDFLG 0x06 // Read flags
#define RDTMP 0x08 // Read Temps

#define STCVAD 0x10 // Start all A/D's - poll status
#define STOWAD 0x20 // Start testing all open wire - poll status
#define STTMPAD 0x30 // Start temperatures A/D's - poll status


void setup()
{
// SPI Configuration
// No interupt, Enable SPI, MSB first, Master, Clock rests high,
// Read on rising edge, 1Mhz speed
DONE // Set CS High
Spi.mode((1<<SPE) | (1<<MSTR) | (1<<CPOL) | (1 << CPHA) | (1 << SPR1) | (1<<SPR0) );
Serial.begin(9600);

}

void loop() {
byte userInput;
byte ltcResponse[9];

if (Serial.available())
{
userInput = (Serial.read()) - 0x30; // convert from ASCII

TALK
for(int i=0; i<8; i++)
ltcResponse = Spi.transfer(userInput); // Command
DONE

for(int i=0; i<8; i++)
Serial.println(ltcResponse, HEX);
}
}[/pre]
//*****************************************************************************

Methods >= happy

-methods
 
You're the man Methy! Great work getting that thing to talk!

Super cool stuff! Makes me wish I hadn't skipped my uController class 80% of the time. lol
 
User interface working
Register config working
Start A/D's working
Read A/D's working

Example output:
Below I first sent 99 then 44 while it was not connected. Recognized
I then sent the invalid command 99. recognized
I then sent it the command to read the config registers. recognized
I then told it to read the A/D registers - empty
I then told it to wake up and take an A/D sample
I was then able to read A/D values

Ignore the numbers - they are 12bit readings stretched across 8 bit registers.
Next is to decode the bits and see about accuracy :)

Code:
Command = 0x99
Comm failure
_____________________
Command = 0x44
Comm failure
_____________________
Command = 0x99
Are you retarded?
1 write config, 2 read config
4 read cells, 6 read flags
8 read temps, 10 start A/D's
_____________________
Command = 0x2
Read Configuration Register Group
E0
0
0
0
0
0
A1
_____________________
Command = 0x4
Read Cell Voltage Register Group
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
_____________________
Command = 0x10
Start A/D Conversion
_____________________
Command = 0x4
Read Cell Voltage Register Group
70
A8
87
5C
A8
8C
73
F8
89
AE
58
89
7B
_____________________


The code used to obtain that output is here.

Code:
#include <Spi.h>

// Driver for the LTC6802-1
// Monitor only - 36 cells

//pin 13	SCK_PIN	        SPI clock	
//pin 12	MISO_PIN	SPI master in, slave out
//pin 11	MOSI_PIN	SPI master out, slave in
//pin 10	SS_PIN	        SPI slave select

#define TALK digitalWrite(SS_PIN, LOW);    // Chip Select
#define DONE digitalWrite(SS_PIN, HIGH);   // Deselect

// LTC6802-1 Command Codes (short list)
#define WRCFG    0x01  // Write config
#define RDCFG    0x02  // Read config
#define RDCV     0x04  // Read cells
#define RDFLG    0x06  // Read flags
#define RDTMP    0x08  // Read Temps

#define STCVAD   0x10  // Start all A/D's - poll status
#define STOWAD   0x20  // Start testing all open wire - poll status
#define STTMPAD  0x30  // Start temperatures A/D's - poll status


void setup()
{
  // SPI Configuration
  // No interupt, Enable SPI, MSB first, Master, Clock rests high,
  // Read on rising edge, 1Mhz speed
  DONE  // Set CS High
  Spi.mode((1<<SPE) | (1<<MSTR) | (1<<CPOL) | (1 << CPHA) | (1 << SPR1) | (1<<SPR0) );
  Serial.begin(9600);
  
}

void loop() {
  int userInput;
  byte wake;
  byte ltcResponse[20];
  byte commandSize;
  byte printSize; 
  byte waitms;
   
  waitms = 0; 
  wake = 0;
    
  if (Serial.available() >= 2)
  {
    userInput = (Serial.read()) - 0x30;    // convert from ASCII
    userInput = userInput << 4;
    userInput |= (Serial.read()) - 0x30;    // build into 2 byte hex
    // Get user's choice
    
    Serial.print("Command = 0x");
    Serial.println(userInput, HEX);
   
   // Confirm that we are communicating well.  Break out if not
    TALK
    for(int i=0; i<2; i++)
      ltcResponse[i] = Spi.transfer(0x02); // Try to read a 0xE0
    DONE
    
    if(ltcResponse[1] != 0xE0)  // Check to make sure we are connected
    {
      Serial.println("Comm failure");  // report and break if not.
      printSize = 0;
      Serial.println("_____________________");
    }
    else              
    {
       switch (userInput) {         // At this point we have good comms with LTC
      case WRCFG:
        Serial.println("Write Configeration Register Group");
        // Send command + 6 bytes
        // No return
        // Not implementing this now - no need.
        printSize = 0;
        break;
      case RDCFG:
        Serial.println("Read Configuration Register Group");
        // Send command
        // Read 6 bytes + CRC
        commandSize = 8;
        printSize = 7;
        break;
      case RDCV:
        Serial.println("Read Cell Voltage Register Group");
        // Send command
        // Read 12 bytes + CRC
        commandSize = 14;
        printSize = 13;
        break;
      case RDFLG:
        Serial.println("Read Flag Register Group");
        // dont care
        printSize = 0;
        break;    
      case RDTMP:
        Serial.println("Read Temperature Register Group");
        // dont care
        printSize = 0;
        break;        
      case STCVAD:
        Serial.println("Start A/D Conversion");
        // Send Command
        // No return
        commandSize = 1;
        printSize = 0;
        waitms = 20;
        wake = 1;
        break;    
      case STTMPAD:
        Serial.println("Start Temperature A/D Status");
        // Send commmand
        // No return
        commandSize = 1;
        printSize = 0;
        break;      
      default: 
        // if nothing else matches, do the default
        Serial.println("Are you retarded?");
        Serial.println("1 write config, 2 read config");
        Serial.println("4 read cells, 6 read flags");
        Serial.println("8 read temps, 10 start A/D's");
        printSize = 0; 
      }
      
      if(wake == 1)
      {
        TALK
        Spi.transfer(0x01);   // Command Set 
        Spi.transfer(0xE2);   // Command Wake up
        Spi.transfer(0x00);   // Command
        Spi.transfer(0x00);   // Command
        Spi.transfer(0x00);   // Command
        Spi.transfer(0x00);   // Command
        Spi.transfer(0x00);   // Command
        DONE
      }
     
     // Here we print out as much as need be for the operation
      TALK
      for(int i=0; i<=commandSize; i++)
        ltcResponse[i] = Spi.transfer(userInput);   // Command
      
      delay(waitms); // used for
      DONE
      
      for(int i=1; i<=printSize; i++)
        Serial.println(ltcResponse[i], HEX);

      Serial.println("_____________________");
    }// end if
  }// end outer if
}

-methods
 
I blew it up.
At some point I blew out the SDO pin - stuck low.
Probably happened when I removed the 12S lipo pack while SDO was still connected directly to the uC
So thaaaaaaattttttssssss why they have all that crap on the input :mrgreen:

Tried to pull the chip with a heat gun - ended up melting every wire on the board together :roll:
Oh well - at least it worked once :)

I converted the A/D readings and they were off.
I suspect that I was not giving the A-D time to settle

We will find out later when the demo board arrives. No way in hell am I soldering up another one of those bastards :?

-methods
 
Congrats on your initial success! Sorry to hear the chip blew. :(
I have heard some anecdotal stories about how sensitive the LTC6802 is. Wish it was emphasized more in the documentation for it.
 
Wait a second here.....

The temperature input (1 and 2) is biased between the reference voltage and "ground" but on the top LTC "ground" is actually 22V or 44V or 66V.... This means that if I hook up a temperature sensor and send it off into the system someplace it will be a hot wire! That is no good at all........ I can see it now, scuff an RTD wire and make lightning :?

Crap. I was depending on using those. Now I have to find an external serial 12bit ADC

-methods
 
The ref output drops like a rock if the load impedance is much lower than 100K. And with the thermistor being a 100K unit, the current flow will be pretty low is there's any problem "after" the thermistor. Still pops the chip though if there's a short to anyplace nasty. :(

Just thinking out loud here, not really sure...
Won't you still have the same problem using an external ADC (I really like Microchip's 12-bit models, very easy to use)? That is, if any wire gets scuffed, there's gonna be trouble?
 
I think generally if someone sees an RTD with 2 wires they assume there is no appreciable voltage on those lines.
In this case one of those wires is a direct 0 ohm shot to 66V (or whatever the voltage is on the stack just below).
Not worried about popping the chips - just worried about having a long wire in the system that people assume is only an RTD but is really V+.

Something like balance lines are kept short and protected but RTD's are flapping in the wind.

View attachment 001_DS.jpg

-methods
 
Hmm...good point.

Actually, I would think that any users of a BMS would think that every cable could be dangerous, should be protected, and that if one gets damaged it should be replaced and not touched. I agree, it's not the safest approach to take with a design, but so many things are so darn dangerous with an HV pack that I'm not sure if a decent physical design for protecting the cable (in between cells, metal braid sheath around the wire, etc.) isn't good enough.

Wait a sec...
Am I the one saying spend less and remove stuff and you're the one saying to add cost-increasing, space-hogging electronics to something? Now THAT'S a reversal for us! :mrgreen: :mrgreen: :mrgreen:
 
methods said:
...
...

Something like balance lines are kept short and protected but RTD's are flapping in the wind.



-methods
Just use two 50k Ohm resistors (instead of a single 100k), one on each end of the cable. That should make it relatively safe all along.
 
WOW WOW WOW !!!!!!!!!

Holly crap - I just did a test to see how accurate the LTC6802 is..... The worst case error was 0.05%
This came down to the LSB resolution of the Fluke!
In other words - DNO (Dead Nuts On)

Room temperature using demo board DC1331
JST-XH extension cables tied to 12S 5Ah of Lipo

Code:
LTC6902	Fluke 87V	% difference
4.052	4.053	-0.02%
4.018	4.018	0.00%
4.045	4.046	-0.02%
4.051	4.052	-0.02%
4.043	4.044	-0.02%
4.079	4.080	-0.02%
4.052	4.054	-0.05%
4.031	4.032	-0.02%
4.046	4.048	-0.05%
4.054	4.054	0.00%
4.043	4.045	-0.05%
4.078	4.079	-0.02%

LTC_Error_Test.jpg
View attachment 001_LTC_ERROR_TEST2.jpg

-methods
 
Ok - I need to make a purchase and I would like to see if anyone can help me break into the 100 unit pricing.

http://www.linear.com/pc/productPurchase.do?navId=H0,C1,P86662&partNumber=LTC6802-1
1-99____$13.86 each
>100____$11.59 each

I can probably justify picking up 60 of them but I dont want to have too much of my cash tied up.
Where are you guys getting yours? I KNOW these can be had for less. . . . . $9 sounds more like it....

-methods
 
Hi Method, Good work on getting it to read! I'm willing to join the group buy. How many more units do you need to get to 100?
 
I should know by Thursday morning.
I am going to select the LTC6802-1 though... Most people design with the LTC6802-2.

The -1 is on revision D (same part used on the demo board) and I am confident that the communication issues have been worked out.
I like the fact that it uses less external components.

I suspect at this point that a lot of the problems that people were having were due to a lack of documentation by Linear. With the Rev C documentation and implementation I think reliability will go way up.

-methods
 
Back
Top