Averaging analog signal

I am trying to take the average of the LVDT sensor, and publish it to the console, but it always reads zero, when i just make analogue read, it gives me the right voltage 2.5

@msavooo, showing your code would greatly help us help you! :grin:

1 Like

const int numReadings = 1;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
float average = 0;                // the average

int inputPin = A1;

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(inputPin);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  Spark.publish("voltage",String(average) + "v");
  
  //Serial.println(average);
  delay(5000);        // delay in between reads for stability
}

@msavooo, I’m not sure what kind of average you are trying to calculate! What you are doing is every 5 seconds, you calculate a total based on the previous reading and a new reading then divide by the array size (numReadings) which is set to 1. If the reading-to-reading variation is small, the average will be near or at zero. Also, if you increase numReadings, the results will not be an average as you are not traversing the entire array to calculate your average.

Are you trying to calculate a rolling average or a sample average? Are you intending to capture a number of samples and then calcualate the average?

1 Like

not your issue, but for global arrays, C++ automatically initializes the entire array to zero.

That's not the way I read his code. Since the array only has one member, total = readings[0], and readIndex will always be 0 at the top of loop. Therefore, total - readings[readIndex] will always be zero, and average should be equal to the value of the last call to analogRead, not 0 (unless his analogRead is returning 0). When I run his code, I just see that value each time through loop.

2 Likes

plus, an int divide by an int will return an int... which will be then cast to a float (i.e. average).

it's possible that integer division plays a role in the mysterious readings.

OP should try to explicitly cast the numerator to a float before dividing, i.e.

average = (float)total / numReadings;
3 Likes

i am using LVDT sensor to measure the displacement with an accuracy of 50 micron, when I fix the sensor and take a sample of the reading. the values is not stable, so i want to sample 30 reading and then take the average to make the reading more accurate. the code is working for Arduino

@msavooo, can you provide links to both the LVDT sensor you are using and the Arduino code you used?

Something like this is what you’re after, I think.

unsigned int numReadings = 30;
unsigned int readingCursor = 0;

float readings[numReadings]; // assuming the readings are float, if they're not, use:
//int readings[numReadings];

float latestAverage = 0.0;

void loop() {
    if (readingCursor != numReadings) {
        // take the reading, increment the cursor
        readings[readingCursor % numReadings] = analogRead(inputPin);
        readingCursor++;
    
        // add a delay so you don't take all measurements at once.
        delay(100);
    } else { // time to make the donuts
        float sum = 0.0; // will hold the sum of all sensor readings.

        // add up all the measurements...
        for (int i = 0; i < numReadings; i++) {
            sum += readings[i];
        }
    
        // and divide by the number of measurements to get the average
        latestAverage = sum / numReadings;

        Serial.println(latestAverage);
        // publish here, possibly.
        //Particle.publish("avg", latestAverage);

        // reset
        readingCursor = 0;
    }
}