Averaging multiple sensor readings

Hey guys i need some help averageing my sensor readings. I would like to average them over 3 readings. Any input on this? I have looked at the smoothing example but there must be an easier way than that. Thanks!

#include <PWM.h>
#include <PID_v1.h>
#include <SPI.h>
#include <LiquidCrystal.h>

const int ebp = A0;
const int tps = A1;
const int vss = A2;
const int ebswitch = 13;
const int pwmIn = 8;
const int pwmOut = 10;  //change to 9 for real code
//testing only
const int test = 9;  //delete after testing
//
int ebpvalue = 0;
int ebpvalueD= 0;
int tpsvalue = 0;
int vssvalue = 0;
int ebswitchvalue = 0;
//test only
int dc = 114;
//
double totaltime = 5988;
double dutycycleRead = 0.0;
double dutycycleIn= 0.0;
double dutycycleOut = 0.0;
int dutycycleInD = 0;
int dutycycleOutD = 0;
unsigned long durationL;

int32_t frequency = 167; //frequency (in Hz)

//pid info
//Define PID variables
double Setpoint, Input, pidOutput;
//Specify the links and initial tuning parameters
PID myPID(&Input, &pidOutput, &Setpoint,1,40,0, DIRECT);

// initialize lcd with pin numbers
LiquidCrystal lcd (7, 6, 5, 4, 3, 2);

void setup() {
  //TCCR2B = TCCR2B & 0b11111000 | 0x06;  //set frequency to 122 hz
  pinMode(ebp, INPUT);
  pinMode(tps, INPUT);
  pinMode(vss, INPUT);
  pinMode(ebswitch, INPUT);
  pinMode(pwmIn, INPUT);
  pinMode(pwmOut, OUTPUT);   
  pinMode(test, OUTPUT); 
  
      //initialize all timers except for 0, to save time keeping functions
  InitTimersSafe(); 

  //sets the frequency for the specified pin
  bool success = SetPinFrequencySafe(test, frequency);  //change to pwmOut after testing
  //if the pin frequency was set successfully, turn pin 13 on
  if(success) {
    pinMode(test, OUTPUT);   //change to pwmOut after testing 
  }
    //initialize PID variables
  Input = ebpvalue;
  Setpoint = 360;  //test value of 360 = 33.5 psia or 20 psig
  myPID.SetOutputLimits(25, 108);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
}

void loop() {
  
  ebpvalue = analogRead(ebp);
  ebpvalueD = ((ebpvalue * 0.004888 * 19.01) - 13.5);
  //testing only
  dc = map(ebpvalue, 0, 1023, 0, 108);
  pwmWrite(test, dc);
  //
  tpsvalue = analogRead(tps);
  vssvalue = analogRead(vss);
  ebswitchvalue = digitalRead(ebswitch);
  
  durationL = pulseIn(pwmIn, LOW);
  dutycycleRead = (durationL / totaltime) * 100;
  dutycycleIn = (dutycycleRead * 2.55);
  
  lcd.clear();
  
  if (ebswitchvalue == HIGH && tpsvalue < 86 && vssvalue > 300){
    Input = ebpvalue;
    myPID.Compute();
    pwmWrite(pwmOut, pidOutput);
   
   lcd.setCursor(14, 0);
   lcd.print("ON");
   lcd.setCursor(0, 1);
   lcd.print("VGT%:");
   lcd.setCursor(5, 1);
   lcd.print((pidOutput * 0.3922));
  }
  
  else{
   pwmWrite(pwmOut, dutycycleIn);
   lcd.setCursor(13, 0);
   lcd.print("OFF");
   lcd.setCursor(0, 1);
   lcd.print("VGT%:");
   lcd.setCursor(5, 1);
   lcd.print(dutycycleRead);
  }    
  
  if(ebswitchvalue == HIGH){
   lcd.setCursor(0, 0);    
   lcd.print("ENABLED");
  }
  else{
   lcd.setCursor(0, 0);
   lcd.print("DISABLED");
  }
  
  lcd.setCursor(11, 1);
  lcd.print("EP:");
  lcd.setCursor(14, 1);
  lcd.print(ebpvalueD);
  
  delay(1);  
  
}

Read the value 3 times using a for loop adding to a total on each iteration. On completion of the for loop divide the total by 3. What am I missing ?

Incidentally, as ebpvalueD and ebpvalue are ints  ebpvalueD = ((ebpvalue * 0.004888 * 19.01) - 13.5);is probably not doing what you want.

could you explain that a little bit more? i am new to programming and arduino. Thanks!

Which part of UKHeliBob's answer did you not understand?

I am not sure on how to use a for loop to read an analog input multiple times and then take the average of the readings.

I am also unclear of why an int would not work properly for the values i am reading.

Thanks

One example, not sure if it is exactly what you need but maybe it will help get you on the right path.

int sum = 0;
for (int i=0; i<3; i++){     // Basic for loop, if you don't understand it then look it up.  It's not hard.
sum += analogRead(sensorPin);
}
int average = sum /3;

As for why integers don’t work… well, integers only hold whole numbers. They don’t do decimals. So all that math you 've got going on with the decimal places and an int value isn’t going to work out like you want it to. Everything gets rounded off.

What UKHeliBob is saying is that your expression:

ebpvalueD = ((ebpvalue * 0.004888 * 19.01) - 13.5);

uses integer variables for part of the calculation. If ebpvalue equals 100, then:

ebpvalueD =  (100 * .004888 * 19.01) - 13.5;
                       =  (.49 * 19.01) - 13.5;         // Precedence does multiply before subtraction, associate left to right
                       =  9.29 - 13.5;
                       =  -4.21;
ebpvalueD  = -4;

By using integer variables, you lose the decimal fraction component of the answer.

Whole numbers are fine even if they are rounded up for some of my sensors.

I pasted the for loop that Delta_G posted and my reading continuously goes from lowest to highest then repeats.

Sorry guys i am reading up on this as much as i can. I do appreciate your help!

Whole numbers are fine even if they are rounded up for some of my sensors.

Losing the decimal part of the result does not mean that they are rounded up though.

Presumably the magic numbers 100, 0.004888 and 19.01 matter in some way and it would be a shame to throw away that level of precision which obviously matters to someone.

The precision would be nice I agree but i do now want the decimals being displayed on my lcd screen.
I copied and pasted the smoothing example for one of my sensors and it is working but it just seems like alot of code to average the sensor values or am I just hoping this would be super simple?

i am reading the duty cycle of a pwm input using double and it displays the decimal on my lcd which I don't like and is why for some sensors i chose int.

Thanks

lcd.print(someFloat,0); will print the float with zero decimal places.

mitchedwards:
I pasted the for loop that Delta_G posted and my reading continuously goes from lowest to highest then repeats.

Well there's the problem. It wasn't meant as a paste in solution, only as an example of how a for loop works since you seemed to be confused.

Cutting and pasting random bits of code together hardly ever gets you anywhere. You need to understand what the code does and how and then you can write your own code that will do what you actually want it to do.

Thanks groundfungus that makes my lcd so much cleaner!
Delta_G, I am trying to learn coding but i am a mechanical engineering student so it is not my expertise. I have read and read and read but there are some things that are difficult for me to understand.

I do appreciate all the help and advice.

Thank you!

Delta_G:
One example, not sure if it is exactly what you need but maybe it will help get you on the right path.

int sum = 0;

for (int i=0; i<3; i++){     // Basic for loop, if you don’t understand it then look it up.  It’s not hard.
sum += analogRead(sensorPin);
}
int average = sum /3;

If you’re doing averaging with integers, it’s a good idea to add in count/2 to the sum, to give a rounded result. It’s also a good idea to make the count even. I would:

const int count = 4;
int sum = count/2;
for (int i=0; i<count; i++) {
  sum += analogRead(sensorPin);
}
int average = sum / count;

Now if you average {99,100,100,100} you will get a result rounded to 100.
Without the extra count/2, the average will come out to 99.
For some tasks, the rounded value is what you want. YMMV.

Thanks for all the input guys i really appreciate it! Here is what i have so far. Let me know what you think. If my rounding is off by one it will not be the end of the world but i see where you are coming from. I dont want to take to many samples as the value is always changing ( sensors in a truck) and i am just trying to smooth the inputs to the arduino.

Thanks

#include <PID_v1.h>
#include <PWM.h>
#include <SPI.h>
#include <LiquidCrystal.h>

int32_t frequency = 167; //frequency (in Hz)

const int numReadings= 3;

//duty cycle in measurement
const int pwmIn = 8;
float totaltime = 6000.0;
float dutycycleIn;
unsigned long durationL;
float durationL_readings[numReadings];      
int durationL_index = 0;                  
float durationL_total = 0;                  
float durationL_average = 0; 

//duty cycle out
int dutycycleOut = 0;

//exhaust pressure sensor
int ebp_readings[numReadings];      
int ebp_index = 0;                  
float ebp_total = 0;                  
float ebp_average = 0; 
const int ebp = A0;

//throttle position sensor
int tps_readings[numReadings];      
int tps_index = 0;                  
float tps_total = 0;                  
float tps_average = 0; 
const int tps = A1;

//vehicle speed sensor
int vss_readings[numReadings];      
int vss_index = 0;                  
float vss_total = 0;                  
float vss_average = 0; 
const int vss = A2;

// exhaust brake switch that enables or disabled exhaust brake
const int ebswitch = 12;
int ebswitchvalue = 0;

//pid information
double Setpoint, Input, pidOutput;
PID myPID(&Input, &pidOutput, &Setpoint,1,0,0, DIRECT);

const int pwmOut = 9;
float starttime;
float ebdelay;

// initialize lcd
LiquidCrystal lcd (7, 6, 5, 4, 3, 2);

void setup() {
  pinMode(pwmIn, INPUT);
  pinMode(ebswitch, INPUT);
  pwmWrite(pwmOut, 100);  //testing only
  
  //exhaust pressure sensor
  for (int ebp_thisReading = 0; ebp_thisReading < numReadings; ebp_thisReading++)
    ebp_readings[ebp_thisReading] = 0;
  // duty cycle in measurement
  for (int durationL_thisReading = 0; durationL_thisReading < numReadings; durationL_thisReading++)
    durationL_readings[durationL_thisReading] = 0;
  
  //throttle position sensor
  for (int tps_thisReading = 0; tps_thisReading < numReadings; tps_thisReading++)
    tps_readings[tps_thisReading] = 0;  
 
  //vehicle speed sensor
  for (int vss_thisReading = 0; vss_thisReading < numReadings; vss_thisReading++)
    vss_readings[vss_thisReading] = 0;    

  //initialize all timers except for 0, to save time keeping functions
  InitTimersSafe(); 
  //sets the frequency for pwmOut pin 9
  bool success = SetPinFrequencySafe(pwmOut, frequency);  //change to pwmOut after testing
  //if the pin frequency was set successfully, turn pin 13 on
  if(success) {
    pinMode(pwmOut, OUTPUT);   //change to pwmOut after testing 
  }
  //initialize PID variables
  Input = ebp_average;
  Setpoint = 360;  //test value of 360 = 33 psia or 20 psig
  myPID.SetOutputLimits(39, 115);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);    
  
  // lcd setup
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("TURBO:");
  lcd.setCursor(0,1);
  lcd.print("EBP:");

}

void loop() {
  //starttime = micros();
  
  //duty cycle in measurement
  durationL_total= durationL_total - durationL_readings[durationL_index];         
  durationL_readings[durationL_index] = pulseIn(pwmIn, LOW); 
  durationL_total= durationL_total + durationL_readings[durationL_index];         
  durationL_index = durationL_index + 1;                    
  if (durationL_index >= numReadings)              
    durationL_index = 0;                           
    
  durationL_average = durationL_total / numReadings; 
  dutycycleIn = durationL_average / totaltime;
  dutycycleOut = map(dutycycleIn * 100, 0, 100, 0, 255);
  
  //exhaust pressure sensor
  ebp_total= ebp_total - ebp_readings[ebp_index];         
  ebp_readings[ebp_index] = analogRead(ebp); 
  ebp_total= ebp_total + ebp_readings[ebp_index];         
  ebp_index = ebp_index + 1;                    
  if (ebp_index >= numReadings)              
    ebp_index = 0;                           
    
  ebp_average = ebp_total / numReadings;    
  
  //throttle position sensor
  tps_total= tps_total - tps_readings[tps_index];         
  tps_readings[tps_index] = analogRead(tps); 
  tps_total= tps_total + tps_readings[tps_index];         
  tps_index = tps_index + 1;                    
  if (tps_index >= numReadings)              
    tps_index = 0;                           
    
  tps_average = tps_total / numReadings; 
  
  //vehicle speed sensor
  vss_total= vss_total - vss_readings[vss_index];         
  vss_readings[vss_index] = analogRead(vss); 
  vss_total= vss_total + vss_readings[vss_index];         
  vss_index = vss_index + 1;                    
  if (vss_index >= numReadings)              
    vss_index = 0;                           
    
  vss_average = vss_total / numReadings; 
  
  //exhaust brake enable disable switch
  ebswitchvalue = digitalRead(ebswitch);
  if(ebswitchvalue == HIGH){
    lcd.setCursor(14,0);
    lcd.print("  ");
    lcd.setCursor(14,0);
    lcd.print("EN");
  }
  else{
    lcd.setCursor(14,0);
    lcd.print("  ");
    lcd.setCursor(14,0);
    lcd.print("DD");
  }    
  
  // output
  if (ebswitchvalue ==HIGH && tps_average <= 85 && vss_average >= 200){
    Input = ebp_average;
    myPID.Compute();
    pwmWrite(pwmOut, pidOutput); 
    //print pidoutput
    lcd.setCursor(6, 0);
    lcd.print("   ");
    lcd.setCursor(6,0);
    lcd.print(pidOutput * 100,0);   
    
    lcd.setCursor(14,1);
    lcd.print("  ");
    lcd.setCursor(14,1);
    lcd.print("ON");
  }
  
  else{
    pwmWrite(pwmOut, dutycycleOut);
    //print duty cycle in measurement
    lcd.setCursor(6, 0);
    lcd.print("   ");
    lcd.setCursor(6,0);
    lcd.print(dutycycleIn * 100,0);

    lcd.setCursor(13,1);
    lcd.print("   ");
    lcd.setCursor(13,1);
    lcd.print("OFF");
  }
  
  //print exhaust pressure sensor measurement
  lcd.setCursor(5, 1);
  lcd.print("  ");
  lcd.setCursor(5, 1);
  lcd.print(((ebp_average * 0.004888 * 19.01) - 13), 0);
/*
  //print code cycle time
  lcd.setCursor(0,1);
  lcd.print("        ");
  lcd.setCursor(0,1);
  lcd.print (micros() - starttime, 0);
 */
}