Skip to content

Commit 5844049

Browse files
authored
Merge pull request #13 from DrGFreeman/esp8266
Fixed compilation issues on ESP8266 boards
2 parents f190df9 + 6c235ec commit 5844049

4 files changed

Lines changed: 217 additions & 181 deletions

File tree

MedianFilter.cpp

Lines changed: 172 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,180 +1,207 @@
11
/*
2-
MedianFilter.cpp - Median Filter for the Arduino platform.
3-
Copyright (c) 2013 Phillip Schmidt. All right reserved.
4-
5-
This library is free software; you can redistribute it and/or
6-
modify it under the terms of the GNU Lesser General Public
7-
License as published by the Free Software Foundation; either
8-
version 2.1 of the License, or (at your option) any later version.
9-
10-
This library is distributed in the hope that it will be useful,
11-
but WITHOUT ANY WARRANTY; without even the implied warranty of
12-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13-
Lesser General Public License for more details.
14-
15-
You should have received a copy of the GNU Lesser General Public
16-
License along with this library; if not, write to the Free Software
17-
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2+
MedianFilter.cpp - Median Filter for the Arduino platform.
3+
Copyright (c) 2013 Phillip Schmidt. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1818
*/
1919

20-
/*
21-
A median filter object is created by by passing the desired filter window size on object creation.
22-
The window size should be an odd number between 3 and 255.
23-
24-
New data is added to the median filter by passing the data through the in() function. The new medial value is returned.
25-
The new data will over-write the oldest data point, then be shifted in the array to place it in the correct location.
26-
27-
The current median value is returned by the out() function for situations where the result is desired without passing in new data.
28-
29-
!!! All data must be type INT. !!!
30-
31-
Window Size / avg processing time [us]
32-
5 / 22
33-
7 / 30
34-
9 / 40
35-
11 / 49
36-
21 / 99
37-
20+
/*
21+
A median filter object is created by by passing the desired filter window size on object creation.
22+
The window size should be an odd number between 3 and 255.
23+
24+
New data is added to the median filter by passing the data through the in() function. The new medial value is returned.
25+
The new data will over-write the oldest data point, then be shifted in the array to place it in the correct location.
26+
27+
The current median value is returned by the out() function for situations where the result is desired without passing in new data.
28+
29+
!!! All data must be type INT. !!!
30+
31+
Window Size / avg processing time [us]
32+
5 / 22
33+
7 / 30
34+
9 / 40
35+
11 / 49
36+
21 / 99
37+
3838
*/
3939

4040
#include "MedianFilter.h"
4141

42-
4342

44-
MedianFilter::MedianFilter(const byte size, const int seed)
43+
MedianFilter::MedianFilter(int size, int seed)
4544
{
46-
47-
medFilterWin = max(size, 3); // number of samples in sliding median filter window - usually odd #
48-
medDataPointer = size >> 1; // mid point of window
49-
data = (int*) calloc (size, sizeof(int)); // array for data
50-
sizeMap = (byte*) calloc (size, sizeof(byte)); // array for locations of data in sorted list
51-
locationMap = (byte*) calloc (size, sizeof(byte)); // array for locations of history data in map list
52-
oldestDataPoint = medDataPointer; // oldest data point location in data array
53-
54-
for(byte i = 0; i < medFilterWin; i++) // initialize the arrays
55-
{
56-
sizeMap[i] = i; // start map with straight run
57-
locationMap[i] = i; // start map with straight run
58-
data[i] = seed; // populate with seed value
59-
}
60-
45+
medFilterWin = constrain(size, 3, 255); // number of samples in sliding median filter window - usually odd #
46+
medDataPointer = size >> 1; // mid point of window
47+
data = (int*) calloc (size, sizeof(int)); // array for data
48+
sizeMap = (uint8_t*) calloc (size, sizeof(uint8_t)); // array for locations of data in sorted list
49+
locationMap = (uint8_t*) calloc (size, sizeof(uint8_t)); // array for locations of history data in map list
50+
oldestDataPoint = medDataPointer; // oldest data point location in data array
51+
totalSum = size * seed; // total of all values
52+
53+
for(uint8_t i = 0; i < medFilterWin; i++) // initialize the arrays
54+
{
55+
sizeMap[i] = i; // start map with straight run
56+
locationMap[i] = i; // start map with straight run
57+
data[i] = seed; // populate with seed value
58+
}
6159
}
6260

63-
int MedianFilter::in(int value)
64-
{
65-
// sort sizeMap
66-
// small vaues on the left (-)
67-
// larger values on the right (+)
68-
69-
boolean dataMoved = false;
70-
const byte rightEdge = medFilterWin - 1; // adjusted for zero indexed array
71-
72-
data[oldestDataPoint] = value; // store new data in location of oldest data in ring buffer
73-
74-
// SORT LEFT (-) <======(n) (+)
75-
if(locationMap[oldestDataPoint] > 0){ // don't check left neighbours if at the extreme left
76-
77-
for(byte i = locationMap[oldestDataPoint]; i > 0; i--){ //index through left adjacent data
78-
79-
byte n = i - 1; // neighbour location
80-
81-
if(data[oldestDataPoint] < data[sizeMap[n]]){ // find insertion point, move old data into position
82-
83-
sizeMap[i] = sizeMap[n]; // move existing data right so the new data can go left
84-
locationMap[sizeMap[n]]++;
85-
86-
sizeMap[n] = oldestDataPoint; // assign new data to neighbor position
87-
locationMap[oldestDataPoint]--;
88-
89-
dataMoved = true;
90-
91-
}
92-
else {
93-
94-
break; // stop checking once a smaller value is found on the left
95-
96-
}
97-
}
98-
}
99-
100-
// SORT RIGHT (-) (n)======> (+)
101-
if(!dataMoved && locationMap[oldestDataPoint] < rightEdge){ // don't check right if at right border, or the data has already moved
102-
103-
for(int i = locationMap[oldestDataPoint]; i < rightEdge; i++){ //index through left adjacent data
104-
105-
int n = i + 1; // neighbour location
106-
107-
if(data[oldestDataPoint] > data[sizeMap[n]]){ // find insertion point, move old data into position
108-
109-
sizeMap[i] = sizeMap[n]; // move existing data left so the new data can go right
110-
locationMap[sizeMap[n]]--;
111-
112-
sizeMap[n] = oldestDataPoint; // assign new data to neighbor position
113-
locationMap[oldestDataPoint]++;
114-
115-
}
116-
else {
117-
118-
break; // stop checking once a smaller value is found on the right
119-
120-
}
121-
}
122-
}
123-
124-
oldestDataPoint++; // increment and wrap
125-
if(oldestDataPoint == medFilterWin)
126-
oldestDataPoint = 0;
127-
128-
return data[sizeMap[medDataPointer]];
61+
62+
int MedianFilter::in(const int & value)
63+
{
64+
// sort sizeMap
65+
// small vaues on the left (-)
66+
// larger values on the right (+)
67+
68+
boolean dataMoved = false;
69+
const uint8_t rightEdge = medFilterWin - 1; // adjusted for zero indexed array
70+
71+
totalSum += value - data[oldestDataPoint]; // add new value and remove oldest value
72+
73+
data[oldestDataPoint] = value; // store new data in location of oldest data in ring buffer
74+
75+
// SORT LEFT (-) <======(n) (+)
76+
if(locationMap[oldestDataPoint] > 0) // don't check left neighbours if at the extreme left
77+
{
78+
for(uint8_t i = locationMap[oldestDataPoint]; i > 0; i--) //index through left adjacent data
79+
{
80+
uint8_t n = i - 1; // neighbour location
81+
82+
if(data[oldestDataPoint] < data[sizeMap[n]]) // find insertion point, move old data into position
83+
{
84+
sizeMap[i] = sizeMap[n]; // move existing data right so the new data can go left
85+
locationMap[sizeMap[n]]++;
86+
87+
sizeMap[n] = oldestDataPoint; // assign new data to neighbor position
88+
locationMap[oldestDataPoint]--;
89+
90+
dataMoved = true;
91+
}
92+
else
93+
{
94+
break; // stop checking once a smaller value is found on the left
95+
}
96+
}
97+
}
98+
99+
// SORT RIGHT (-) (n)======> (+)
100+
if(!dataMoved && locationMap[oldestDataPoint] < rightEdge) // don't check right if at right border, or the data has already moved
101+
{
102+
for(int i = locationMap[oldestDataPoint]; i < rightEdge; i++) //index through left adjacent data
103+
{
104+
int n = i + 1; // neighbour location
105+
106+
if(data[oldestDataPoint] > data[sizeMap[n]]) // find insertion point, move old data into position
107+
{
108+
sizeMap[i] = sizeMap[n]; // move existing data left so the new data can go right
109+
locationMap[sizeMap[n]]--;
110+
111+
sizeMap[n] = oldestDataPoint; // assign new data to neighbor position
112+
locationMap[oldestDataPoint]++;
113+
}
114+
else
115+
{
116+
break; // stop checking once a smaller value is found on the right
117+
}
118+
}
119+
}
120+
oldestDataPoint++; // increment and wrap
121+
if(oldestDataPoint == medFilterWin) oldestDataPoint = 0;
122+
123+
return data[sizeMap[medDataPointer]];
129124
}
130125

131126

132127
int MedianFilter::out() // return the value of the median data sample
133128
{
134-
return data[sizeMap[medDataPointer]];
129+
return data[sizeMap[medDataPointer]];
135130
}
136131

137132

133+
int MedianFilter::getMin()
134+
{
135+
return data[sizeMap[ 0 ]];
136+
}
137+
138+
139+
int MedianFilter::getMax()
140+
{
141+
return data[sizeMap[ medFilterWin - 1 ]];
142+
}
143+
144+
145+
int MedianFilter::getMean()
146+
{
147+
return totalSum / medFilterWin;
148+
}
149+
150+
151+
int MedianFilter::getStDev() // Arduino run time [us]: filterSize * 2 + 131
152+
{
153+
int32_t diffSquareSum = 0;
154+
int mean = getMean();
155+
156+
for( int i = 0; i < medFilterWin; i++ )
157+
{
158+
int diff = data[i] - mean;
159+
diffSquareSum += diff * diff;
160+
}
161+
162+
return int( sqrtf( float(diffSquareSum) / float(medFilterWin - 1) ) + 0.5f );
163+
}
164+
138165

139166
// *** debug fuctions ***
140167
/*
141168
void MedianFilter::printData() // display sorting data for debugging
142169
{
143-
for(int i=0; i<medFilterWin; i++)
144-
{
145-
Serial.print(data[i]);
146-
Serial.print("\t");
147-
}
148-
Serial.println("Data in ring buffer");
170+
for(int i=0; i<medFilterWin; i++)
171+
{
172+
Serial.print(data[i]);
173+
Serial.print("\t");
174+
}
175+
Serial.println("Data in ring buffer");
149176
}
150177
151178
void MedianFilter::printSizeMap()
152-
{
153-
for(int i=0; i<medFilterWin; i++)
154-
{
155-
Serial.print(sizeMap[i]);
156-
Serial.print("\t");
157-
}
158-
Serial.println("Size Map, data sorted by size");
179+
{
180+
for(int i=0; i<medFilterWin; i++)
181+
{
182+
Serial.print(sizeMap[i]);
183+
Serial.print("\t");
184+
}
185+
Serial.println("Size Map, data sorted by size");
159186
}
160187
161188
void MedianFilter::printLocationMap()
162-
{
163-
for(int i=0; i<medFilterWin; i++)
164-
{
165-
Serial.print(locationMap[i]);
166-
Serial.print("\t");
167-
}
168-
Serial.println("Location Map, size data sorted by age");
169-
}
189+
{
190+
for(int i=0; i<medFilterWin; i++)
191+
{
192+
Serial.print(locationMap[i]);
193+
Serial.print("\t");
194+
}
195+
Serial.println("Location Map, size data sorted by age");
196+
}
170197
171198
void MedianFilter::printSortedData() // display data for debugging
172199
{
173-
for(int i=0; i<medFilterWin; i++)
174-
{
175-
Serial.print(data[sizeMap[i]]);
176-
Serial.print("\t");
177-
}
178-
Serial.println("Data sorted by size");
200+
for(int i=0; i<medFilterWin; i++)
201+
{
202+
Serial.print(data[sizeMap[i]]);
203+
Serial.print("\t");
204+
}
205+
Serial.println("Data sorted by size");
179206
}
180207
*/

0 commit comments

Comments
 (0)