Last active
January 19, 2017 17:27
-
-
Save cowboy/f6360088180a30ba4b55491dd666d4df to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* digitalSmooth | |
Paul Badger 2007 | |
A digital smoothing filter for smoothing sensor jitter | |
This filter accepts one new piece of data each time through a loop, which the | |
filter inputs into a rolling array, replacing the oldest data with the latest reading. | |
The array is then transferred to another array, and that array is sorted from low to high. | |
Then the highest and lowest %15 of samples are thrown out. The remaining data is averaged | |
and the result is returned. | |
Every sensor used with the digitalSmooth function needs to have its own array to hold | |
the raw sensor values. This array is then passed to the function, for it's use. | |
This is done with the name of the array associated with the particular sensor. | |
*/ | |
/* | |
#define SensorPin1 0 | |
#define SensorPin2 0 | |
#define filterSamples 13 // filterSamples should be an odd number, no smaller than 3 | |
int sensSmoothArray1 [filterSamples]; // array for holding raw sensor values for sensor1 | |
int sensSmoothArray2 [filterSamples]; // array for holding raw sensor values for sensor2 | |
int rawData1, smoothData1; // variables for sensor1 data | |
int rawData2, smoothData2; // variables for sensor2 data | |
void setup(){ | |
Serial.begin(9600); | |
} | |
void loop(){ // test the digitalSmooth function | |
rawData1 = analogRead(SensorPin1); // read sensor 1 | |
smoothData1 = digitalSmooth(rawData1, sensSmoothArray1); // every sensor you use with digitalSmooth needs its own array | |
Serial.print(rawData1); | |
Serial.print(" "); | |
Serial.println(smoothData1); | |
rawData2 = analogRead(SensorPin2); // read sensor 2 | |
smoothData2 = digitalSmooth(rawData2, sensSmoothArray2); // every sensor you use with digitalSmooth needs its own array | |
} | |
*/ | |
#define filterSamples 33 | |
int digitalSmooth(int rawIn, int *sensSmoothArray){ // "int *sensSmoothArray" passes an array to the function - the asterisk indicates the array name is a pointer | |
int j, k, temp, top, bottom; | |
long total; | |
static int i; | |
// static int raw[filterSamples]; | |
static int sorted[filterSamples]; | |
boolean done; | |
i = (i + 1) % filterSamples; // increment counter and roll over if necc. - % (modulo operator) rolls over variable | |
sensSmoothArray[i] = rawIn; // input new data into the oldest slot | |
// Serial.print("raw = "); | |
for (j=0; j<filterSamples; j++){ // transfer data array into anther array for sorting and averaging | |
sorted[j] = sensSmoothArray[j]; | |
} | |
done = 0; // flag to know when we're done sorting | |
while(done != 1){ // simple swap sort, sorts numbers from lowest to highest | |
done = 1; | |
for (j = 0; j < (filterSamples - 1); j++){ | |
if (sorted[j] > sorted[j + 1]){ // numbers are out of order - swap | |
temp = sorted[j + 1]; | |
sorted [j+1] = sorted[j] ; | |
sorted [j] = temp; | |
done = 0; | |
} | |
} | |
} | |
/* | |
for (j = 0; j < (filterSamples); j++){ // print the array to debug | |
Serial.print(sorted[j]); | |
Serial.print(" "); | |
} | |
Serial.println(); | |
*/ | |
// throw out top and bottom 15% of samples - limit to throw out at least one from top and bottom | |
bottom = max(((filterSamples * 15) / 100), 1); | |
top = min((((filterSamples * 85) / 100) + 1 ), (filterSamples - 1)); // the + 1 is to make up for asymmetry caused by integer rounding | |
k = 0; | |
total = 0; | |
for ( j = bottom; j< top; j++){ | |
total += sorted[j]; // total remaining indices | |
k++; | |
// Serial.print(sorted[j]); | |
// Serial.print(" "); | |
} | |
// Serial.println(); | |
// Serial.print("average = "); | |
// Serial.println(total/k); | |
return total / k; // divide by number of samples | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* fscale | |
Floating Point Autoscale Function V0.1 | |
Paul Badger 2007 | |
Modified from code by Greg Shakar | |
This function will scale one set of floating point numbers (range) to another set of floating point numbers (range) | |
It has a "curve" parameter so that it can be made to favor either the end of the output. (Logarithmic mapping) | |
It takes 6 parameters | |
originalMin - the minimum value of the original range - this MUST be less than origninalMax | |
originalMax - the maximum value of the original range - this MUST be greater than orginalMin | |
newBegin - the end of the new range which maps to orginalMin - it can be smaller, or larger, than newEnd, to facilitate inverting the ranges | |
newEnd - the end of the new range which maps to originalMax - it can be larger, or smaller, than newBegin, to facilitate inverting the ranges | |
inputValue - the variable for input that will mapped to the given ranges, this variable is constrained to originaMin <= inputValue <= originalMax | |
curve - curve is the curve which can be made to favor either end of the output scale in the mapping. Parameters are from -10 to 10 with 0 being | |
a linear mapping (which basically takes curve out of the equation) | |
To understand the curve parameter do something like this: | |
void loop(){ | |
for ( j=0; j < 200; j++){ | |
scaledResult = fscale( 0, 200, 0, 200, j, -1.5); | |
Serial.print(j, DEC); | |
Serial.print(" "); | |
Serial.println(scaledResult, DEC); | |
} | |
} | |
And try some different values for the curve function - remember 0 is a neutral, linear mapping | |
To understand the inverting ranges, do something like this: | |
void loop(){ | |
for ( j=0; j < 200; j++){ | |
scaledResult = fscale( 0, 200, 200, 0, j, 0); | |
// Serial.print lines as above | |
} | |
} | |
*/ | |
#include <math.h> | |
int j; | |
float scaledResult; | |
/* | |
void setup() { | |
Serial.begin(9600); | |
} | |
void loop(){ | |
for ( j=0; j < 200; j++){ | |
scaledResult = fscale( 0, 200, 0, 200, j, -1.5); | |
Serial.print(j, DEC); | |
Serial.print(" "); | |
Serial.println(scaledResult , DEC); | |
} | |
} | |
*/ | |
float fscale( float originalMin, float originalMax, float newBegin, float | |
newEnd, float inputValue, float curve){ | |
float OriginalRange = 0; | |
float NewRange = 0; | |
float zeroRefCurVal = 0; | |
float normalizedCurVal = 0; | |
float rangedValue = 0; | |
boolean invFlag = 0; | |
// condition curve parameter | |
// limit range | |
if (curve > 10) curve = 10; | |
if (curve < -10) curve = -10; | |
curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output | |
curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function | |
/* | |
Serial.println(curve * 100, DEC); // multply by 100 to preserve resolution | |
Serial.println(); | |
*/ | |
// Check for out of range inputValues | |
if (inputValue < originalMin) { | |
inputValue = originalMin; | |
} | |
if (inputValue > originalMax) { | |
inputValue = originalMax; | |
} | |
// Zero Refference the values | |
OriginalRange = originalMax - originalMin; | |
if (newEnd > newBegin){ | |
NewRange = newEnd - newBegin; | |
} | |
else | |
{ | |
NewRange = newBegin - newEnd; | |
invFlag = 1; | |
} | |
zeroRefCurVal = inputValue - originalMin; | |
normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float | |
/* | |
Serial.print(OriginalRange, DEC); | |
Serial.print(" "); | |
Serial.print(NewRange, DEC); | |
Serial.print(" "); | |
Serial.println(zeroRefCurVal, DEC); | |
Serial.println(); | |
*/ | |
// Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine | |
if (originalMin > originalMax ) { | |
return 0; | |
} | |
if (invFlag == 0){ | |
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin; | |
} | |
else // invert the ranges | |
{ | |
rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange); | |
} | |
return rangedValue; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment