Skip to content

Commit 8872190

Browse files
committed
Add a minimum run interval to all filters.
1 parent 97a216b commit 8872190

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

examples/exponential-moving-average/exponential-moving-average.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ void setup() {
88
pinMode(kInputPin, INPUT_PULLUP);
99
input = new ExponentialMovingAverageFilter<uint32_t>(filter_functions::ForAnalogRead<kInputPin>(), 255);
1010
input->SetLogToSerial(true);
11+
input->SetMinRunInterval(50);
1112

1213
pinMode(kLedPin, OUTPUT);
1314
}
@@ -16,5 +17,4 @@ void loop() {
1617
input->Run();
1718
digitalWrite(kLedPin, input->GetFilteredValue() > 511);
1819
Serial.flush();
19-
delay(50);
2020
}

src/filter.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ class Filter {
3636
// Returns the output of the filter, converted.
3737
OutputType GetFilteredValue();
3838

39+
// Instructs the filter to run no more frequently than this delay. This can be
40+
// used to run the filter at a defined rate, which can make the filter more
41+
// consistent.
42+
//
43+
// One way to use this is to measure how long your main loop typically takes,
44+
// and set this to value several times that.
45+
void SetMinRunInterval(uint32_t interval_millis);
46+
3947
// Controls whether to log the input and output values of this filter. Values
4048
// are logged to Serial in the form <input> <output>. Both input and output
4149
// are converted before logging. These values can be graphed using the
@@ -79,6 +87,7 @@ class Filter {
7987
static OutputType NoOpConvert(InputType input);
8088

8189
InputType filtered_value_ = 0;
90+
uint32_t min_run_interval_ = 0;
8291
uint32_t run_at_ = 0;
8392
bool log_to_serial_ = false;
8493

@@ -111,6 +120,8 @@ void Filter<InputType, OutputType>::Run() {
111120
if (log_to_serial_) {
112121
LogState();
113122
}
123+
// Note: if min_run_interval_ is 0 (default), this will have no effect
124+
SetRunDelayInMillis(min_run_interval_);
114125
}
115126
}
116127

@@ -124,6 +135,16 @@ OutputType Filter<InputType, OutputType>::GetFilteredValue() {
124135
return Convert_(filtered_value_);
125136
}
126137

138+
template <typename InputType, typename OutputType>
139+
void Filter<InputType, OutputType>::SetMinRunInterval(
140+
uint32_t interval_millis) {
141+
min_run_interval_ = interval_millis;
142+
143+
if (run_at_ - millis() > interval_millis) {
144+
run_at_ = millis() + interval_millis;
145+
}
146+
}
147+
127148
template <typename InputType, typename OutputType>
128149
void Filter<InputType, OutputType>::SetRunDelayInMillis(uint32_t delay) {
129150
run_at_ = millis() + delay;

test/filter-test.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "gtest/gtest.h"
2+
3+
#include <cstdio>
4+
#include "../src/exponential-moving-average-filter.h"
5+
#include "run-data-test.h"
6+
7+
namespace filter_test {
8+
9+
TEST(Filter, SetMinRunInterval_default) {
10+
// Filter that returns the sensor value immediately
11+
ExponentialMovingAverageFilter<uint32_t> *input = new ExponentialMovingAverageFilter<uint32_t>(analogRead, 255);
12+
std::vector<InputOutput<uint32_t>> data = {
13+
{1, 1, 1},
14+
{2, 1, 2},
15+
{3, 1, 3},
16+
{4, 1, 4},
17+
{5, 1, 5},
18+
};
19+
RunDataTest(input, data);
20+
}
21+
22+
TEST(Filter, SetMinRunInterval_10) {
23+
// Filter that returns the sensor value immediately
24+
ExponentialMovingAverageFilter<uint32_t> *input = new ExponentialMovingAverageFilter<uint32_t>(analogRead, 255);
25+
input->SetMinRunInterval(10);
26+
std::vector<InputOutput<uint32_t>> data = {
27+
{1, 1, 1},
28+
{2, 9, 1},
29+
30+
{1, 1, 1},
31+
{2, 9, 1},
32+
33+
{3, 10, 3},
34+
};
35+
RunDataTest(input, data);
36+
}
37+
38+
TEST(Filter, SetMinRunInterval_updates) {
39+
ExponentialMovingAverageFilter<uint32_t> *input = new ExponentialMovingAverageFilter<uint32_t>(analogRead, 255);
40+
input->SetMinRunInterval(10);
41+
input->SetMillis(0);
42+
analogReadValue = 1;
43+
input->Run();
44+
EXPECT_EQ(input->GetFilteredValue(), 1);
45+
46+
input->SetMinRunInterval(5);
47+
input->SetMillis(5);
48+
analogReadValue = 2;
49+
input->Run();
50+
EXPECT_EQ(input->GetFilteredValue(), 2);
51+
}
52+
53+
}

test/run-data-test.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ void RunDataTest(Filter<uint32_t, O>* filter,
4747
analogReadValue = point.input;
4848
filter->Run();
4949

50-
EXPECT_LE(point.lower_bound, filter->GetFilteredValue())
50+
EXPECT_GE(filter->GetFilteredValue(), point.lower_bound)
5151
<< debug_stream.str();
52-
EXPECT_GE(point.upper_bound, filter->GetFilteredValue())
52+
EXPECT_LE(filter->GetFilteredValue(), point.upper_bound)
5353
<< debug_stream.str();
5454

5555
millis++;

0 commit comments

Comments
 (0)