# How to get average of 16bit ADC readings?

I have an Adafruit ADS1115 analog-to-digital converter, configured in single ended mode. I want to average over 3 sensor readings to increase the reading stability.

``````  //initialize variables
int16_t rawData, ambient;
int i=0;

// start loop
while(i<3) {
// divide sensor reading by three
// (doing so after summation will lead to an overflow)
rawData=rawData/3;
Serial.println(rawData); // print data to serial for debugging (OK)
ambient+=rawData;
i+=1;
delay(100);
Serial.println("I LIVVVVEEE"); // print text to serial for debugging (OK)
}

// Print signal (NOT OK)
Serial.print("Ambient is ");
Serial.println(ambient);
``````

The "rawData" is printed correctly on the serial monitor. However, the value for "ambient" can be crazy: the resulting output is over an order of magnitude higher. Somehow, the summation doesn't seem to be performed correctly.

• this is not avarege of 3 readings. it is a sum a of 1/3 of readings
– Juraj
Commented Apr 20, 2019 at 10:20

You forgot to initialize `ambient` to zero, so it got whatever happened to be in that place of memory when it got instantiated. Some unpredictable, seemingly random data.

• are you saying that `int16_t ambient; Serial.println(ambient, DEC);` could show something besides `0`? Commented Apr 22, 2019 at 17:29
• @dandavis: Yes, absolutely. The value of `ambient` here is indeterminate. In some circumstances, using such a value can even lead to undefined behavior. Commented Apr 22, 2019 at 18:04

If you are trying to average out three sensor ADC reading first you need to store and add them all then divide it by 3.

`````` int16_t rawData =0;
int32_t avg=0,ambient=0;
int i=0;

while(i<3) {
// divide sensor reading by three
// (doing so after summation will lead to an overflow)
Serial.println(rawData); // print data to serial for debugging (OK)
avg += rawData;
i++;
delay(100);
Serial.println("I LIVVVVEEE"); // print text to serial for debugging (OK)
}
abmient = avg /3;
avg = 0;
// Print signal (NOT OK)
Serial.print("Ambient is ");
Serial.println(ambient);
``````
• This approach is great for small numbers. However, the ADC is 16 bit. By adding three 16bit values, this may (can) lead to buffer overflow for "ambient". Commented Apr 20, 2019 at 9:38
• @plasma, sum of 3 16 bit numbers will not run out of 32 bit
– Juraj
Commented Apr 20, 2019 at 10:44
• @Juraj there is nothing like that. I just made changes in his program. Commented Apr 20, 2019 at 10:51
• appreciated.... Commented Apr 20, 2019 at 11:44
• you will actually get more stable readings if you take the median of the 3 readings instead of the mean. consider reading `12,13,5` when the true reading is 13. with avg you get `10` (err=3), but with median you get `12` (err=1). I used this method for a DMM project and it made a HUGE difference compared to my naive oversample+avg method... You can also adjust how many internal AD1115 samples are collected, and at the expense of reading time, get a more stable set of values from the get go. Commented Apr 22, 2019 at 17:25