Best way to go about this?

Hi, for my project I’ve got an LTC6803 monitoring some 6S LiPo packs, and I was wanting to add a few cutoff points to it. The first one is an undervoltage cutoff, which is simple to do, no worries there.

However, the other I was hoping to implement was a cell imbalance warning. However, in order to do this, I’d somehow need to compare all 6 values to each other, and if any one is say, 0.2V different from any of the others, it’d give a warning. I can’t really figure out what the best way to go about this would be? I can work with the values in millivolts so I don’t have to worry about lots of floating point calculations, but it just seems like i’d need for loops in for loops in for loops etc etc …

Any ideas?

If you put the six values in an array and sorted it then you could compare adjacent values very easily. Even a simple bubble sort would be very fast for six values.

UKHeliBob:
If you put the six values in an array and sorted it then you could compare adjacent values very easily. Even a simple bubble sort would be very fast for six values.

And if those six values are in a struct you can also contain the cell number in there too, so you know which cell it is that’s imbalanced.

But then, do you even need to sort? Just scanning the array 6 times would take about the same amount of time as a bubble sort.

Here is an interesting discussion about sorting small arrays - algorithm - Fastest sort of fixed length 6 int array - Stack Overflow -

I like this solution, although it has O(n^2) comparisons it places the values directly in the right spot => O(n) assignments.

inline void sort6(int *d)
{
  int e[6];
  memcpy(e, d, 6*sizeof(int));
  int o0 = (d[0]>d[1]) + (d[0]>d[2]) + (d[0]>d[3]) + (d[0]>d[4]) + (d[0]>d[5]);
  int o1 = (d[1]>=d[0]) + (d[1]>d[2]) + (d[1]>d[3]) + (d[1]>d[4]) + (d[1]>d[5]);
  int o2 = (d[2]>=d[0]) + (d[2]>=d[1]) + (d[2]>d[3]) + (d[2]>d[4]) + (d[2]>d[5]);
  int o3 = (d[3]>=d[0]) + (d[3]>=d[1]) + (d[3]>=d[2]) + (d[3]>d[4]) + (d[3]>d[5]);
  int o4 = (d[4]>=d[0]) + (d[4]>=d[1]) + (d[4]>=d[2]) + (d[4]>=d[3]) + (d[4]>d[5]);
  int o5 = 15 - (o0 + o1 + o2 + o3 + o4);
  d[o0] = e[0]; d[o1] = e[1]; d[o2] = e[2]; d[o3] = e[3]; d[o4] = e[4]; d[o5] = e[5];
}

But then, do you even need to sort? Just scanning the array 6 times would take about the same amount of time as a bubble sort.

Let the discussion about sort methods commence :slight_smile:

In practice, with only six elements to be compared any method, sorted or not, is going to be lightning fast anyway and the process would stop as soon as the first exception was found which would make it faster still.

Quicksort?

But really, take the first value and compare to the other five.

Then if that passes take the second one and compare to the other four.

And so on. Wouldn't take long. The CPU will be bored anyway, it'll appreciate the extra work.

Things:
Hi, for my project I’ve got an LTC6803 monitoring some 6S LiPo packs, and I was wanting to add a few cutoff points to it. The first one is an undervoltage cutoff, which is simple to do, no worries there.

However, the other I was hoping to implement was a cell imbalance warning. However, in order to do this, I’d somehow need to compare all 6 values to each other, and if any one is say, 0.2V different from any of the others, it’d give a warning. I can’t really figure out what the best way to go about this would be? I can work with the values in millivolts so I don’t have to worry about lots of floating point calculations, but it just seems like i’d need for loops in for loops in for loops etc etc …

Any ideas?

Calculate the mean (or better median) value first, then run through looking at the differences between each value and the mean (or median).

Something a bit like:

#define  MAX_DIFF  0.2
float mV [N] ;
float mean = 0.0 ;

void check ()
{
  mean = 0.0 ;
  for (int i = 0 ; i < N ; i++)
    mean += mV [i] ;
  mean /= N ;
  for (int i = 0 ; i < N ; i++)
    if (abs (mV [i] - mean >= MAX_DIFF)
    {
      .. warn ..
    }
}