EV monitor / Opto-coupler help

I need some help using an opto-coupler to sense battery voltage of a 96v battery pack on my EV truck.

I have a feeling that this is a math problem, or that the LDR/LED combo I’m using as an opto-coupler is too sensitive/unreliable.

I have an LED hooked up through a 18k resistor to the 96v pack, I tested it and it visibly dimmed when I engaged the main motor on the EV, pulling the voltage down by 2-3 volts, while sucking about 20amps from the pack. So I know the LED is representing voltage sag, or state of charge.

The LDR is a 5k and is hooked up to the arduino in a voltage divider config with a 2.2k resistor (I did this so it hopefully produces around 4.5v for roughly 3-400ohm reading on the LDR and .5v for above 5k, when the LED is off)

The problem I have is that the LDR resistance variance is very small, between 2.935kohm and 2.920kohm, corresponding to the LED so I might be asking too much of the ADC ? I’m not sure. The reading I get stays fairly consistent but often bounces 10’s of volts at a time, something is generating noise.

Two methods of attempting to smooth readings are below in the code, I’ve used the method for current also on the voltage reading.

I need to figure out a way to smooth the readings and also shift the noise down to fractions of a volt in the reading and not have the reading shoot up or down. Math is not a strong point :wink: hopefully someone can point out an obvious problem, or ask something I haven’t thought about. :pray:

//sample 96 volt traction pack

  float packVolts1;  
  float packVolts;
   
  for (int i1 = 0; i1 < smoothread; i1++)
  {
   packVolts1 = map(analogRead(packVpin), 1023, 0, 3045, 0 );
    delay(5);

 // subtract the last reading:
  smTotal= smTotal - smoothreadArr[smIndex];        
  // read from the sensor:  
  smoothreadArr[smIndex] = packVolts1;
  // add the reading to the total:
  smTotal= smTotal + smoothreadArr[smIndex];      
  // advance to the next position in the array:  
  smIndex = smIndex + 1;                    

  // if we're at the end of the array...
  if (smIndex >= smoothread)              
    // ...wrap around to the beginning:
    smIndex = 0;                          

  // calculate the average:
  smAvg = smTotal / smoothread;         
  }//end smooth loop
  packVolts = smAvg; //value used for display


  //sample current
  int packAmpSum = 0.0;
  float packAmps;
  for (int i2 = 0; i2 < 250; i2++){
   packAmps = map(analogRead(packApin), 1023, 0, 0, 2614 );
   packAmpSum = packAmpSum + packAmps;              
    delay(5);                                             
  }

 packAmps = packAmpSum /88; 
  
  if (packAmps < 100)
  {  lcd.clear();
  }

You should look for an integrated analog optocoupler. That will give a much larger

analog signal to the microprocessor, and less noise.

As for removing noise from the readings the simple standard ways are

  • average of a fixed number of samples

  • exponentially weighted moving average (EWMA) yout = (1-a)yprev + axin

But removing noise from the analog input by having an optocoupler with more signal swing

and less noise is the preffered way.

As said above, you’ve got the wrong circuitry to do the task. First off you need to define what range of voltages your wish to monitor. If the nominal voltage is 96V, how far above and below this do you wish to read ? What kind of accurac and resolution do you need for the reading ? My thinking is that you should subtract off some nominal voltage from the “96V” to get a voltage that’s in the range needed. This can be fed into the A/D. The digital output (and input too) can be opto-isolated if needed.

How many batteries is the pack made of ? Is the Arduino used for anything other than monitoring the voltage ? If so that may dictate a slight change.

I was trying to be too cheap. (hence not just buying a manufactured meter :wink:

Looking at using something similar to this http://www.farnell.com/datasheets/1698329.pdf as an integrated solution that will give more predictable results (thanks Mlu)

Now I need to find a ~140v regulator that will output ~30v any suggestions ?

I wonder if it will be cheaper than buying a hall-effect voltage sensor.

Just a suggestion but something akin to this might be a better choice.

http://www.linear.com/product/LTC4151

There may be higher voltage parts, I haven’t looked. Also monitoring 80% of the stack and extrapolating the true voltage isn’t that bad of an idea.