Archive for December 2nd, 2013

Arduino Analog Input Averaging

The Hall effect LED current controller measures a bunch of analog signals that have a lot of PWM ripple, so I average ten readings:

//-- Read AI channel
//      averages several readings to improve noise performance
//		returns value in volts assuming known VCC ref voltage

#define NUM_T_SAMPLES    10

float ReadAI(byte PinNum) {

  word RawAverage;

  digitalWrite(PIN_SYNC,HIGH);					// scope sync

  RawAverage = (word)analogRead(PinNum);		// prime the averaging pump

  for (int i=2; i <= NUM_T_SAMPLES; i++) {
    RawAverage += (word)analogRead(PinNum);
  }

  digitalWrite(PIN_SYNC,LOW);

  RawAverage /= NUM_T_SAMPLES;

  return Vcc * (float)RawAverage / 1024.0;

}

The PIN_SYNC output produces the upper trace, with the LED current in the lower trace at 50 mA/div:

Arduino Analog 10x sample avg - ILED 50 mA-div

Arduino Analog 10x sample avg – ILED 50 mA-div

In round numbers, ten samples require 1.1 ms and cover about 35 PWM pulses (using 32 kHz PWM, as you really should if you need an actual analog voltage).

Because the samples occur asynchronously with respect to the PWM pulses, the computed average comes out surprisingly close to the actual average. Fewer samples would probably be just as good, but I’m in no hurry.

2 Comments