# 1st Gen Chevy Volt BMS Balance Commands Found



## swoozle (Nov 13, 2011)

Here's how to command your OEM Chevy Volt BMS BICMs (slaves) to bleed charge off of specific cells in order to keep them in balance. 

This does not involve the BECM (master). I wasn't able to figure out the command(s) to send the BECM to get it to initiate this work. This is a more manual method that involves sending the BICMs commands indicating which specific cells to bleed. You still have to figure out which cells are out of balance and do the heavy lifting of dropping them to the right level. This would be done by continually sending these commands to the BICMs on a CAN bus with just the BICMs, no BECM.

A little background is useful. In normal operation every 200 milliseconds the BECM sends 3 CAN frames: 0x200, 0x300 and 0x310. If the 0x200 CAN frame contains data content of 0x020000, all connected BICMs send back the voltage and temperatures of their battery modules. That much has been documented.

It turns out that 0x300 and 0x310 are queuing commands for bleeding energy from specific cells. When a specific cell location is sent in either of those commands, the next 0x200#020000 frame causes the BICM to bleed energy from that cell for about 130 milliseconds. 
Attached is a scope cap showing that action. This was taken from a BICM PCB across a 1 ohm resistor on the trace that connects the cells to the measuring/bleeding circuits.

The first two blips are the BICM opening a small transistor on the trace to measure the cell voltage. Negative blip is the cell we're watching, positive blip is the next higher cell.
Then since this cell was commanded to bleed, the BICM opens its circuit to bleed across a couple of 15 ohm resistors in series. There are a couple of 1 ohm resistors and a diode in that path so the bleed current ends up being about 100 mA.

If the right 0x300/310 command is sent, this happens every 200 msec.

I've mapped out the right 0x300/310 data bits that correspond to each cell and will drop them in the next post.


----------



## Tomdb (Jan 28, 2013)

Hat off to you. 

Very good work, i will now look at implementing it in my code ofcourse.


----------



## jbman (Oct 26, 2017)

That's huge, thanks!

Sent from my SM-N960U using Tapatalk


----------



## swoozle (Nov 13, 2011)

Thanks, guys. 
Here are the details.

0x300 takes 8 bytes of data
0x310 takes 5 bytes.

I'll attach a csv/xls with the location mapping table, but it looks like this:


```
0x460:	1	3	1-3	300#XX.00.00.00.00.00.00.00	01	02	04	
0x470:	1	3	4-6	300#XX.00.00.00.00.00.00.00	08	10	20	
0x461:	1	4	7-10	300#00.XX.00.00.00.00.00.00	08	04	02	01
0x471:	1	4	11-14	300#00.XX.00.00.00.00.00.00	80	40	20	10
0x462:	1	4	15-18	300#00.00.XX.00.00.00.00.00	01	02	04	08
0x472:	1	4	19-22	300#00.00.XX.00.00.00.00.00	10	20	40	80
0x463:	1	4	23-26	300#00.00.00.XX.00.00.00.00	01	02	04	08
0x473:	1	4	27-30	300#00.00.00.XX.00.00.00.00	10	20	40	80
```
The files have column headers but they mess up the formatting here, so:
The first column is the voltage reporting CAN frame ID, 
the second is the BICM number,
the third is the number of cells in that CAN frame group,
the fourth is the cell number designation starting from the POSITIVE end,
the fifth is the specific CAN command (in linux canutils cansend format) to designate that cell with XX placeholding for the next columns
and the last four are the specific hex data values that go in the placeholder for each sequential cell in that group.

Again, look at the file, it will make better sense.

So to draw down the cell at the most positive end of the pack, you would send:
0x300#01.00.00.00.00.00.00.00
0x200#020000

every 200 milliseconds until it reaches the voltage you want.

I don't know what the rules are for queuing multiple cells as it's a pain to detect when one of these things is bleeding, let alone monitoring multiple cells at once. I know you can't queue adjacent cells because I tried it. Which makes sense. The higher cell dumps its current onto the high volt trace of the lower cell.
I would guess that at the very least you could queue up cells in different BICMs, possible even the different computational groups within each BICM.

If anyone knows of an easy way to detect multiple cell bleed activity, please let me know. I need to do this same mapping on my car pack. My car pack is two parallel 42 cell strings and the BICMs send duplicate voltage reporting frames (like two 0x460 frames) and I need to be able to detect if that means the bleed mapping duplicates as well.


----------



## bilbo (Oct 31, 2017)

That is some great work!

How did you find the the relevant labels (0x300, 0x310, 0x200)?


----------



## swoozle (Nov 13, 2011)

bilbo said:


> That is some great work!
> 
> How did you find the the relevant labels (0x300, 0x310, 0x200)?


Thanks but it was really just luck.

If you look at the BECM-BICM CAN bus traffic, it's constantly repeating the same small number of frames. Other people had decoded all of the module voltage and temperature frames that the BICMs put out so it was easy to eliminate those. 
That left only 0x200, 0x300 and 0x310.
0x300 and 0x310 are always empty (that I'd seen. Now we know why).

Awhile back I tried repeating a captured 0x200 frame to just the BICMs and quickly figured out that it was the prompt for them to spit out their data. That left 300 and 310. I could never figure out what they did.

When I got interested recently in the balancing command again I did what I could on the external BECM bus using your ideas but couldn't get anything to work. I was still sniffing the internal BECM-BICM bus so I went back to that. I had also soldered some leads to one of the BICM balance resistors so I could tell when balancing was happening for one cell. 
It occurred to me that those two unknown CAN ids might have something to do with balancing so I ran cangen and put random data in those frames. Luckily I still had the BECM on the bus so it was still generating the 0x200 frames. Very quickly I saw blips on the balance resistor and then it was just a matter of elimination to replay bits of traffic to home in on the relevant commands. 

Mapping the cells is a pain in the butt. I certainly wasn't going to solder leads to every single BICM cell position so I made a breakout board with a protoboard and jumper leads to get easy (relatively) access to the BICM-battery wiring. It turns out that if you put a scope on a cell positive and negative leads it will pick up that balancing activity. Probably the little bit of resistance added by my breakout board connections helped that. Then it was just a matter of a couple of hours to swap it onto the different BICM connectors and map out the bit pattern.


----------



## Nuts&Volts (Dec 20, 2011)

Awesome work. I wish I could buy you a beer


Sent from my iPhone using Tapatalk


----------



## Tomdb (Jan 28, 2013)

Looking at the build up of the balancing messages its really straight forward.

Atleast that is if you take the reporting message IDs to build your voltage arrays.

I literally just take the report message id - 459 and then use that to bit shift the cell positions in to the various bytes of the messages. 

Luckily there is logic between how they number and report out cell voltages and how they structure the balancing requests.

Anyone want to sniff around in my code:


```
void BMSModuleManager::balanceCells()
{
  for (int c = 0; c < 8; c++)
  {
    msg.buf[c] = 0;
  }
  for (int y = 1; y < 9; y++)
  {
    if (modules[y].isExisting() == 1)
    {
      int balance = 0;
      for (int i = 1; i < 9; i++)
      {

        if (getLowCellVolt() < modules[y].getCellVoltage(i))
        {
          balance = balance | (1 << i);
        }
      }
      msg.buf[y - 1] = balance;
    }
  }
  msg.id  = 0x300;
  msg.len = 8;
  Can0.write(msg);

  for (int c = 0; c < 8; c++)
  {
    msg.buf[c] = 0;
  }
  for (int y = 1; y < 9; y++)
  {
    if (modules[y].isExisting() == 1)
    {
      int balance = 0;
      for (int i = 1; i < 9; i++)
      {
        if (getLowCellVolt() < modules[y].getCellVoltage(i))
        {
          if (y < 11 || i < 4)
          {
            balance = balance | (1 << i);
          }
          else
          {
            balance = balance | (1 << (i+1));
          }
        }
      }
      msg.buf[y - 8] = balance;
    }
  }
  msg.id  = 0x310;
  msg.len = 5;
  Can0.write(msg);
}
```
Full bms code: https://github.com/tomdebree/AmperaBattery/tree/master/VoltBMSV2


----------



## swoozle (Nov 13, 2011)

Nice, Tom. That'll make it a lot easier to use balancing. Thanks.

Oh, I was wrong about not being able to queue up adjacent cells. You can, it's just harder to see. The way I am detecting it, adjacent signals stomp on each other a little.

I've confirmed that carries through a full module; you can queue up more than one cell to balance in a module. And I'm sure that carries through the whole pack.
I've yet to try more than two at a time (next on the to-do list), but I'd be surprised if there was a limit. 

It takes quite awhile to see the results. I've run the experiment to confirm a rough calculation: it takes on the order of an hour of feeding the balance command every 200 ms to see an unmistakable change in the cell voltage reported (0.001V). 
One confounding problem is that the whole pack is also slowly drawing down from the act of sampling the voltages at the same time the balancing is occurring. It's a noticeable drain when running the BMS for an extended period and tracking cell voltages to the millivolt.

The other confounding issue is that the voltage readings bounce around more than 0.001V. It'd probably be easier to see by averaging the reading over time.


----------



## swoozle (Nov 13, 2011)

Using a 12 cell module on BICM 4, I've confirmed that at least every other cell in a module can be queued up for balancing in one shot.
e.g., I saw balancing on cells 1,3,5,7,9 and 11 at one shot.

I gave up at that because as I said it's very difficult to see balancing when adjacent cells are active. 

Although I did see that queuing ALL of the cells didn't work. Nothing balanced in that case.

So somewhere between every other cell and all cells there is a limit.

The queuing rules so far:
1. Every other cell can be queued.

2. Adjacent cells can be queued to some unknown limit. Limit is greater 2 and less than 12. 
- All cells cannot be queued.


----------



## kablammyman (Mar 16, 2017)

Tomdb said:


> Looking at the build up of the balancing messages its really straight forward.
> 
> Atleast that is if you take the reporting message IDs to build your voltage arrays.
> 
> ...


Slightly off topic: 
wait....this is all c++...since when is automotive code not in asm? Is this for a custom board or for an arduino? Where can I find out more about how you guys are putting this stuff together and compiling code?

Sorry for derailing the convo a bit.


----------



## swoozle (Nov 13, 2011)

kablammyman said:


> Slightly off topic:
> wait....this is all c++...since when is automotive code not in asm? Is this for a custom board or for an arduino? Where can I find out more about how you guys are putting this stuff together and compiling code?
> 
> Sorry for derailing the convo a bit.


Actually, we're talking CAN. There are many ways to speak CAN to the BMS. I'm using a CAN adapter on a Raspberry Pi with Python. Tom has his own custom board (that uses the Arduino IDE tool chain I think).


----------



## swoozle (Nov 13, 2011)

swoozle said:


> Nice, Tom. That'll make it a lot easier to use balancing. Thanks.


Well, it would if I could actually follow what you're doing. 
That's beyond my meager coding skills.


----------



## kablammyman (Mar 16, 2017)

swoozle said:


> Actually, we're talking CAN. There are many ways to speak CAN to the BMS. I'm using a CAN adapter on a Raspberry Pi with Python. Tom has his own custom board (that uses the Arduino IDE tool chain I think).


where did you get your adapter? Where can I learn more about this stuff?


----------



## swoozle (Nov 13, 2011)

kablammyman said:


> where did you get your adapter? Where can I learn more about this stuff?


There's a ton of info on using various computing platforms to read/write CAN. Just start with your favorite SBC and add "CAN bus" to the google search. All kinds of videos and tutorials will pop up.

Personally, I've used both a Raspberry Pi with a Canberry
http://www.industrialberry.com/canberrydual-v2-1/

as well as a MUCH cheaper chinese adaptor with equal success.
https://www.aliexpress.com/item/She...978.html?spm=a2g0s.9042311.0.0.7c364c4d1GtTku

The canberry is a lot more plug-and-play and appropriate for starting out.


----------



## kablammyman (Mar 16, 2017)

swoozle said:


> There's a ton of info on using various computing platforms to read/write CAN. Just start with your favorite SBC and add "CAN bus" to the google search. All kinds of videos and tutorials will pop up.
> 
> Personally, I've used both a Raspberry Pi with a Canberry
> http://www.industrialberry.com/canberrydual-v2-1/
> ...


awesome, thanks for this info!


----------



## ybpvin (Jul 11, 2019)

swoozle said:


> Thanks, guys.
> Here are the details.
> 
> 0x300 takes 8 bytes of data
> ...


Great job done! I take off my hat))


----------



## zubmio (May 19, 2020)

I have recently bought a Gen 1 Volt battery set. I am working on putting it in my S10 that has been sitting parked with no batteries for about 5 years. Here are a few questions I have about cell balancing:
1. If I leave the set originally wired (96 cells in series) and I give 12V power and ignition signal to BEMC (and it starts communicating with slaves - confirmed) will it (BEMC) take care of cell balancing if needed? Or, does it need to talk to someone else, or … ?
2. If so …. and if I re-wire the set into two strings of 48 cells each (first 30 and last 18 will make one string and the rest will be the other) would BEMC be bothered by it or will it continue to monitor/balance the cells?

Thanks


----------



## swoozle (Nov 13, 2011)

zubmio said:


> I have recently bought a Gen 1 Volt battery set. I am working on putting it in my S10 that has been sitting parked with no batteries for about 5 years. Here are a few questions I have about cell balancing:
> 1. If I leave the set originally wired (96 cells in series) and I give 12V power and ignition signal to BEMC (and it starts communicating with slaves - confirmed) will it (BEMC) take care of cell balancing if needed? Or, does it need to talk to someone else, or … ?
> 2. If so …. and if I re-wire the set into two strings of 48 cells each (first 30 and last 18 will make one string and the rest will be the other) would BEMC be bothered by it or will it continue to monitor/balance the cells?
> 
> Thanks


I'm not aware that anyone has seen the BECM initiate balancing on its own. It needs a command from somewhere else to do that. 
I'm also not aware that anyone has figured out what that command sequence is.


----------



## BogdanT (Sep 15, 2018)

I'm currently working on a Volt pack with SimpBMS, configured as 2 strings in parallel.
Does anyone know if the canbus connections to the slaves can be swapped?
eg: Original wiring goes through modules 30-24-24-18, with 30 being the first and 18 the last. 

The reconfiguration means now that I have 30+18 in the front, and 24+24 in the back, and for simplifying the wiring I would like to connect them in the order 30-18-24-24.

Would that work or there's something in the last slave (18) that would need to keep it the last in the chain?


----------



## swoozle (Nov 13, 2011)

No, that won't work. The first three BICMs have two pairs of CAN bus wires in the connectors to take the signal from the upstream BICM and pass it to the downstream. The number 4 BICM does not. It only has one pair of connections. Internally there is nothing connected to the 2nd pair of pins.


----------



## BogdanT (Sep 15, 2018)

@swoozle do you remember if the slaves were spitting the voltages at the same time as receiving the balance command? 

I'm playing around with the SIMP code and as soon as it enters "balance" mode (frames 300 and 310 populated) there are no CAN messages coming from the slaves.


----------



## swoozle (Nov 13, 2011)

Yes, the 300/310 frames don't result in any CAN traffic. They seem to only internally queue up the cells to balance and the 200 frame both triggers the balance and results in the voltage measurement data frames being sent.


----------



## BogdanT (Sep 15, 2018)

I meant to say as soon as I send 300 (populated) + 310 (populated) + 200 -> no more CAN responses from the slaves. If I send just the 200 frame, they are responding. Probably I'm doing something wrong with Tom's code, I'll give it more thought tomorrow.
But thanks for the input, that's what I wanted to confirm that the cells are still spiting voltages on CAN when they receive the 'next' 200 frame after queueing balance commands.


----------



## BogdanT (Sep 15, 2018)

@swoozle Back to you with a question... In your original excel file, I think there is a typo on frames 461 and 471
- the bytes to activate the cells seems to be reversed (when compared to the other 8-cell groups). Marked with yellow - reversed; green -assumed correct.

Can you confirm the typo or is that group somehow 'special'?


----------



## swoozle (Nov 13, 2011)

Woops! Yes, yellow is a typo. 
The sequencing across the pack is uniform. 
Thanks, good catch.


----------



## BogdanT (Sep 15, 2018)

We're you able to further check the part on queueing "all" cells for balancing?

I'm working on fixing the SIMP balancing, which appears broken and would also like to implement that check/workaround.

Question would be:
Is that restriction applying on whole BICM or "module within BICM"? Eg. For BICM4 can you queue 17(of 18) cells or just 11(of 12) from one module + 5(of 6) from the other module?


----------



## swoozle (Nov 13, 2011)

Nope, I didn't do any more with checking how many cells can be balanced at a time. The most I checked was every other cell on one battery module. I'm guessing, but I assume you can do half of the cells (every other one) within a whole BICM at a time. I don't know why it would be limited by battery module.

I did my work by physically connecting to the bleed resistors and seeing the current pass through them. A less intrusive but more subtle way would be to watch the voltages on the cells you are targeting. Hit them with a bleed every 200 msec and you can see the voltage depress slightly after a few(?) minutes. Stop bleeding and they bounce back up a little.


----------



## BogdanT (Sep 15, 2018)

It seems like it works. So what happened on my side: while trying to fix the SIMP bms code, I ended up with 3 cells on BICM4 at 3.90V and all the others in the full pack at 3.94

After clearing all the bugs, I left it to balance, effectively triggering all the other cells (except the 3 on BICM4).
Next morning all the cells were within 10mV.

The code loop was updated to trigger 4 balance requests x 200ms then 1 sampling request (blank frames 300/310) - not sure if this is needed to get correct voltage but seemed reasonable to do.

It's not a very accurate test but it deed seem to work  Discharge time was around 3hours / 10mV.


----------



## Rod-N (Nov 13, 2021)

swoozle said:


> Here's how to command your OEM Chevy Volt BMS BICMs (slaves) to bleed charge off of specific cells in order to keep them in balance.
> 
> This does not involve the BECM (master). I wasn't able to figure out the command(s) to send the BECM to get it to initiate this work. This is a more manual method that involves sending the BICMs commands indicating which specific cells to bleed. You still have to figure out which cells are out of balance and do the heavy lifting of dropping them to the right level. This would be done by continually sending these commands to the BICMs on a CAN bus with just the BICMs, no BECM.
> 
> ...


Hi great work on this swoozle!
Question for you ( or anyone!) I have a gen 2 and have connected the can bus and all I am receiving is 0x200 00 00 00 00 00 00 00 and on the GMLAN high speed its all 0x2C7 00 00 00 00 00 00 , this is not in a car (on the bench) does anyone know if a ACQ is maybe what its looking for? Or a log of a GEN 2 (2017) would probably help thank you!


----------



## mons2b (Nov 17, 2015)

A solution we could buy and just plug into the slaves would be nice. This code stuff is over my head.


----------



## piwhy (Feb 8, 2011)

Hi all,

I'm currently investigating on IMD circuit which is integrated in the BECM board on chevy volt gen 1 : Chevy volt BECM IMD (insulation monitoring device) and...
Sadly, the goal is not to use this part for a third usage in a crazy ev conversion  but maybe some know there are more and more stock chevy volt owner concerned by (wrong) insulation issue. I'm concerned by this problem also on mine and after having checked and measure insulation of every HV component and harness, I try to figure out if the insulation monitoring device itself can be incriminate as bad due to an aging phenomena or defective component in the insulation measurement circuit.

To facilitate this deep investigation I would like to know if someone know the CAN command to activate the insulation test on the BECM and then get the value back ? I know this command is possible through the official GM GDS software and then it should be requested by the HPCM2 module to the BECM ; but I would ideally be able to test it separately from the car.

Thanks.


----------

