Monday, 15 October 2012

Digital Filters on ARDUINO!!!!!

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; 


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-generation programming language. MATLAB attracts users from various backgrounds of engineering,science, and economics. We can determine FIR filter coefficients using fir1( ) command in MATLAB. Once we have coefficients, the rest part is simple. Now we are all set to write an arduino program for implementing digital filters.

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));
    }
}



Saturday, 7 July 2012

The SD Card


The next task is to interface a microSD with Arduino and play music files. The first thing to know about SD card is its pinout. 

SD CARD PINOUT
Te various pins are:
CS:         Chip Select
MOSI:   Master Out Slave In
GND:     Ground
VDD:      Supply pins
SCK:       Serial Clock
MISO:    Master In Slave Out
NC:          No Connect
IRQ:        Reserved

The SD card communicates using SPI mode of communication. Beginners dont have to worry about it much as the Arduino IDE provides a header file<SD.h> for the communication. All you need to know is the basic commands and the rest is IDE's job.

HARDWARE
For basic purposes , i don't think there is much of hardware required. All you need to do is connect MISO, MOSI, SCK and CS pins of SD to the respective pins of arduino. On arduino UNO we have: 
SCK:        pin 13
MISO:     pin 12
MOSI:     pin 11
CS:            pin 10
Also note that SD card works on 3.3V and Arduino on 5V, So we need to use an appropriate voltage divider circuit.The connection diagram is :


I had my own arduino shield with connections already made.
For playing music, we will need other cicuitary about which we'll discuss later.

SOFTWARE
I started with making .txt files and reading the ones already on it. I think <SD.h> is a very a nice library to help beginners read and write data to SD card. The SD library , by default creates an object called "SD". The various functions for this object are:
  1. begin()
  2. exists()
  3. mkdir()
  4. open()
  5. rmdir()
  6. remove()
These are a set of basic operations on SD card.
The various file operations are...
  1. available()
  2. flush()
  3. close()
  4. peek()
  5. print()
  6. pritln()
  7. seek()
  8. size()
  9. read()
  10. write()
  11. isDirectory()
  12. rewindDirectory()
The exact syntax of these functions is available on arduino playground
There are many test functions which give clear insight of how to play with SD Card.....

Saturday, 9 June 2012

Analog Clock and Thermometer on an Oscilloscope

This was our first major project at CEDT, NSIT. Using Arduino and two DACs, we had to generate an analog clock and thermometer on an oscilloscope in x-y mode. We started on 31st may, the day our 4th sem exams finished. Though Initially, it seemed quite tough. But it isn't that tough.



First of all our aim was to develop a shield with two DAC and a thermistor. We made it on 1st june. Then we started developing code for the project. We ,at first, tested the working of the DAC. It was working perfectly fine except the one or two minor flaws in it. Then made a sine and a cos wave. It was good but not fantastic. In xy mode, it presented a circle.


They weren't that bad. Because we were first to make it. The feeling was awesome. We have made something useful. The error was due to frequency considerations. The program was quite slow. It required further optimization. The solution was to write the code in AVR . The frequency of operation improved.  Next we moved on to drawing lines, we made a function which takes the angle in degrees and draws a line.
It was successfully implemented. We could now make most of the shapes on the Oscilloscope.

The next major thing was to implement the RTC. We couldn't use the delay function of the program as this would stop the rest of the program too. We didn't want that. So ,we had to use AVR timer interrupts. Luckily we got much of the help needed from the internet and were able to use the Timer of ATMega 168.

Now,we are almost done with our project. The video of our project is on youtube: http://goo.gl/HglPx