analogReadAveraging not behaving as I would expect

Status
Not open for further replies.

Break Stuff

Active member
I expected analogReadAveraging(200);
to smooth out the jittery results of analogRead(0);

Yet it has no discernible effect that I can see.

The blue line is very much having a caffeine overdose:
Code:
void setup() {
 analogReadAveraging(200);
}

void loop() {
  Serial.print(analogRead(0));

  Serial.print(" "); //for serial plotter visual scaling
  Serial.print(1200); //for serial plotter visual scaling
  Serial.print(" "); //for serial plotter visual scaling
  Serial.println(0); //for serial plotter visual scaling
}

While the red line, using my clunky manual averaging is just chillin' with some ice tea on the porch:
Code:
void setup() {

}

void loop() {
  const int averaging = 200;  // how many to average
  static int x[averaging];   // array of values to average
  int xAVG = 0;              // store average result
  
  for (int i = averaging - 1; i > 0; i--) { x[i] = x[i-1];}  //move each value to the next spot in array
  x[0] = analogRead(0);                                     //fill first value of array with most recent 
  for (int i = 0; i < averaging; i++) { xAVG += x[i]; }    // add all values of array together
  xAVG = xAVG/averaging;                                   // divide by number of values to get average      
  
  Serial.print(1200); //for serial plotter visual scaling  
  Serial.print(" ");//for serial plotter visual scaling
  Serial.print(xAVG);                                       // print average
  Serial.print(" ");//for serial plotter visual scaling
  Serial.println(0);//for serial plotter visual scaling
}

ARAexample.jpg
 
I expected analogReadAveraging(200);

The maximum is 32. Anything over 32, like 200, configures for only 32.

This is a hardware feature. The software doesn't add any extra averaging beyond what the hardware does, and the hardware limit is 32.

Look at the ResponsiveAnalogRead library for a more advanced software-based approach.
 
Max use is analogReadAveraging( 32 ).

That will be back to back reads done in very short order. For that short period the signal presented will be resampled and averaged. It will return the measured average of the signal present at that time - with no regard to prior samples. It seems that averaging time may be like 50 MICROSECONDS if I recall a post I made some months back?

The red line averaging as presented is a long term SMOOTHING of a signal that has quite some change over time. It looks like the lower scale increments are 100 MILLIseconds? If the left scale is analog read values - is that about a range of 100 peak to peak?

Those are two separate ways to view the incoming signal - desired use and what is being measured determines how it is to be done.
 
Thank you, for the quick reply! looking at ResponsiveAnalogRead library right now.

using analogReadAveraging(32); for the blue line
and const int averaging = 32; for the red line
still shows a significant visual difference:

ARAexample2.jpg

Shouldn't they be fairly similar?
I'd expect doing the same averaging in software to produce a similar result as letting the hardware do it.
 
defragster there is a lot of information in your post

could you clarify this:
"It will return the measured average of the signal present at that time - with no regard to prior samples."

I'm smoothing out the line by averaging the last 32 samples (200 in the first post), I'm not clear on why analogReadAveraging( 32 ) isn't smoothing it.
 
It's measuring the light in the room via a voltage divider and ir sensor so the range of values isn't the issue as a stray gust of wind can move the blinds!
By similar I was referring to the jitter or smoothness of the lines.
 
A single analog read takes a few micros. Asking for hardware average of 32 samples takes like 50 or 70 micros.

Requesting an average of 32 readings starts 'with no regard to prior samples'. The average returned is only affected by the data at that moment - where the moment is maybe 50 microseconds long.

The returned average is only for that 'short' time before the data is collected and returned.
 
To detect the blinds moving or a door opening/closing - you would want an accurate reading over a short duration < 100 microseconds. And having it average what happened a second before would hide that event.

If short term events don't matter then the 'red line' smoothing is what is desired. Then you can tell when the sun rises or sets perhaps
 
That smoothing is happening FAST.
I have no problem detecting my hand waving over the sensor.


analogReadAveraging(0);
  • 2 microseconds with no Serial prints
  • 26 microseconds with serial prints


analogReadAveraging(32);
  • 2 microseconds with no Serial prints
  • 61 microseconds with serial prints


manual averaging of 32
  • 12 with no serial prints
  • 31 with Serial prints


manual averaging of 200
  • 28 with no serial prints
  • 61 with Serial prints


manual averaging of 1000 (just for fun)
  • 106 with no serial prints
  • 206 with Serial prints



hardware averaging
Code:
void setup() {
 analogReadAveraging(32);//
  Serial.println("Start"); //for serial plotter visual scaling
  delay(1000);
}

void loop() {
  static unsigned long startTime = micros();  
  static int i=0;
/*
  Serial.print(analogRead(0));

  Serial.print(" "); //for serial plotter visual scaling
  Serial.print(1200); //for serial plotter visual scaling
  Serial.print(" "); //for serial plotter visual scaling
  Serial.println(i); //for serial plotter visual scaling
*/
  i++;
  if (i >= 10000) {
  Serial.print("ar takes micros = "); 
  Serial.println((micros() - startTime)/10000); 
  i = 0;
  delay(1000);
  startTime = micros();  
  }
}

Softwareware averaging
Code:
void setup() {

}

void loop() {
  static unsigned long startTime = micros();  
  static int i=0;
  const int averaging = 32;  // how many to average
  static int x[averaging];   // array of values to average
  int xAVG = 0;              // store average result
  
  for (int i = averaging - 1; i > 0; i--) { x[i] = x[i-1];}  //move eace value to the next spot in array
  x[0] = analogRead(0);                                     //fill first value of array with most recent 
  for (int i = 0; i < averaging; i++) { xAVG += x[i]; }    // add all values of array together
  xAVG = xAVG/averaging;                                   // divide by number of values to get average      
/*
  Serial.print(1200); //for serial plotter visual scaling  
  Serial.print(" ");//for serial plotter visual scaling
  Serial.print(xAVG);                                       // print average
  Serial.print(" ");//for serial plotter visual scaling
  Serial.println(0);//for serial plotter visual scaling
*/
    i++;
  if (i >= 10000) {
  Serial.print("ar takes micros = "); 
  Serial.println((micros() - startTime)/10000); 
  i = 0;
  delay(1000);
  startTime = micros();  
  }
}
 
Status
Not open for further replies.
Back
Top