Implementation of FIR and IIR Filters using Arduino

Hey everyone!

I know some of this stuff has been spoken about in many posts, but indirectly and only in bits and pieces. I was wondering if I could get help with this, it's my class project.

So firstly I need to input signals such as audio or ECG waves (any signals basically) into the Arduino. I've already looked up on ways to do this, (i) audio by using an op-amp circuit to make the limits 0-5 V and can then be fed into the Arduino for processing, (ii) ECG signals (or any signals) can be inputted through MATLAB, I'm guessing.

Then comes the processing part. I read about how to implement filters in Arduino using coefficients calculated from MatLab, and then coding the Arduino to filter the signals a certain way. Also I could somehow output the filtered signals through and Analog pin to a speaker to show my professor the filtered signal, or use Processing to map it on the screen? :-\

But despite all this, I just don't know where to start and how to go about the project. I don't know if what I'm doing is correct even. :frowning:

Maybe a push in the right direction would really make things clear for me.

Any kind of help would be really great! :smiley:

ECG signals (or any signals) can be inputted through MATLAB, I'm guessing.

Why are you guessing? Have you any evidence that MATLAB can output an ECG signal (whatever that is)?

It hardly makes sense to discuss ways of "filtering" the data when you don't really seem to have a clue what kind of data you will be dealing with OR how you want to "filter" the data.

The Arduino can directly read signal voltages from the analog pins, but it is not fast enough to read and filter audio signals in real time.

You could use another Arduino or a signal generator to create a much more slowly changing signal (for example, a low frequency square wave), and filter that.

I would look at microprocessors which have hardware to directly support FIR filters such as Microchips dsPIC series
http://www.microchip.com/design-centers/16-bit/products/dspic33f-e

or Texas DSP

depending upon level of complexity

PaulS,

I'm not guessing, let me rephrase. I can produce signals from MatLab that can be then fed into the Arduino via USB using the MatLab interface.

The kind of signals I wish to deal with are trying to imitate daily signals (for the sake of the project), such as speech and music. I have to load those signals onto the arduino, and filter it using FIR or IIR filters.

And an ECG (Electro Cardio Graph) signal can be made by summing it's individual PQRST segments.

jremington,

Yes it can read analog voltages, but how do I connect an AUX cable to a jumper wire that's connected to an analog input pin? I was trying to somehow transfer audio from my computer via USB, but there doesn't seem to be an application that can do that.

Also, is there any way to "slow down" a real-time audio signal to ensure no data gets lost in the 10-bit ADC?

horace,

Apparently I need to use an Arduino. Also, I don't think I'd require a DSP if I was somehow able to make the audio signals more processable before feeding them into the board.

if you do a web search for arduino dsp and arduino audio dsp you will get plenty of links which may help
why do you have to use an arduino?

Sounds like homework. When is our assignment due? If you already have the data in Matlab then processing it there is going to be much easier, so doing it on an Arduino is make-work.

The Arduino can sample fast enough for basic audio processing. You don't need to slow it down. The normal analogRead() works at about 10kHz if you aren't trying to do any processing during the data-collection time. With some effort, you can get the sample frequency much higher and do some limited processing (like an FIR or IIR) at the same time. The real limitation to sample-then-process is the small amount of memory on the Arduino. High sample rates will chew up all the available SRAM in a fraction of a second.

I use http://t-filter.engineerjs.com/ to design my FIR filters. It's very easy to use that to visualise the result of pass-bands and stop-bands. Then you click the "source code" button and it has everything already programmed in C for you to copy-paste into your Arduino sketch. For some of my projects, I re-write it into a C++ class because it's so easy to do and makes it easier to use the filter in a real project.

If you're already using Matlab to generate the coefficients, then just copy-paste that into the code provided by t-filter. That will get you started.

1 Like

such as speech and music. I have to load those signals onto the arduino, and filter it using FIR or IIR filters.

Not a project for the standard Arduino.

Since you already have to go to a higher end Arduino, consider something like the Raspberry Pi. Or just use MATLAB on the PC.

MorganS,

Thank you so much! The link you sent helped me a lot. My assignment is due in a month's time, I know it's a lot of time but getting the parts together and preparing a report while simultaneously "trying" not to bunk classes is going to be a drag.

MorganS:
With some effort, you can get the sample frequency much higher and do some limited processing (like an FIR or IIR) at the same time.

I have a small doubt, what would be the difference in implementation between an IIR and FIR filter of the same bandwidth?

MorganS:
High sample rates will chew up all the available SRAM in a fraction of a second.

Is there any way for the Arduino to spit out the data elsewhere before getting filled up?

jremington,

jremington:
Not a project for the standard Arduino.

I don't need real speech and audio signals, I'll be making them somewhere else just to imitate a real-time signal.

OK, so you're just processing samples as they come in over Serial and you can control that rate so the Arduino doesn't get overloaded. Then you don't have any problem with limited storage. A typical FIR or IIR filter might use 20-50 storage locations, which would probably be 16-bit integers or 32-bit floats. That's not a very large amount of storage at all.

Well, an FIR filter would be implemented by storing the last M samples of the input and then running the filter over those samples when required. (See the t-filter example.) An IIR would run the filter on each incoming value and store M result values. The IIR would usually also store M input values so it would seem that it needs twice as much memory but usually M is much smaller for an IIR of equivalent performance.

Where is the data supposed to go after it's processed? Back to Matlab on Serial? Save it on an SD card?

MorganS:
OK, so you're just processing samples as they come in over Serial and you can control that rate so the Arduino doesn't get overloaded.

Yes, and the method of inputting the data is still unclear. I could get an AUX cable jack and input sound directly from the computer, or I could just pass a signal to the Arduino through a MatLab interface. I'm not sure which one to do.

MorganS:
Where is the data supposed to go after it's processed? Back to Matlab on Serial? Save it on an SD card?

If it could be displayed somehow, that would be great. Maybe I could use Processing to show the filtered signal on the computer screen?
If that's not possible I can still output it to MatLab and show my professor that as well. But a display of some kind would be perfect for presentation.

Addition:

Do you know any code examples where filter coefficients are used to implement a filter in Arduino, both as an FIR and an IIR filter? That would really clear up my concepts, I only seem to know the theory of IIR and FIR but nothing about actual implementation.

sam_andrew:
Do you know any code examples where filter coefficients are used to implement a filter in Arduino, both as an FIR and an IIR filter? That would really clear up my concepts, I only seem to know the theory of IIR and FIR but nothing about actual implementation.

There may be optimizations possible with specific filter coefficients, but a direct implementation of a FIR filter implementing the convolution is straightforward.

 y=0; //will contain next filter output
for (i=0; i<LEN; i++)
  {
    y = y + w[i]*x[i];  // w is vector of FIR coefficients, x is vector of recent input samples
  }

IIR is left as an exercise for the student, but it isn't much different.

Sending out an analog signal containing digital data is a waste of time. You would only do that if you needed to actually use the analog input (say, for a microphone) but you wanted to test with a known input generated from Matlab.

Matlab can talk to COM ports. It can send the data out one sample at a time, then wait for the result to come back. Have Matlab store the value or even use its charting functions.

If you wanted to use Processing for this, you can't have Matlab send the data direct to the COM port, because you can't split transmit and receive to different programs. Just make a data file with the data from Matlab and have Processing read it out to the Arduino then receive the result.

Well, I've already shown an example of the FIR filter. Here's a complete working example of an IIR.

/*********************************************************************
 * Single Pole IIR filter
 * Author: Morgan
 * Date: 26 Sept 2017
 * 
 * Purpose: Demonstrate a working IIR filter using Serial
 ********************************************************************/
//Serial.parseFloat is useful, but distinguishing a timeout from a real number is difficult
//We need to explicitly set its timeout (so we know what it is) and then see if it took that long
//If it did take that long, then we can assume that there was no number.
#define MyTimeout 500 //milliseconds

void setup() {
  Serial.begin(9600);
  while(!Serial && millis()<5000) {
    //wait up to 5 sec for Serial connection (Teensy/Leonardo only)
  }
  Serial.println("IIR filter demo version 1.0");
  Serial.println("Give me numbers, one on each line and I'll give you an IIR filtered output (one on each line.)");

  Serial.setTimeout(MyTimeout);
}

void loop() {
  unsigned long StartTime = millis();
  float inputVal = Serial.parseFloat();
  if(inputVal !=0 || millis() - StartTime < MyTimeout) {
    //we got a valid input from parseFloat()
    float outputVal = filter(inputVal);
    Serial.println(outputVal);
  }
}

float filter(float inputVal) {
  //implement the IIR filter
  //reference: The Scientist and Engineer's Guide to Digital Signal Processing By Steven W. Smith, Ph.D.
  //  http://www.dspguide.com/ch19/2.htm
  //This is a "single pole" filter. 

  //x is the decay between adjacent samples. Choose any number between 0 and 1 (except 1).
  const float x = 0.86; 
  static float outputVal = 0; //make it static so it's stored for the function to use again the next time it's called
  
  outputVal = outputVal * x + inputVal * (1-x);
  return outputVal;
}

There's some complexity in this to get around the limitations of the parseFloat() method but the rest of it should be easy enough to understand.

I don't need real speech and audio signals, I'll be making them somewhere else just to imitate a real-time signal.

So what is the point of using an Arduino? Any computer can do this, using the exact same code.

It's a homework assignment. That's the point.

Hopefully the professor's plagiarism filter will find the final submission sufficiently different from my code above.

MorganS:
If you wanted to use Processing for this, you can't have Matlab send the data direct to the COM port, because you can't split transmit and receive to different programs.

Okay so I now understood that I need to have MatLab or Processing input data into the Arduino and once the Arduino sends the processed data back, the same software must display it. I'll do some reading on how to do this. But do you have any thoughts on which would be better, MatLab or Processing?

Also just for clarification, once I get the filter coefficients, I make a matrix of say N values and use each value individually to get a response (by multiplying the corresponding input for FIR, or inputs and output for IIR). Is this correct?

I'll try developing a code if this logic is right.

MrMark:
IIR is left as an exercise for the student, but it isn't much different.

The change would be "y = y[i]*w[i] + x[i]*w[i]"

Is this logic correct?

No, that would be a terrible filter. You need different coefficients for the x and y components.

You also can't have a scalar variable called y as well as a vector (array) called y[].

output = y[i]*w[i] + x[i]*v[i];

Don't forget to save output into the correct location in the y[] array.

The other problem with this simplistic code is that it assumes you're always storing values from 0 to LEN, whereas a real filter implementation would have to treat the vectors as circular buffers.

Okay so different coefficients for x and y. Got it. And these get stored into an array.

Doubt, I understand how to find the filter coefficients for an FIR filter since I only need to get the x coefficients. But for an IIR filter, how do I get the coefficients for x and y? Would the x coefficients be the same as they were for an FIR filter of equivalent performance? And how would the y coefficients vary from these?

To implement a circular buffer technique, we could have the nth value of the circle to be spit out to MatLab every cycle?

For example, if the circle was of four values. Every time the next value gets added to the circle, the oldest value needs to be discarded. Instead of discarding, maybe it could be sent back to MatLab?

I'm curious what is the context for this exercise.

You've described a project that touches on a number of different subject areas, which I would expect to be separate classes, including analog signal conditioning, microcontrollers and general coding, and digital signal processing. It might be a senior project of some sort hence multiple disciplines, but I'm not seeing much evidence of passing understanding of any of these topics. Trying to learn this stuff via a (typically) short response interactive forum primarily dedicated to only one of these subjects seems inefficient at best.

I'm curious what is the context for this exercise.

I am too, but the class instructor may be even more clueless than the students.

In total, the exercise is rather pointless.