My next task is to implement Digital filters on Arduino........
We live in a analog world. Everything "Natural" around us is analog in nature. But ,we being Engineers,love the Digital way. So in order to communicate with digital world, we need Sensors and ADCs. Sensors convert various quantities around us into analog electrical signals which are digitized using ADC. But during this Analog to digital conversion noise creeps into our system and it becomes necessary to remove that noise and extract only the required signals. Then comes into existence the filters.
Digital filters as the name suggests filters digitally.Or in other words it filters digital signals. Basically, it is use to implement a filter in software. This has an advantage over normal analog signals, that their properties can be changed by just changing the program. In contrast, to change the properties of an analog filter, we need to change the entire filter design.Then comes the importance of digital filters. Digital Filters are omnipresent. Any system which interfaces with the outside world or use sensors ,use s filters , most of which are digital.
A digital filter is characterized by its transfer function. Mathematical analysis of the transfer function can describe how it will respond to any input.
The transfer function for a linear, time-invariant, digital filter can be expressed as a transfer function in the z-domain;
A digital filter is characterized by its transfer function. Mathematical analysis of the transfer function can describe how it will respond to any input.
The transfer function for a linear, time-invariant, digital filter can be expressed as a transfer function in the z-domain;
where the order of the filter is the greater of N or M.
This is the form for a recursive filter with both the inputs (Numerator) and outputs (Denominator), which typically leads to an IIR infinite impulse response behaviour, but if the denominator is made equal to unity i.e. no feedback, then this becomes an FIR or finite impulse response filter.
My aim is to implement Digital Filters on Arduino. I wanted to make FIR filters(all types). For an FIR filter transfer function has denominator equal to unity. The coefficients in the transfer function of equation ..1 can
be determined using MATLAB....
MATLAB (MATrix LABoratory) is a numerical computing environment and fourth-
The program is:
/*
This is Program to implement three dgital filters:
(1) 200Hz-600Hz
(2) 600Hz-1200Hz
(3) 1200Hz-2400Hz
The output can be verified using a function generator and reading relative magnitudes of output on Serial Monitor and on Oscilloscope if you have DACs
*/
#define M 50
#define N 65
#include<avr/io.h>
#include<avr/delay.h>
#include <util/delay.h>
uint16_t x[N]; //Samples
// Filter coefficiants to implement Three Digital Filters
int32_t b1[N]={1,0,-3,-5,-7,-8,-5,0,8,17,25,28,23,6,-25,-72,-134,-205,-280,-349,-401,-425,-413,-360,-262,-124,44,231,418,589,725,813,844,813,725,589,418,231,44,-124,-262,-360,-413,-425,-401,-349,-280,-205,-134,-72,-25,6,23,28,25,17,8,0,-5,-8,-7,-5,-3,0,1};
int32_t b2[N]={-3,-2,3,12,22,27,20,0,-30,-58,-69,-55,-21,14,29,11,-25,-45,-9,101,256,382,388,214,-128,-538,-855,-923,-668,-139,493,1001,1196,1001,493,-139,-668,-923,-855,-538,-128,214,388,382,256,101,-9,-45,-25,11,29,14,-21,-55,-69,-58,-30,0,20,27,22,12,3,-2,-3};
int32_t b3[N]={0,11,15,-4,-23,-14,6,0,-9,30,72,18,-89,-92,5,22,-39,45,240,174,-200,-368,-92,107,-80,-25,662,929,-288,-1827,-1380,998,2406,998,-1380,-1827,-288,929,662,-25,-80,107,-92,-368,-200,174,240,45,-39,22,5,-92,-89,18,72,30,-9,0,6,-14,-23,-4,15,11,0};
uint16_t a;
uint16_t i;
void InitADC() // Function to initialise ADC Channel
{
ADMUX=(1<<REFS0);
ADMUX&=~((1<<REFS1)|(1<<ADLAR)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0));
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
uint16_t ReadADC(uint8_t ch) // Function to read value of ADC
{
ch=ch&0b00000111;
ADMUX|=ch;
ADCSRA|=(1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
//_delay_ms(1000);
ADCSRA|=(1<<ADIF);
return(ADC);
}
void setup() //Setup Function to intialise ADC and Serial Communication
{
DDRC=0x00; //PORTC as INPUT
DDRD=0xFF; //PORTD is OUTPUT
DDRD=0xFF;
for(i=0;i<N;i++)
{
InitADC();
a=ReadADC(4);
x[i]=a;
}
Serial.begin(9600);
}
int32_t num1=0,num2=0,num3=0,y1[M],y2[M],y3[M],sum1=0,sum2=0,sum3=0,ans1=0,ans2=0,ans3=0; // Various variables to determine Y-OUTPUT
void loop() //Loop Function
{
for(int i=0;i<M;i++)
{
num1=0; //cumulative summation of filter1
num2=0; //cumulative summation of filter2
num3=0; //cumulative summation of filter3
for(int j=0;j<N;j++) // taking Samples
{
InitADC();
x[j]=ReadADC(4);
}
for(int k=0;k<N;k++) //Convolution
{
num1+=b1[k]*x[N-1-k]; //Filter1
num2+=b2[k]*x[N-1-k]; //Filter2
num3+=b3[k]*x[N-1-k]; //Filter3
}
y1[i]=num1/10000; //Normalisation
y2[i]=num2/10000;
y3[i]=num3/10000;
}
//Now take RMS values
for(int i=0;i<M;i++)
{
sum1+=y1[i]*y1[i];
sum2+=y2[i]*y2[i];
sum3+=y3[i]*y3[i];
}
sum1/=M;
sum2/=M;
sum3/=M;
ans1=sqrt(sum1);
ans2=sqrt(sum2);
ans3=sqrt(sum3);
// Printing them on Serial Monitor
Serial.print("200-600Hz::");
Serial.println(ans1);
Serial.print("600-1200Hz::");
Serial.println(ans2);
Serial.print("1200-2400Hz::");
Serial.println(ans3);
//Checking the OUTPUT on Oscilloscope
dacx(ans1);
dacy(ans2);
}
void dacx(unsigned char a) // Function to write values on one of the DACs DACx
{
byte k=0;
for(unsigned char i=0;i<2;i++)
{
k=a&(1<<i);
if(k)
PORTB|=(1<<i);
else
PORTB&=~(1<<i);
}
for(unsigned char i=0;i<6;i++)
{
k=a&(1<<(i+2));
if(k)
PORTD|=(1<<(7-i));
else
PORTD&=~(1<<(7-i));
}
}
void dacy(unsigned char a) // Function to write values on one of the DACs DACy
{
byte k=0;
for(unsigned char i=0;i<4;i++)
{
k=a&(1<<i);
if(k)
PORTC|=(1<<(3-i));
else
PORTC&=~(1<<(3-i));
}
for(unsigned char i=0;i<4;i++)
{
k=a&(1<<(i+4));
if(k)
PORTB|=(1<<(5-i));
else
PORTB&=~(1<<(5-i));
}
}
Hi, i got a question on how to get the filter coefficiants? let say if i wanted a filter of 20-100Hz, 2400Hz- 4800Hz, etc etc... hope to hear from you..
ReplyDeleteHello Ong..!!
ReplyDeleteI used a function 'fir1' in MATALB.
The syntax of this function is
b = fir1(n,Wn)
b = fir1(n,Wn,'ftype')
b = fir1(n,Wn,window)
b = fir1(n,Wn,'ftype',window)
b = fir1(...,'normalization')
DESCRiPTION: fir1 implements the classical method of windowed linear-phase FIR digital filter design. It designs filters in standard lowpass, highpass, bandpass, and bandstop configurations. By default the filter is normalized so that the magnitude response of the filter at the center frequency of the passband is 0 dB.
b = fir1(n,Wn) returns row vector b containing the n+1 coefficients of an order n lowpass FIR filter. This is a Hamming-window based, linear-phase filter with normalized cutoff frequency Wn. The output filter coefficients, b, are ordered in descending powers of z.
If Wn is a two-element vector, Wn = [w1 w2], fir1 returns a bandpass filter with passband w1 < ω< w2.
If Wn is a multi-element vector, Wn = [w1 w2 w3 w4 w5 ... wn], fir1 returns an order n multiband filter with bands 0 < ω< w1, w1 < ω< w2, ..., wn < ω< 1.
b = fir1(n,Wn,'ftype') specifies a filter type, where 'ftype' is:
'high' for a highpass filter with cutoff frequency Wn.
'stop' for a bandstop filter, if Wn = [w1 w2]. The stopband frequency range is specified by this interval.
'DC-1' to make the first band of a multiband filter a passband.
'DC-0' to make the first band of a multiband filter a stopband.
fir1 always uses an even filter order for the highpass and bandstop configurations. This is because for odd orders, the frequency response at the Nyquist frequency is 0, which is inappropriate for highpass and bandstop filters. If you specify an odd-valued n, fir1 increments it by 1.
b = fir1(n,Wn,window) uses the window specified in column vector window for the design. The vector window must be n+1 elements long. If no window is specified, fir1 uses a Hamming window (see hamming) of length n+1.
b = fir1(n,Wn,'ftype',window) accepts both 'ftype' and window parameters.
b = fir1(...,'normalization') specifies whether or not the filter magnitude is normalized. The string 'normalization' can be the following:
'scale' (default): Normalize the filter so that the magnitude response of the filter at the center frequency of the passband is 0 dB.
'noscale': Do not normalize the filter.
The group delay of the FIR filter designed by fir1 is n/2.
Apart from this, you can also use GUI functions available in MATLAB. You can always use it. They also give same coefficients.
Hope it helps..!!
Hi, my question is if I want to implement IIR filter, how should I do that?
ReplyDeletewhat is your sampling frequency?
ReplyDeleteThe sampling freq is the maximum achievable by an Arduino running at 16MHz. I did not give any delay between samples. So the time between two samples is the time to execute instructions between two sampling instructions.
ReplyDeletea small correction : the time between two samples is not the "time to execute instructions between two sampling instructions", which is very small if your cas, but it is 13 cycles of adc frequency, this frequency being the processor freq (16MHz) divided by a divider between 1 and 128. So I would suspect that your sampling rate is not exactly what you thought. Maybe you could be sure of this by outputing 1 and 1 on a digital pin that you can observe with your scope
ReplyDeleteVery, very nice work anyway !
Very nice work. He used a prescaler of 128 for his ADC clock. It's in his InitADC() routine. That's 125kHz sampling frequency
DeleteI am sorry. You are correct.
DeleteAnd Thank you.
hello, i have a project in which i need to to deteced a car horn frequency range 2400-2500Hz but i didn't get the fir1 function or how to enter my parameters in order to get cofficient [N,WN,bandpass,]
ReplyDeleteis it right?
and also how to enter WN i want 2400-2500HZ
thank you
regards
If you are using MATLAB, you can read this: http://in.mathworks.com/help/signal/ref/fir1.html , this link explains the usage of fir1 function with examples.
ReplyDeleteFor ocatve, which is an open source software, read this:
http://octave.sourceforge.net/signal/function/fir1.html
How can we implement the filter which has both num and den ???
ReplyDeleteHello,
ReplyDeleteFor my ECG project , I want to remove powerline interference noise from ecg signal.it frequency is 50hz.i want to do it on arduino. How can I do that..how can I implement a band stop filter using arduino
Thank You and that i have a tremendous offer: What Do House Renovations Cost house renovation process
ReplyDelete