I'm measuring a analog input value which in turn converts and display a voltage qualtity to my display. I found that the measurement is mostly correct in a range but fluctate a lot.
I've implemented signal smoothing as per example below.
My question is , how do I truncate the sample value? I want to discard the highest and lowest value in the sample and use the rest for an average calc. Any advise would be appreciated.
Thanks
//
// Helper function to smooth out the light sensor data.
// Takes any number of readings and smoothes out the data to an average value.
//
// Returns 8-bit value (0-255).
//
int smooth(){
int i;
int value = 0;
int numReadings = 10;
for (i = 0; i < numReadings; i++){
// Read light sensor data.
value = value + analogRead(sensor);
// 1ms pause adds more stability between reads.
delay(1);
}
// Take an average of all the readings.
value = value / numReadings;
}
First I'll say that I wouldn't throw out data. I'd take more samples and average more samples.
With that said, to do what you're asking, I would store all the analogRead() values in an array, then for loop through the array to find the the highest and lowest value.
From there it would just be a matter of calculating the average of all the indices in the array (except the Max/min).
I'd do something like this (completely untested, just for illustration)
int sampleSize = 10;
int sampleRate = 10;
int myArray[sampleSize];
float average = 0;
int maxVal = 0; //set low so any value read will be higher
int minVal = 1024; //set arbitrarily high so any value read will be lower
for(int i=0; i < sampleSize; i++)
{
myArray[i] = analogRead(0);
if(myArray[i] >= maxVal)
maxVal = myArray[i];
if(myArray[i] <= minVal)
minVal = myArray[i];
delay(sampleRate);
}
for(int i; i < sampleSize; i++)
{
sum = sum + myArray[i];
}
average = (sum - (maxVal+minVal))/(sampleSize-2);
I will play around with multiple average of samples and give your idea a try. ...did not think about that.
I did notice that there pops in a couple of low and high values over a decent size sample. So I dont think throwing out one high and one low will make thay a big differnce in say a sample of 50 readings?
This can be very effective in cases where occasional large outliers cause conventional smoothing to fail, but requires constant sorting of the input data.
In my experience, using a cheap exponential moving average filter followed by a hysteresis stage works very well to eliminate the fluctuations in an analog reading.
[color=#434f54]// Include the library[/color]
[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Filters[/color][/b][color=#434f54].[/color][color=#000000]h[/color][color=#434f54]>[/color]
[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]AH[/color][/b][color=#434f54]/[/color][color=#000000]Hardware[/color][color=#434f54]/[/color][b][color=#d35400]FilteredAnalog[/color][/b][color=#434f54].[/color][color=#000000]hpp[/color][color=#434f54]>[/color]
[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]AH[/color][/b][color=#434f54]/[/color][color=#000000]Timing[/color][color=#434f54]/[/color][color=#000000]MillisMicrosTimer[/color][color=#434f54].[/color][color=#000000]hpp[/color][color=#434f54]>[/color]
[color=#434f54]// Create a filtered analog object on pin A0, with the default settings:[/color]
[b][color=#d35400]FilteredAnalog[/color][/b][color=#434f54]<[/color][color=#434f54]>[/color] [color=#000000]analog[/color] [color=#434f54]=[/color] [color=#000000]A0[/color][color=#000000];[/color]
[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
[b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000]115200[/color][color=#000000])[/color][color=#000000];[/color]
[color=#5e6d03]while[/color] [color=#000000]([/color][color=#434f54]![/color][b][color=#d35400]Serial[/color][/b][color=#000000])[/color]
[color=#000000];[/color]
[color=#434f54]// Select the correct ADC resolution[/color]
[color=#000000]analog[/color][color=#434f54].[/color][color=#d35400]setupADC[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]
[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
[color=#434f54]// Read the analog input every millisecond, and print if the value has changed[/color]
[color=#00979c]static[/color] [b][color=#d35400]Timer[/color][/b][color=#434f54]<[/color][color=#d35400]millis[/color][color=#434f54]>[/color] [color=#000000]timer[/color] [color=#434f54]=[/color] [color=#000000]1[/color][color=#000000];[/color] [color=#434f54]// ms[/color]
[color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]timer[/color] [color=#434f54]&&[/color] [color=#000000]analog[/color][color=#434f54].[/color][color=#d35400]update[/color][color=#000000]([/color][color=#000000])[/color][color=#000000])[/color]
[b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]analog[/color][color=#434f54].[/color][color=#d35400]getValue[/color][color=#000000]([/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]
Take a look at the inputs.
If they are all over the place then question the value of the signal.
You cannot fix a bad sensor in software.
Also consider signal filters before the ADC.
paulw2:
I'm measuring a analog input value which in turn converts and display a voltage qualtity to my display.
What sensor you're using.
Measuring a 'voltage' with a ratiometric A/D (what you're code is doing) is fundamentally wrong.
Measuring a ratiometric sensor with a ratiometric A/D, and convert it into a voltage (which you can't do with simple code like that) is also wrong.
Give us all the facts, including schematic/pictures/powering/etc. of the setup.
All the advice given so far is impressive, but could be wrong for your sensor.
Leo..
paulw2:
Hi Im using a simple voltage divider with low %tolerances.
A voltage divider to bring a higher voltage down to what the Arduino can measure?
If you measure a voltage, then you must use (one of) the internal reference voltage(s) for a stable result.
Default Aref measures a ratio (of the 5volt supply).
If the 5volt supply 'wobbles', so will the end result.
Low tolerance resistors means nothing.
Aref could be 5% or more off, and that usually sets the final tolerance.
Now tell us what you're really trying to do.
Leo..
What generates the signal?
What is the full scale of the signal?
Do you have a data sheet for the device that generates the signal?
This is where you should be giving excessive details. Data sheets , links to the device etc.
Also schematic of your circuit. Measuring an AC waveform with a simple voltage divider?