1
\$\begingroup\$

I came across a moving average code for my ADS1115 ADC to smooth out the noise.

When I do voltage scaling I getting zeros at my serial monitor.

I'm giving input to my ADC from an LMC6001 op-amp.

Although I'm able to read ADC values, when I do voltage scaling (voltage = (adc2 * 0.1875)/1000; which I have included in my code) I'm reading zeros on my serial monitor.

Please point out the mistake.

#include <Wire.h>
#include <Adafruit_ADS1015.h>
Adafruit_ADS1115 ads(0x48);
const int numReadings = 10;
int readings[numReadings];

//int readings;
int readIndex = 0;
long int total = 0;
float average = 0.0;
float Voltage2 = 0.0;

void setup(void)
{
  Serial.begin(9600);
  ads.setGain(GAIN_TWOTHIRDS);
  ads.begin();
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop(void)
{
  int16_t adc2;
  adc2 = ads.readADC_SingleEnded(2);
//  readings = analogRead(inputPin);
  Voltage2 = (adc2 * 0.1875)/1000;
  total = total - readings[readIndex];
  readings[readIndex] = Voltage2;
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }

  average = total / numReadings;
  Serial.print("AIN2: "); Serial.println(adc2);
  Serial.print("Average: "); Serial.println(average);
  Serial.println(" ");
  delay(1000);
}
```
\$\endgroup\$
6
  • \$\begingroup\$ adc2 looks like an integer and, if you multiply that by 0.1875 and then divide by 1000 you might shift all the relevant fractional information into the toilet never to be seen again. Shouldn't adc2 be defined as a float? I'm no expert on this BTW. \$\endgroup\$
    – Andy aka
    Feb 16 at 15:37
  • 3
    \$\begingroup\$ You are mixing up your floats and ints. "readings" is int, Voltage2 is float. That's going to be a problem. \$\endgroup\$
    – JRE
    Feb 16 at 15:42
  • \$\begingroup\$ When you do math with mixed ints and floats, you need to think really hard about the result of each step and how that result will be interpreted. It is usually safest to convert to floats, do your math, then (if needed) convert to some other numeric type. \$\endgroup\$
    – JRE
    Feb 16 at 15:45
  • \$\begingroup\$ You should divide by 1000.0, not 1000. 1000 is an integer and C compilers will likely interpret your code as integer divide not a float divide. \$\endgroup\$
    – Ben
    Feb 16 at 15:47
  • 1
    \$\begingroup\$ @Ben that would violate the C(++) type promotion rules; 1.875 is float, so the entire expression should be. \$\endgroup\$
    – marcelm
    Feb 16 at 17:12
0
\$\begingroup\$

Even if you cast your ADC value to float like this:

Voltage2 = ((float)adc2 * 0.1875) / 1000.0;

you may end up with very small numbers (truncated do zero), assuming your ADC returns values from -32768 to 32767. Not to mention how slow the floating point operations may be (what is your micro-controller?).

Truncation to zero would happen here for small readings aprox. [-2666, 2666]:

readings[readIndex] = Voltage2;

What about changing your buffer to int32_t and scaling your readings:

int32_t adc2;
adc2 = ads.readADC_SingleEnded(2) * 1000;
\$\endgroup\$
0
\$\begingroup\$

Try this:

#include <Wire.h>
#include <Adafruit_ADS1015.h>
Adafruit_ADS1115 ads(0x48);
const int numReadings = 10;
int readings[numReadings];

//int readings;
int readIndex = 0;
long int total = 0;
float average = 0.0;
//float Voltage2 = 0.0;

void setup(void)
{
  Serial.begin(9600);
  ads.setGain(GAIN_TWOTHIRDS);
  ads.begin();
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop(void)
{
  int16_t adc2;
  adc2 = ads.readADC_SingleEnded(2);
//  readings = analogRead(inputPin);
  //Voltage2 = (adc2 * 0.1875)/1000;
  total -= readings[readIndex];
  readings[readIndex] = adc2;
  total += readings[readIndex];
  readIndex++;
  if (readIndex >= numReadings)
    readIndex = 0; 
  average = (float) total * 0.1875/(1000. * numReadings);
    Serial.print("AIN2: "); Serial.println(adc2);
  Serial.print("Average: "); Serial.println(average);
  Serial.println(" ");
  delay(1000);
}

This defers all floating point operations until you have the total. The main issue was:

readings[readIndex] = Voltage2;

Tries to set a member of an array of ints to a floating point value.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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