Control Software

Perhaps there will eventually even be code snippets posted here for download, or even a complete program for the Balancer's Stamp!

In March 2002, I asked Lee to describe the key aspects of how he runs his own unit, wondering particularly about relay life, and how often/fast to scan the battery voltages:

The relays are rated at 100,000 cycles at full load (about one day if you cycle it once per second). If they switch a "dry circuit", mechanical life is 1,000,000 cycles.

So first of all, I have the relays switch at zero current.

1. Turn off the DC/DC.
- Wait a second or until the voltage drops (indicating that it did turn off).
2. Turn off a battery relay.
- Wait a second or until the voltage drops (indicating that it did open, and allowing time for C13 to charge).
3. Turn on the next relay.
- Wait until the voltage increases, indicating that it did close.
4. Turn on the DC/DC converter.
- Wait for the voltage rise (indicating that the DC/DC did turn on).

Second, the relays cycle quite slowly. The Balancer is not intended to tell you the short-term total pack voltage by adding up the individual voltages (that is a job for an E-meter). A complete cycle in my Balancer is about 5 minutes while driving, and an hour while parked. The exact rate is a consequence of the algorithm. Basically, it checks all voltages, and then charges the lowest one for a time proportional to how much lower than average it is, and inversely proportional to average pack voltage. Like this:

    let Tbase = 20                (timebase is roughly 20 minutes per battery)

    for i = 1 to N
        select battery i

        let Vi     = voltage of battery i
        let Vave   = (Vi+Vave*(N-1))/N               (compute running average)
        let Charge = Tbase*(Vave-Vi)*(Vave-10)

        if Charge < 0 then Charge = 0       (don't charge batts above average)
        if Charge > 60 then Charge = 60      (don't charge 1 battery too long)

        Charge battery i for Charge minutes
    next i

You then run this loop whenever you want balancing to occur (basically, while driving, while pack average is above about 12.5v, or while charging power is available).

(Lee later clarified that the magic value '10' that appears in the psuedo-code example above is represents the 10V per 12V module minimum voltage that he would ever want to see while operating the EV. Basically, this equation suggests that the closer the average module voltage gets to 10V, the shorter the charge time will be, which forces the Balancer to scan more rapidly at low SOC in case the weak module jumps around.)

When asked about how he came up with the value of Tbase=20 minutes, Lee explained:

I arrived at the value for Tbase experimentally. I try it, see what it does, and tinker with it until I like what happens. Changing the number of batteries or other system parameters would require retuning the algorithm. That's why I don't want people to run my programs. They won't work for someone else's system without tuning.

I asked Lee how this algorithm handled the fact that while driving it might well sample one module's voltage at a significantly different load current than when the next module is sampled (thinking of the varying voltage drop due to the varying load current). He explains:

Basically, I ignore instantaneous voltages and currents. The balancer only needs to figure out which one is the lowest, and charge it. The above algorithm dithers around a lot while driving. due to the rapidly changing current; however, it still manages to charge the right battery.

I have an E-meter with serial option, and there are extra serial ports on the balancer. I had intended to interface the E-meter, so the balancer knows instantaneous pack voltage and current, which helps a lot to decide which battery to charge. But, I haven't gotten around to implementing it because the balancer is already charging the right battery most of the time while driving, and while parked, voltages aren't changing fast enough for it to be a problem.

Later, Lee clarified that by "ignor[ing] instantaneous voltages and currents", he really means:

I meant that *I* ignored the fact that the voltages and currents are constantly changing, and wrote the algorithm as if they were constant.

Last fall, I had an algorithm that maintained a timer for each battery, and when it did a scan, it incremented/decremented this timer based on comparing each battery to the average. It had the effect of deciding how long to charge each battery based on its average voltage over several samples. I was working towards a scheme that tracks amphour capacity of each battery rather than simply its voltage. But I ran out of memory with the Basic Stamp 2 to fully implement it, and a partial implementation wasn't any better than the simpler method I'm using now.

My current thinking is that a voltage-based balancer is always going to be in error anyway. What we really want is for the balancer to keep track of remaining amphour capacity in each battery. During driving, it should strive to keep the same number of amphours remaining in every battery. Thus, they all go dead at the same time. While charging, the converse is true; aim to make all batteries hit full charge at the same time. The only time you aim for the same voltage is when parked (since you don't know if charging or driving will be coming up next).

[Back] [Site Home]

Revision History:

22 Sep 2002: Corrected indexing in pseudocode (thanks Fred Whitridge!)
05 Aug 2002: Initial revision.