1

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) {
      rawData = ads.readADC_SingleEnded(0); //read from ADC
      // 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.

1
  • 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

2 Answers 2

2

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.

2
  • are you saying that int16_t ambient; Serial.println(ambient, DEC); could show something besides 0?
    – dandavis
    Commented Apr 22, 2019 at 17:29
  • 1
    @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
2

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) {
      rawData = ads.readADC_SingleEnded(0); //read from ADC
      // 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);
7
  • 1
    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".
    – plasma
    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.
    – Vaibhav
    Commented Apr 20, 2019 at 10:51
  • appreciated....
    – Vaibhav
    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.
    – dandavis
    Commented Apr 22, 2019 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.