/*
Solution For:
Topic: What expFilter / algorithm to use ?
Category: Programming Questions
Link: https://forum.arduino.cc/t/what-expFilter-algorithm-to-use/1117083
Sketch: ExponentialFilter.ino
Date: 19-Apr-23 MicroBeaut (μB)
Author: MicroBeaut (μB)
Reference: Triconex - EXPFLTR Function Block
*/
/*
This code initializes an exponential filter and simulates input values for processing.
It reads analog input from pins A0 to A3 and applies the exponential filter to the input values.
The exponential filter smoothens the input data based on a factor and generates an output value.
It contains functions for setting up the filter, simulating input values, applying the filter,
and plotting the input and output values via the serial monitor.
*/
// Pin definitions for reset, factor, noise, and input
#define resetPin A0 // Pin for reset
#define factorPin A1 // Pin for factor adjustment
#define noisePin A2 // Pin for noise input
#define inputPin A3 // Pin for analog input
// Interval definition for triggering actions
#define interval 10UL // 10 milliseconds
// Struct definition for the exponential filter parameters
typedef struct {
float input; // Input value
float initial; // Initial value
float factor; // Factor for smoothing
float output; // Output value
bool badPara; // Flag for bad parameters
bool reset; // Reset flag
} EXPFLTR;
EXPFLTR smooth; // Instance of the exponential filter struct
float factor; // Factor variable
float noise; // Noise variable
long noiseScaleRandom; // Random noise scale
float input; // Input value
float processValue; // Processed value
void setup() {
Serial.begin(115200); // Initialize serial communication
pinMode(resetPin, INPUT_PULLUP); // Set reset pin as input with pull-up resistor
}
void loop() {
bool reset = !digitalRead(resetPin); // Read reset pin state
long factorAin = analogRead(factorPin); // Read analog value from factor pin
long noiseAin = analogRead(noisePin); // Read analog value from noise pin
long inputAin = analogRead(inputPin); // Read analog value from input pin
bool trigger = Interval(interval); // Trigger an action based on the defined interval
// Factor Simulator: Simulate the factor based on analog input
long factorScaling = map(factorAin, 0, 1023, 1, 2000);
factor = factorScaling / 10000.0f; // Scale factor value to the range 0.0001 - 0.2000
// Noise Simulator: Simulate noise based on analog input
long noiseScaling = map(noiseAin, 0, 1023, 1, 100000);
noiseScaleRandom = random(0, noiseScaling);
noise = noiseScaleRandom / 10000.0f; // Scale noise value to the range 0.0000 - 10.0000
// Process Value Simulator: Simulate the input and add noise
long inputScaling = map(inputAin, 0, 1023, 0, 10000);
input = inputScaling / 100.0f;
processValue = input + noise;
// Set the simulated values to EXPFLTR parameters and apply the exponential filter
smooth.initial = processValue; // Set initial value
smooth.input = processValue; // Set input value
smooth.factor = factor; // Set factor value
smooth.reset = reset; // Set reset flag
ExponentialFilter(&smooth); // Apply the exponential filter to the input values
Plot(&smooth); // Plot the input and output values via the serial monitor
}
// Check if the specified interval time has elapsed
bool Interval(unsigned long intervalTime) {
static unsigned long start = millis(); // Record the start time
unsigned long elapsed = millis() - start; // Calculate elapsed time
if (elapsed < intervalTime) return false; // If interval not elapsed, return false
start = millis(); // Reset the start time
return true; // Return true to indicate interval elapsed
}
// Apply the exponential filter to the input values
void ExponentialFilter(EXPFLTR *expFilter) {
static bool firstScan = false; // Flag to indicate first scan
if (!firstScan) {
expFilter->output = expFilter->input; // Set output to initial input value
firstScan = true; // Set first scan flag to true
}
if (expFilter->reset) expFilter->output = expFilter->initial; // Reset output if specified
if (expFilter->factor < 0.0f || expFilter->factor > 1.0f) { // Check for valid factor range
expFilter->badPara = true; // Set flag for bad parameters
return;
} else {
expFilter->badPara = false; // Clear bad parameter flag
}
expFilter->output += expFilter->factor * (expFilter->input - expFilter->output); // Apply the exponential filter equation
}
// Plot the input and output values via the serial monitor
void Plot(EXPFLTR *expFilter) {
Serial.println("expInput:" + String(expFilter->input, 4)
+ ", expOutput:" + String(expFilter->output, 4)
//+ ", expFactor:" + String(expFilter->factor, 4)
); // Print input and output values to the serial monitor
}