RC filter

If we want to smooth unwanted noises or annoying fluctuations of an electric signal we read from an analog sensor we have to create a filter.

Now we want to consider different methods to create a filter, both software and hardware, and to do this we first need to prepare a simple circuit to use to test them.

We will use a photoresistor (or light-dependent resistor if you prefer) as the main element for our tests. By the way we’ve found this tutorial by Adafruit very interesting: it contains a lot of information about this electric component, definitely worth reading!

scheme

Our siple circuit is composed of a:

fritzing circuit

Let’s start reading and plotting the voltage across the photoresistor. Here’s the code we are using:

#define PHOTO A0

void setup() {
  Serial.begin(9600);

}

void loop() {
  unsigned int value = analogRead( PHOTO );
  Serial.println( value, DEC);
  delay( 5 );
}

We use the Serial monitor to print the values from the analog input, and the Serial plotter tool to represent them in a more intuitive way.

serial plotter big variation

As we see from the graph above, when we change the light headings towards the photoresistor, the graph registers big variations in ADC values: greater the quantity of light, the lower the resistance value, the same the voltage measured on analog pin 0.

On the other hand, when we let everything untouched, even if the readings from the photoresistor seems to be quite stable, they present a lot of noise.

serial monitor

From the serial monitor we read continuosly changing values (even if they only change a bit), the same we see from the serial plotter graph.

serial plotter noise

Even though this behaviour seems to be different according to the type of light, we would like to filter out this noise in some way.

The software way

Let’s try first to use software to smooth our analog readings. The first method we will see is the array method.

The array method

As we learn from Arduino Smoothing tutorial, we can use an array to store consecutive readings and calculate their mean. This way we will always have an output that will be smoother than the input.

Here’s the code we are using (the same shown in the tutorial):

const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

#define PHOTO A0

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  int thisReading;
  for (thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[ thisReading ] = 0;
  }
}

void loop() {
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead( PHOTO );
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println( average, DEC);
  delay(5);        // delay in between reads for stability
}

Below two screenshots for both a light changing and stable environment. As we see noise now seems to be more controlled.

serial plotter changes

serial plotter noise

Maybe changing the size of the array could improve the filter power but at the same time, as we read from the tutorial introduction, it will create a delay

The higher the number of samples to keep track of, the more the readings will be smoothed, but the slower the output will respond to the input.

The bit shift method

Another way could be that of usign a bit shift. In other words using this method we are reducing the bit depth of the ADC signal, loosing some of the least significant bits of the original 10 bit sampled signal.

This is a very rough method that is also responsible of reducing the dynamic range of the sampled signal because of a reduction of the number of quatization levels.

Here’s the code:

#define PHOTO A0

void setup() {
  Serial.begin(9600);

}

void loop() {
  unsigned char value = analogRead( PHOTO ) >> 3;
  Serial.println( value, DEC);
  delay( 5 );
}

And here the plotter images:

serial plotter chages

The scale of the graph has been reduced; due to the bit shift operation the maximum value that the value variable could assume is lower than 1023 .

We can also test that the more bit we shift the readings to the left, the more squarewav-ish the graph will appear.

serial plotter noise

However if we take a look at the image above, it seems that the noise has been significantly reduced: this is because our graph now has a much lower resolution than before.

Because our noise is only responsible for little voltage variations, here we are no more able to see them.

The 1-sample delay method

Recently I’ve read about this method on Andy Farnell’s Designing Sound book. There’s a moment in chapter 10 when he describes this simple PureData patch:

PD float Low Pass Filter patch

This patch is a simple low pass filter that follows this filter equation:

The strenght of the filter is set by the ratio . Both and should be between and and add up to .

Let’s try this method in code with Arduino:

#define PHOTO A0

const float A = 0.1;
float B;

float currentValue, previousValue;

void setup() {
  Serial.begin(9600);
  B = 1.0 - A;
  previousValue = 0.0;
}

void loop() {
  currentValue = analogRead( PHOTO );
  previousValue = currentValue * A + previousValue * B;
  Serial.println( int(previousValue), DEC);
  delay( 5 );
}

Here we have and , so the filter ratio is . Here the images from the serial plot for both a light changing environment and a static light one.

serial plotter big chages

serial plotter noise

We also tried with different values for and : here and , for a filter ratio of

serial plotter big chages

serial plotter noise

In both cases as we see, noise seems to be little, and we also note that the smaller is, more this code seems to graph a signal similar to a capacitor charge and discarge cycle.

The second one is much slower than the first one, meaning that a smaller and a smaller filter ratio creates a more powerful low pass filter behaviour.

If you want to go deeper into the theory behind this patch, please refer to this post!

The hardware way

But what about doing a filter using hardware components instead of code? We have to realize a simple circuit variation, adding the so called RC filter:

RC filter scheme

The theory tells us that if we accurately calibrate the value of R and C, we can precisely define , the cut frequency (where ) as:

In this way, all variations on the input signal will be attenuated according to their frequency. Voltage variations with a frequency will be attenuated and will not be transferred to the output signal. On the other hand, signals with a frequency lower than will be left untouched.

RC filter graph


Let’s say we want to cancel all variations faster that , so we have to calculate the values for and accordingly.

For example, if we use and , we will obtain approximately an , as we wanted. Here’s our new circuit:

scheme

And here’s the Fritzing representation:

fritzing

We highly reccomend you to read the chapter 2 of the “Practical Elctronics for inventors” by Paul Sherz if you want more information about filters.

Here’s the Arduino Serial plotter images for great variations:

serial plotter big chages

and for no variation at all:

serial plotter noise

Despite our hopes, the noise is still present, as you can see in the last image. Even if this circuit would have completely cancelled the noise it actually seems to add more of it.

If you have a more clear understanding of this phenomenon, please feel free to leave a comment or contact us so we can improve this article adding new and significant clarification.

Maybe the solution it to use an hybrid approach and to create both an hardware RC and a software RC filter. We will let you know in our future experimentations.


If you find this article useful and you like it, please leave a comment below: let us know what do you think about it, we'd really appreciate it. Thank you very much and, as always, stay tuned for more to come!