Average value of a series of analog numbers over 5 sec.

Hello Arduino community

I have a question about a problem I am working with ...

I need a program to calculate the average value over 5 sec. of my analog (sensor) values (that the Arduino reads). This process has to start when I push a pushbutton.

Anyone who can give me a code? I will be very thankful with that!

Kind regards

Stan

Stan,

Please take a look at the AnalogRead() function and how to BlinkWithoutDelay, it will help you.

You need to think of how fast will you read, this will influence your cumulative variable. i.e., if you read every time, without a time delay you likely will have an overflow.

Would be good to tell us if you know how to program and it isn't a good practice to ask for a code, you should try first and ask what your problems are.

The code below is really basic and will overflow your variable, so you need to set a time between the readings and also the 5s desired times.

int analogPin = A3; // your sensor is connected here
uint32_t val = 0;  // variable to store the value read

void setup() {
  Serial.begin(9600);           //  setup serial so you can print
}

void loop() {
  val += analogRead(analogPin);  // read your sensor and add it to val
  Serial.println(val);          // debug value
}
int analogPin = A3; // your sensor is connected here
uint32_t val = 0;  // variable to store the value read

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last val = 0

// constants won't change:
const long interval = 5000;           // interval at which to reset is ms
cont int betweenReadings = 500;       // interval at which it will read your variable

void setup() {
  Serial.begin(9600);           //  setup serial so you can print
}

void loop() {
  // check to see if it's time set val=0; that is, if the difference
  // between the current time and last time you did it is bigger than
  // the interval at which you want it you happen.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you reset val
    previousMillis = currentMillis;

    val = 0;
  }

  val += analogRead(analogPin);  // read your sensor and add it to val
  Serial.println(val);           // debug value
  delay(betweenReadings);        // block the execution for this time
}

Be aware that using delay is easier but it blocks your program, it will do nothing during this time. So it is recommended to use millis() for it too, like we did in the code above to wait the 5 seconds before reseting val.

staneveraert:
Hello Arduino community

I have a question about a problem I am working with …

I need a program to calculate the average value over 5 sec. of my analog (sensor) values (that the Arduino reads). This process has to start when I push a pushbutton.

Anyone who can give me a code? I will be very thankful with that!

Kind regards

Stan

If you just want help coding an average, I presume you mean the “mean value”.

mean = sum of values / number of values.

So if you record N samples over the 5 seconds:

float average (int N, int * samples)
{
  long sum = 0 ;
  for (int i = 0 ; i < N ; i++)
    sum += samples[i] ;
  return float(sum) / N;
}

Hello both reply’ers

Thanks for the assistance! But I made my program on a other way … You can see the code below:

/*

In dit programma wordt er een kalibratie van een sensor uitgevoerd. Dit door voor een onbepaalde tijd de drukknop in te duwen.
In die tijd zal het programma zoeken naar de maximale en minimale analoge waarde die de sensor binnenleest. De referentiewaarde
die de "kalibratie" aangeeft is dan gelijk aan het gemiddelde van die twee extreme waarden.

 */
 
#include <LiquidCrystal.h>                                              
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;             
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);                              

const int sensorPin = A0;
const int indicatorLedPin = 13;
const int buttonPin = 0;

int sensorMin = 1023;
int sensorMax = 0;
int sensorValue = 0;
int Kalibratiewaarde;

void setup() {
  Serial.begin(9600);
  pinMode(indicatorLedPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop() {
  while (digitalRead(buttonPin) == HIGH) {
    calibrate();
  }
  digitalWrite(indicatorLedPin, LOW);
  Kalibratiewaarde = (sensorMin + sensorMax) / 2;
  Serial.println(Kalibratiewaarde);
  lcd.setCursor(0, 0);                                                  
  lcd.print(Kalibratiewaarde);
  delay(500);                                  
}

void calibrate() {
  sensorMin = 1023;
  sensorMax = 0;
  while (digitalRead(buttonPin) == HIGH) {
    digitalWrite(indicatorLedPin, HIGH);
    sensorValue = analogRead(sensorPin);
    if (sensorValue > sensorMax) {
      sensorMax = sensorValue;
    }
    if (sensorValue < sensorMin) {
      sensorMin = sensorValue;
    }
  }
}

Thanks again for the reply!
Kind regards
Stan

So you use the average of the minimum and maximum? That's about the worst approach as it relies entirely
on outlier data and is more likely to be influenced by odd spikes and dropouts than either the mean, mode or median.

Hello Mark

I have to say that you are completely right ... The problem is that I'm just a beginner in programming with Arduino, and that I barely understand your example in the comment above. Is there a way that you could explain me your code?

Thanks in advance
Stan

Do you want to average or smooth the data?

To smooth data I use SimpleKalmanFilter

I want to average the data

Take 5 readings with a 1 sec delay between each
add em up as you go
divide by 5.

staneveraert:
Hello Mark

I have to say that you are completely right ... The problem is that I'm just a beginner in programming with Arduino, and that I barely understand your example in the comment above. Is there a way that you could explain me your code?

Thanks in advance
Stan

Its a function called average that takes an array of samples and an integer count of the samples,
then computes the average (to be precise, the mean).

You need to call it with an appropriate array of samples collected over the last 5 seconds...

The code works now, thanks for the help everybody!

/*

  In dit programma zal de arduino de gemiddelde waarde van een sensor berekenen over 5 seconden, en over 1000 intervallen. De gemiddelde waarde zal na X seconden verschijnen op de LCD.

*/

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const int sensorPin = A0;
const int kalibratieLED = 13;
const int drukknop = 0;
const int intervallen = 1000;

int gemiddelde;
int knopwaarde;
int Oknopwaarde = LOW;

unsigned long vorigeTijd = 0;
unsigned long kalibratieTijd = 5000;

unsigned int som = 0;

void setup() {
  Serial.begin(9600);
  pinMode(kalibratieLED, OUTPUT);
  pinMode(drukknop, INPUT);
}

void loop() {
  knopwaarde = digitalRead(drukknop);
  if (Oknopwaarde != knopwaarde) {
    if (millis() - vorigeTijd > kalibratieTijd) {
      vorigeTijd = millis();
      for (int loops = 0; loops < intervallen; loops++) {
        som = som + analogRead(sensorPin);
        Serial.println(som);
        digitalWrite(kalibratieLED, HIGH);
        delay(kalibratieTijd / intervallen);
      }
      gemiddelde = float(som) / intervallen;
      Serial.println(gemiddelde);
      lcd.setCursor(0, 0);
      lcd.print(gemiddelde);
      digitalWrite(kalibratieLED, LOW);
    }
    som = 0;
  }
}

But now I have another question. I want to compare the values that the sensor reads with the mean value I calculated (f.e. if the sensorvalue is 200 ‘points’ higher than the mean value, write the LED high). I tried the program beneeth, but the LED remains HIGH …

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const int sensorPin = A0;
const int calLED = 13;
const int pushbutton = 0;
const int intervals = 1000;
const int LED = 6;

int mean;
int buttonstate;
int oldButtonState = LOW;
int value;

unsigned long prevTime = 0;
unsigned long calTime = 5000;

unsigned int sum = 0;

void setup() {
  Serial.begin(9600);
  pinMode(calLED, OUTPUT);
  pinMode(pushbutton, INPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  buttonstate = digitalRead(pushbutton);
  if (oldButtonState != buttonState) {
    if (millis() - prevTime> calTime) {
      prevTime = millis();
      for (int loops = 0; loops < intervals; loops++) {
        sum = sum + analogRead(sensorPin);
        Serial.println(sum);
        digitalWrite(calLED, HIGH);
        delay(calTime / intervals);
      }
      mean = float(sum) / intervals;
      Serial.println(mean);
      lcd.setCursor(0, 0);
      lcd.print(mean);
      digitalWrite(kalibratieLED, LOW);
    }
    sum = 0;
  }
value = analogRead(pinSensor);
  if(abs(value - mean) > 200){
    digitalWrite(LED, HIGH);
  }
}

The LED is energized here

 Serial.println(sum);
        digitalWrite(calLED, HIGH);
        delay(calTime / intervals);

The comparison is done here, the LED is already on.

if(abs(value) > ( mean + 200) ){
    digitalWrite(LED, HIGH);
  }

Where is the code to turn the LED off? If the only code is to turn the LED on, then it makes sense that the only thing the LED will do is turn on.

Some place you will need to code in digitalWrite(LED, LOW);

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.