For loop to get average value of analog input

I'm measuring the voltage and current of a battery. I'm getting inconsistent values. That's why I want to take multiple measures over a longer period. I think I should use a for loop but I'm not sure how.

float measureCurrent() {

  // Measure
  float shuntvoltage = ina219.getShuntVoltage_mV();
  float busvoltage = ina219.getBusVoltage_V();
  float current_mA = ina219.getCurrent_mA();
  float loadvoltage = busvoltage + (shuntvoltage / 1000);
  
  Serial.print("Bus Voltage:   "); Serial.print(busvoltage); Serial.println(" V");
  Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
  Serial.print("Load Voltage:  "); Serial.print(loadvoltage); Serial.println(" V");
  Serial.print("Current:       "); Serial.print(current_mA); Serial.println(" mA");
  Serial.println("");
  
 
  return current_mA;
  
}

Thanks for any help

Where is your attempt to calculate an average?

I haven't because I don't know how to start

You could start by adding 5 measurements each with 100ms between them and then divide with 5 to get the average of those readings? If your sketch does other work than these measurements you should use millis() for timing instead of a blocking delay :slight_smile:

Have a look here

Hi David,
Welcome to the forum.

Don’t use a for loop for this kind of thing, it stops anything else happening in your code elsewhere. Use loop to do the looping.

I put this together quickly to illustrate how I would get an average if I were doing what you are doing. Note this is incomplete and untested, but I hope it is enough to illustrate the approach. I hope I’ve not made any silly mistakes :confused:

uint16_t A2Dcumulative;
float result;
bool result_ready = false;

void setup() {
  //As required
}

void loop() {
  voltage_average();
  process_result();
  //Your other code
}

void voltage_average() {
  #define no_of_measurements 10
  static uint8_t count = 0;
  if (count < no_of_measurements) {
    A2Dcumulative += your_measurement_function();    //Function to read the analogue input. Add this to the value already in A2Dcumulative
  }
  else {
    result = (float) A2Dcumulative / count;
    A2Dcumulative = 0;
    count = 0;
    result_ready = true;
  }
}

void process_result() {
  if (result_ready) {
    result_ready = false;
    //Do stuff with the result
  }
}

Note:
I used a 16 bit unsigned int for the cumulative result. If you have a 10 bit A2D then the maximum number of results you can add is as follows:
Assume all results return 0x3f, the maximum possible, which is 10 bits all at 1.
There are 6 unused bits
6 bits gives 2^6, which is 64
You can therefore add 64 measurements to the 16 bit unsigned int A2Dcumulative without risking overflow.

Here is how I do it. Note that in my application I didn't need to account for the sample array filling up. You can read with the following call:

smoothedReading = smoothAnalog(analogRead(pin));

int smoothAnalog(int reading) 
{
  const int numSamples = 10;
  static int samples[numSamples];
  static int sampleIndex = 0;
  static int sampleSum = 0;

  //
  // Analogs are a 10-bit value (0-1023), therefore we could
  // average up to 32 values with a signed int.
  // NOTE: It will take 10 measurements to fill the sample
  // array and return a true smoothed value.  This is not a
  // problem for our application and not worth compensating for.
  //
  
  // Update sum
  sampleSum -= samples[sampleIndex];
  samples[sampleIndex] = reading;
  sampleSum += samples[sampleIndex++];
  sampleIndex = sampleIndex % numSamples;

  // Return average of last numSamples measurements
  return sampleSum/numSamples;
}