analogReadAveraging Mystery?

Status
Not open for further replies.

dereckbc

Well-known member
At least a mystery to me anyway has me scratching my head. Below are two test sketches, the first one does not work as expected, and the second one works great. Note the only difference between the two sketches is the MAP command for Thr_Us. Very simple circuit using a Pot to input voltage to a analog pin, read it and print it.

The first sketch is erratic. Mostly prints 800 uS through most of the range except ring in the middle of the span then spits out garbage numbers of 1400 to 1900. Second sketch works perfectly and I get a nice linear readout from 800 to 2200. What in the Devil is going on.

Code:
  const int inPin_A3_Thr = A3; // Ana Input - Rudder potentiometer
  int AI_Raw_THR = 0; // Ana In raw var - 0->2047
  int Thr_Us = 1500; // Ana In var - 0->2047 compensated
     
void setup() {
  analogReadResolution(13);// Sets ADC range to 11 bits (0 to 2043). Teensy 3.2 ranges from  10 to 13 bits
  analogReadAveraging(4);//Average 4, 8, 16 and 32 readings, smooths stick input and jitter.

  Serial.begin(9600);  //Test only disable with // when not in use
}

void loop() {

  AI_Raw_THR = analogRead(inPin_A3_Thr);
  [COLOR="#FF0000"]//Thr_Us = map(AI_Raw_THR, 0, 8191, 800, 2200); // Throttle
  Thr_Us = map(analogRead(AI_Raw_THR), 0, 8191, 800, 2200); // Throttle [/COLOR]
         
  Serial.print( " Thr_Us=");  //Test only disable with // when not in use
  Serial.print(Thr_Us);  //Test only disable with // when not in use
  delay(10); //Test only disable with // when not in use
}

Code:
  const int inPin_A3_Thr = A3; // Ana Input - Rudder potentiometer
  int AI_Raw_THR = 0; // Ana In raw var - 0->2047
  int Thr_Us = 1500; // Ana In var - 0->2047 compensated
     
void setup() {
  analogReadResolution(13);// Sets ADC range to 11 bits (0 to 2043). Teensy 3.2 ranges from  10 to 13 bits
  analogReadAveraging(4);//Average 4, 8, 16 and 32 readings, smooths stick input and jitter.

  Serial.begin(9600);  //Test only disable with // when not in use
}

void loop() {

  AI_Raw_THR = analogRead(inPin_A3_Thr);
  [COLOR="#FF0000"]Thr_Us = map(AI_Raw_THR, 0, 8191, 800, 2200); // Throttle
  //Thr_Us = map(analogRead(AI_Raw_THR), 0, 8191, 800, 2200); // Throttle [/COLOR]
         
  Serial.print( " Thr_Us=");  //Test only disable with // when not in use
  Serial.print(Thr_Us);  //Test only disable with // when not in use
  delay(10); //Test only disable with // when not in use
}
 
Last edited:
The first one you do an analog read and store result. You then pass this returned value to analog read as the PIN number, so probably bogus, and the result is passed to map
 
Not sure I follow you Kurt. I declared two variables called AI_Raw_THR and Thr_Us . Neither is a pin. AnalogRead is used twice, first it reads the analog input pin and saves it as AI_Raw_THR , then another AnalogRead of AI_Raw_THR and stores that number as Thr_Us. Basically all I did is read analog pin , saved it, read it again and stored in a different location.

Basically all logic tells me is AI_Raw_THR should roughly equal Thr_Us . One of my trouble shooting efforts was to print both .AI_Raw_THR and Thr_Us. Raw always tracked the Analog input pin as expected. So I know at least the first analog read is working as expected, but if you read it again is garbage. Reading a value should not change that value by moving it from one memory location to another. At least that is how I think it should work.

Something is going on with the analogReadAverge command I do not understand.
 
Last edited:
Yet another new thread?

It seems Kurt spotted this - passing the VARIABLE as the PIN # in the FIRST snippet::
Code:
void loop() {

  [U]AI_Raw_THR[/U] = analogRead([B]inPin_A3_Thr[/B]);
  //Thr_Us = map(AI_Raw_THR, 0, 8191, 800, 2200); // Throttle
 //>> BAD >> Thr_Us = map(analogRead([COLOR="#FF0000"][U]AI_Raw_THR[/U][/COLOR]), 0, 8191, 800, 2200); // Throttle 
  Thr_Us = map(analogRead([COLOR="#FF0000"][B]inPin_A3_Thr[/B][/COLOR]), 0, 8191, 800, 2200); // Throttle
 
It seems Kurt spotted this - passing the VARIABLE as the PIN # in the FIRST snippet::
Code:
void loop() {

  [U]AI_Raw_THR[/U] = analogRead([B]inPin_A3_Thr[/B]);
  //Thr_Us = map(AI_Raw_THR, 0, 8191, 800, 2200); // Throttle
 //>> BAD >> Thr_Us = map(analogRead([COLOR="#FF0000"][U]AI_Raw_THR[/U][/COLOR]), 0, 8191, 800, 2200); // Throttle 
  Thr_Us = map(analogRead([COLOR="#FF0000"][B]inPin_A3_Thr[/B][/COLOR]), 0, 8191, 800, 2200); // Throttle

Thanks but that does not compute, I am missing something. I only read from the input pin once, save it as AI_Raw_THR, then read AI_Raw_THR, and save it as Thr_Us. Both should be roughly equal after Averaging. At least that is what I think. All I am doing is moving a varible from the input pin, to a memoryy location, move it to another memory location, then print it. I am just trying to smooth the number out and reduce SNR of the ADC
 
Thanks but that does not compute, I am missing something. I only read from the input pin once, save it as AI_Raw_THR, then read AI_Raw_THR, and save it as Thr_Us. Both should be roughly equal after Averaging. At least that is what I think. All I am doing is moving a varible from the input pin, to a memoryy location, move it to another memory location, then print it. I am just trying to smooth the number out and reduce SNR of the ADC

Why does it not compute?
for the sake of testing, replace 'inPin_A3_Thr' by 'A3' in both analogReads, as analogRead requires a pin number, here A3.
 
Why does it not compute?
for the sake of testing, replace 'inPin_A3_Thr' by 'A3' in both analogReads, as analogRead requires a pin number, here A3.

Doh! I get it now, analogRead can only read an analog input pin, not a variable. Correct?

I was just trying to run it through analogRead again to smooth it out further and playing around.

Assuming I got it now couldn't I just rewrite the whole code to a much shorter

Code:
 const int inPin_A3_Thr = A3; // Ana Input - Rudder potentiometer
  int Thr_Us = 1500; // Ana var - 800 to 2200 Smoothed

void setup() {
  analogReadResolution(13);// Sets ADC range to 11 bits (0 to 8191). Teensy 3.2 ranges from  10 to 13 bits
  analogReadAveraging(4);//Average 4, 8, 16 and 32 readings, smooths stick input and jitter.

void loop() {
Thr_Us = map(analogRead(inPin_A3_Thr), 0, 8191, 800, 2200); // Throttle

I assume the analogRead in the map command is averaged? Or do I have to read and store it first like I had it?
 
Last edited:
I think you have it now - I put in red the error the KurtE noticed - indeed to read a pin - you need to specify a pin.

Was it on one of your (too) many threads where I did a time test sketch?

IIRC the results showed with::
AVG==4 the analog return returned in < 10 us.
AVG==32 the analog return returned in > 50 us.

I didn't feel like wading through the code - but that empirical test told me that when higher specified AVG count it takes longer as it makes all the samples during that call then returns the average when it returns.

What you pass to map as the code is written is that return, value and the map result is based on that provided average value.
 
Just decided to test my new 'Sublime Text' install to find "void analogReadAveraging(" after not seeing what I wanted in "analogRead()".

Firstly 'Sublime Text' did an awesome job taking me right to the code - doing a GREP through the installed Teeny files!

Secondly - if I'm reading this right without reading further in the ARM manual - it looks like the call below [from :: teensy3/analog.c] sets up the hardware to automatically and internally perform the read and averaging:
Code:
void analogReadAveraging(unsigned int num)
{

	if (calibrating) wait_for_cal();
	if (num <= 1) {
		num = 0;
		ADC0_SC3 = 0;
	} else if (num <= 4) {
		num = 4;
		ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
	} else if (num <= 8) {
		num = 8;
		ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
	} else if (num <= 16) {
		num = 16;
		ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
	} else {
		num = 32;
		ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
	}
	analog_num_average = num;
}
 
I think you have it now - I put in red the error the KurtE noticed - indeed to read a pin - you need to specify a pin.

Thank you, the way WMXZ phrased it was clear to me.

IIRC the results showed with:: AVG==4 the analog return returned in < 10 us.
AVG==32 the analog return returned in > 50 us.

Great info and surprises me how long it takes

I didn't feel like wading through the code - but that empirical test told me that when higher specified AVG count it takes longer as it makes all the samples during that call then returns the average when it returns.

What you pass to map as the code is written is that return, value and the map result is based on that provided average value.

Thanks again and I get it now.

Lastly

Was it on one of your (too) many threads where I did a time test sketch?

Thank you for your patience and time. Its only 1 and 0's.
 
OK guru's I need some more guidance or a push in the right direction. One quirk I am running into centering errors. Joystick pots do not return exactly to center, close, but no cigar. I know what the fix is, DEAD BAND ZONE, but have no clue how to implement the code. My best guess is maybe if/else statements. So when the stick is say near center like +/- 20 counts, outputs say 512 on a 0 - 1023 scale. So has anyone done this and cares to share?
 
Last edited:
abs() gives you the absolute value of a number. If the number is negative, it turns it positive.

This is one of many math functions provided by the standard C/C++ environment.
 
As Paul mentioned it is one of the standard math functions.

Again if you open up the Arduino Reference page (Arduino IDE Help->Reference menu item), it will be listed on the top level page, in the same section as the map routine.
 
Status
Not open for further replies.
Back
Top