Skip to Content

How to filter digital and analog inputs on an Arduino PLC (Filter library)

January 16, 2019 by
How to filter digital and analog inputs on an Arduino PLC (Filter library)
Alejandro Jabalquinto

To read a digital or analog input reliably on an Arduino PLC, filter it in software. The Industrial Shields Filter library has two classes: DigitalFilter<T> accepts a new input state only after it has stayed stable for T milliseconds (debounce), and AnalogFilter<N, T> returns the average of the last N samples, taking one sample every T milliseconds.

This post explains why an input needs a filter, how each class works and how to use it with two examples for the M-Duino PLC: a digital filter on input I0.8 and an analog filter on input I0.10.

Why filter a digital or analog input?

When a digital input changes from HIGH to LOW, or from LOW to HIGH, the signal does not change cleanly. Mechanical contacts such as push buttons, relays and limit switches bounce, and the PLC can read several changes in a few milliseconds. If the program counts pulses or reacts to each change, these bounces are read as wrong values and cause errors.

Analog inputs have a similar problem: electrical noise and small variations of the sensor make the reading move from one value to the next. An average of several samples gives a more stable value.

ClassWhat it doesParameters
DigitalFilter<T>Debounce. The output changes only when the input keeps the new state for T ms.T: filtering time in ms
AnalogFilter<N, T>Moving average of the last N samples.N: number of samples. T: sample period in ms (0 takes samples as fast as possible)

Requirements

The Filter library was part of the Tools40 library. Since version 1.0.0 (January 2024) it is a separate library, under the LGPL license, and it works on all architectures.

Example 1: digital filter on input I0.8

The template parameter of DigitalFilter is the filtering time in milliseconds. In this example it is 500 ms.

#include <Filter.h>

// Digital filter (debounce)
// Filtering time: 500 ms. A new state is accepted only
// after it has stayed stable for 500 ms
DigitalFilter<500> filter;

void setup() {
  // Init Serial port
  Serial.begin(9600L);
  pinMode(I0_8, INPUT);
}

void loop() {
  // Read pin value
  int value = digitalRead(I0_8);

  // Filter it
  int filtered = filter.update(value);

  // Print the filtered value
  Serial.println(filtered);
}

How it works: while the input keeps the same value as the filtered output, the library restarts its timer. When the input changes, the output keeps the old value. The new value is accepted only if the input stays in it for 500 ms. Bounces and pulses shorter than 500 ms are ignored, and a real change appears at the output 500 ms after the last bounce. This works the same way from HIGH to LOW and from LOW to HIGH.

Choose the filtering time for your signal: a shorter time reacts faster, and a longer time rejects longer disturbances.

Example 2: analog filter on input I0.10

For an analog input, define the number of samples and the sample period in milliseconds:

#include <Filter.h>

// Analog filter (moving average)
// Number of samples: 10
// Sample period: 5 ms (with 0, samples are taken as fast as possible)
AnalogFilter<10, 5> filter;

void setup() {
  // Init Serial port
  Serial.begin(9600L);
  pinMode(I0_10, INPUT);
}

void loop() {
  // Read pin value
  int value = analogRead(I0_10);

  // Filter it
  int filtered = filter.update(value);

  // Print the filtered value
  Serial.println(filtered);
}

With AnalogFilter<10, 5> the filter keeps the last 10 samples, one every 5 ms, and update() returns their average. The average covers the last 50 ms of the signal. More samples or a longer period give a smoother value that follows changes more slowly.

The filter starts with all samples at 0. To start from another value, pass it to the constructor, for example AnalogFilter<10, 5> filter(512);.

Call update() in every loop and avoid delay() in the program: both filters use millis() to measure time. Create one filter object for each input you want to filter.

Both examples compile for the M-Duino 21+ and the M-Duino 58+ with the Industrial Shields AVR boards package 1.2.1.

FAQ about input filters on an Arduino PLC

Does the digital filter add a delay?

Yes. A real change reaches the output after the filtering time, 500 ms in the example. Use a shorter time if the program must react faster.

Can I filter several inputs?

Yes. Each filter object keeps its own state, so create one object for each input.

Is Filter the same as the Tools40 library?

The filter classes come from Tools40. They are now in the separate Filter library, with the same DigitalFilter and AnalogFilter classes.

​Search in our Blog

How to filter digital and analog inputs on an Arduino PLC (Filter library)
Alejandro Jabalquinto January 16, 2019
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.

PLC Comparison