Hi all, I have an analogue pressure sensor reading 0-3PSI it converts the voltage the arduino reads and uses my formula to convert that voltage into pressure.
As the pump powers on the pressure readings fluctuate; however manually reading and copying those fluctuations and putting them into excel I worked out an average and it was pretty much correct within a tolerance i'm happy with.
So my question is will you help me implement code to average out my readings and print them to another post? Here's the part of my code that calculates pressure.
float getPSI() {
// Calculate the average of a number of samples.
// The analogRead() is 0...1023.
// When they are all added into a total value, the total should be able to fit in the choosen variable.
// The sketch has a software timing with millis() of 100ms.
// That means a delay below 100ms will have only little influence on the timing of the sketch.
// That is 500us per sample. The analogRead() takes 120us on a Arduino Uno.
// So an extra delay of 500-120 = 380us is needed.
// The 100 samples will fit in a unsigned long.
const int NumberOfSamples = 100;
unsigned long total = 0UL; // start with zero. The 'UL' means "unsigned long"
for (int i = 0; i < NumberOfSamples; i++) {
total += analogRead(pinSensor);
delayMicroseconds(50); // about 500us per loop
}
// Calculating the formula used to convert voltage to pressure in KPA
// Calculate the voltage with floating point
float Vout = (float) total / (float) NumberOfSamples * 5.0 / 1024.0; // 1024 steps from 0V to 5V.
float alpha = 0.036; //Alpha Value
float beta = 0.04; //Beta Value
float Pe = 0.375; //Pressure Error Value
float Te = -70; // Temprature Error Value
float Vdd = 4.95; // Voltage in
float pressure = ( Vout / (alpha * Vdd) ) + ( beta * Pe * Te ); // Calculating Pressure from given variables in KPA
float p = (pressure * 0.145037738); // Calculating PSI from the given pressure
return ( p); // return the pressure in psi
}
Have you considered just applying an interval between pressure measurements to avoid the fluctuations caused at the time of pump startup ? Presumably it is safe to run the pump for several seconds after it first starts ?
If you want to have a continuous average of the last N readings the simplest way is to create an Array that can hold the N readings and treat the array as a circular buffer. Write the next data to the next array position using a variable to hold the index to the next position. add one to the index when every value is saved. When the index exceeds the end of the array set it back to 0. At any time an average of all of the values can be calculated.
If the sensor is removed (mechanically) and left on the bench is it unstable when the pump starts?
if so it might be worth looking into stabilizing the input signal using electrical parts rather than coding a fix for the problem. (a lot of sensors go a little nuts if the board voltage is not stable)
I also would store it in a ring buffer. Store the ADC value rather then the floats.
int newValue = analogRead(pin);
valueSum -= valueBuffer[counter];
valueSum += newValue;
valueBuffer[counter] = newValue;
counter++;
counter %= ( sizeof(valueBuffer) / sizeof(valueBuffer[0]) ); //make it return to 0 is end of buffer is reached
averageValue = (valueSum + ( sizeof(valueBuffer) / sizeof(valueBuffer[0]) / 2 ) / ( sizeof(valueBuffer) / sizeof(valueBuffer[0]) ); //for correct rounding.
Also, it the pressure is only used to drive a pump just use the ACD value instead of calculating the float value. That makes is really slow. And just add a hysteresis to make it stable.
What you really want is not to average, but to low-pass filter the data, to smooth it. That will have the result of excluding "noise" and short transients that are really not representative of the actual data. A simple digital filter is just:
coefficient will always be less than 1. The close coefficient is to 1, the faster the output will respond to input changes, and the more noise will get through. For an application like this, you'd want a coefficient of probably 0.01 to 0.1.
I have a pressure sensor with this type of simple filter built in to it's firmware. It's nice since instead of reading the sensor N times and doing the calculation myself I only have to read it occasionally to get the filtered result. Of course the flip side of filtering is that the response time increases.
A picture sometimes helps. These are curves for settings (2, 4, 8, 16) which refer to the inverse of the coefficient that Ray defined, so coefficient = 1/2, 1/4, 1/8, 1/16:
If the OP chirps up again and shows an interest in the signal processing stuff, I'll suggest an even nicer way to deal with it (Kalman filter cough cough)