Sunday, August 29, 2010

midi-player (atmega-16)

During my training, along with the calculator (see list of projects), i made a code for a digital midi-player based on atmega-16 as the micro-controller. MIDI implies musical instrument digital interface. The project had a keypad and a speaker . As the different keys of the keypad were pressed, the speaker produced the sound frequency corresponding to the notes 'sa' 're' 'ga' 'ma' etc. Each key was assigned a particular OCR value corresponding to the note frequency and thus the keys were coded to correspond to 'sa' 're' 'ga' etc buttons. Lets go step by step on this:

INTERFACE: The interface consists of a keypad and a

Saturday, August 14, 2010

single digit calculator(Atmega-16)

This was my first project after i got trained in embedded systems. The whole concept is simple. You just need to interface a 4x4 keypad matrix and a 16x2 LCD display to atmega-16 and you've got your own single digit calculator. Lets go step by step on tihs.....
INTERFACE: The interfacing is really simple. The only part that you need to build on your own is a 4x4 matrix keypad. For this, you need 16 push buttons (these are commonly available at any electronics shop), and solder them as shown in the figure. This matrix acts as the input device to Atmega-16. Once you have this, you can connect the 8 lines from the keypad (four from rows and four from columns) to any port of Atmega-16 ( The port that you use must have in built pull up facility. so it will be better if you use port A). Till this point the circuit has input mechanism by the keypad. Now we need an suitable output device for displaying the result etc. I used a 16x2 LCD (also commonly available) for this. The interface of LCD with Atmega-16 is really simple as illustrated in the embedded book by sourabh sankule. For the sake of convinience, here is a diagram on how to connect the LCD to the controller.
You are free to chose any port of Atmega for this connection. Upto this point, we have an input and output mechanism for our circuit. The only connections remaining after this are the Vcc and GND connections (i.e the power supply) and a 7805 (if youre using a power supply > 5V.). The final circuit looks something like this:

I have used PORT A for keypad interface and PORT B for LCD interface. As stated before, youre free to choose any of the ports of your choice.                                                             
Moving on with the project, now that the hardware level design is ready, you can either implement it on a general purpose PCB and solder the components yourself or design a PCB specially for this project. I will be uploading the board and schematic files for the PCB design also. The next step is to program the controller by developing a proper algorithm. The code given later is the code that i used. But i would suggest you to first go throuh the logic developed below and make a new code for yourself.
The only part of the code that you need to consider is the logic of interfacing the keypad. The other part of-course is the working of the calculator. The display of digits on the LCD is very simple as the compiler provides us with very useful functions like lcd_putsf(" ") etc. for the same. Lets first develop the logic for detection of key of keypad.
KEYPAD INTERFACE: An efficient way of using 16 switch matrix with only 8 lines of a port is to connect the switches as shown in the figure (It saves pins as directly using one pin for one switch would require 16 input pins of the controller but here we require only 8 pins). By connecting the switches in this manner, we save 8 pins of Atmega that can be used elsewhere. Now, the logic is as follows:
1. Make the rows as input and columns as output.
2. Since rows are made as inputs, make them in pull-up state by assigning 1 to the PORTA register bits corresponding to the rows. So now, by default, the rows are pulled up (i.e. have a value of logic '1' ) unless triggered by external source.
3. Since the columns act as output pins, make their value logic '0' by setting the corresponding bits of PORTA register to 0.
4. The result is that rows read logic '1' continuously as long as no switch is pressed. As soon as any switch is pressed, the corresponding row of that switch reads logic '0' now, as it gets connected to the corresponding column which is at logic '0'.
5. Store the row no. in a temporary variable and this variable gives us the row no. in which the switch is pressed.
6. Now the role of rows and columns is interchanged. Following the above points, we now get the column no. where the switch is pressed.
After this simple procedure, we get the row and column value of the switch. For ex, if 3rd switch in the first row is pressed, then we will get 1 as the row value and 3 as the column value. So, we have developed the logic to detect the switch pressed. The code for knowing the row and column value is as under:
          DDRA=0b11110000;        //rows are made output and columns as inputs
          PORTA=0b00001111;      //the rows are given 0 as the value and columns are made pull-up
          delay_ms(10);
          if(PINA.0==0)                  //if first column is 0 set y as 0  
          y=0;
          if(PINA.1==0)                  //if second column is 0 set y as 1
          y=1;
          if(PINA.2==0)
          y=2;
          if(PINA.3==0)
          y=3;
          DDRA=0b00001111;           //roles of columns and rows is reversed here onwards
          PORTA=0b11110000;
          delay_ms(10);
          if(PINA.4==0)
          x=0;
          if(PINA.5==0)
          x=1;
          if(PINA.6==0)
          x=2;
          if(PINA.7==0)
          x=3;
LOGIC FOR CALCULATOR: Now as the logic for detection of key of keypad is developed, we now can assign the numbers and operators of the calculator to the keypad. you can remember the assignment or stick tags on the keypad itself. I used the following code for the logic..

   while(1)        
        {
            while (1)
                   {
                              x=4;
                             DDRA=0b00001111;                          
                             PORTA=0b11110000;
                             delay_ms(10);                                      //this delay is necessary
                             if(PINA.4==0)                                     //else the code doesn't work
                               y=0;
                             if(PINA.5==0)
                               y=1;
                             if(PINA.6==0)                                    //coding for switch pad
                               y=2;
                             if(PINA.7==0)
                               y=3;
                             DDRA=0b11110000;
                             PORTA=0b00001111;
                             delay_ms(10);
                             if(PINA.0==0)
                               x=0;
                             if(PINA.1==0)
                               x=1;
                             if(PINA.2==0)
                               x=2;    
                             if(PINA.3==0)
                               x=3;                          //till here the code notes the coordinates of the key
                                                                //this code has been explained in the keypad section
                            
                             lcd_gotoxy(0,0);   
                             if(x==0&&y==0&&count==0)
                              {
                                lcd_putsf("0");                              //display that 0 is pressed
                                count++;
                                dummy=0;
                               // break;
                              }     
                              else if(x==0&&y==1&&count==0)
                              {
                                lcd_putsf("1");                              //display that 1 is pressed
                                count++;
                                dummy=1;
                              }
                              else if(x==0&&y==2&&count==0)
                              {
                                lcd_putsf("2");                              //display that 2 is pressed
                                count++;
                                dummy=2;
                              }
                              else if(x==0&&y==3&&count==0)
                              {
                                lcd_putsf("3");                              //display that 3 is pressed
                                count++;
                                dummy=3;
                              }
                              else if(x==1&&y==0&&count==0)
                              {
                                lcd_putsf("4");                              //display that 4 is pressed
                                count++;
                               dummy=4;
                              }
                              else if(x==1&&y==1&&count==0)
                              {
                                lcd_putsf("5");                               //display that 5 is pressed
                                count++;
                                dummy=5;
                              }
                              else if(x==1&&y==2&&count==0)
                              {
                                lcd_putsf("6");                              //display that 6 is pressed
                                count++;
                                dummy=6;
                              }
                              else if(x==1&&y==3&&count==0)
                              {
                                lcd_putsf("7");                             //display that 7 is pressed
                                count++;
                                dummy=7;
                              }
                              else if(x==2&&y==0&&count==0)
                              {
                                lcd_putsf("8");                             //display that 8 is pressed
                                count++;
                                dummy=8;
                              }
                              else if(x==2&&y==1&&count==0)
                              {
                                lcd_putsf("9");                            //display that 9 is pressed
                                count++;
                                dummy=9;
                              }
                              else if(x==2&&y==2&&count==0)
                              {
                                lcd_putsf("*");        //display that * is pressed
                                count++;                //as soon as * is pressed the previous data is erased
                                var1=dummy;        //from the lcd and its stored to be processed 
                                dummy=0;             //with the next value that we enter after this
                                lcd_clear();
                                multiply=1;                                
                                //break;
                              }
                              else if(x==2&&y==3&&count==0)
                              {
                                lcd_putsf("+          //display that + is pressed
                                count++;               //as soon as + is pressed the previous data is erased
                                var1=dummy;       //from the lcd and its stored to be processed
                                dummy=0;           //with the next value that we enter after this
                                lcd_clear();
                                addition=1;
                                //break;
                              }
                              else if(x==3&&y==0&&count==0)
                              {
                                dummy=0;
                                var1=0;
                                var2=0;
                                result=0;
                                lcd_clear();
                              }
                              else if(x==3&&y==1&&count==0)
                           {
                              lcd_putsf("/");       //display that / is pressed
                              count++;           //as soon as + is pressed the previous data is erased
                              var1=dummy;     //from the lcd and its stored to be processed
                              dummy=0;         //with the next value that we enter after this
                              lcd_clear();
                              divide=1;
                              //break;
                            }
                             
                              else if(x==3&&y==3&&count==0)
                              {
                                
                                lcd_clear();       //as soon as the = button is pressed, the two values
                                lcd_putsf("=");  //that were saved are operated upon and the result
                                count++;          //is displayed on the LCD.
                                var2=dummy;
                                dummy=0;
                                if(addition==1)
                                  {
                                    result=var1+var2;
                                    itoa(result,c);
                                    lcd_puts(c);
                                  }
                                if(divide==1)
                                  {
                                    result=var1/var2;
                                    itoa(result,c);
                                    lcd_puts(c);
                                  }
                                if(multiply==1)
                                  {
                                    result=var1*var2;
                                    itoa(result,c);
                                    lcd_puts(c);
                                  }      
                                //break;
                              }
                              break;
                              // else if(x==4)
                              //lcd_clear();
                   }
                
                   delay_ms(300);
                   if(count==1)
                   count=0;
          
       };
Having gone through the code you can have a general picture of how the things will be working. I have used a variable count that increases by one whenever any key is pressed on the keypad, be it operator or digit. At the end of the first while loop i check for the value of count. If the value is one, it means that a key was pressed and now the further action is going to take place. So i clear the value of count after every successful execution of loop in which a key was pressed. The variable dummy stores the value to be operated upon and whenever any operator is pressed, the value of dummy is stored in a variable named var1 and the value of dummy goes to one. After this again the second value automatically gets read from the keypad and gets stored in the variable dummy. Now as soon as the = operator is pressed, the dummy value goes to var2 and the result of the operation is carried out. the answer is displayed and all the variables and count value is cleared for next set of calculation. This code might take some while to grasp. Instead i would rather advice you to first create your own logical code and try it on the circuit. You can take this code as a backup.
Finally i must bring out some drawbacks of this project.....
1. The major drawback of this project was that it was single digit operable only. The calculations were limited to only one digit and that too positive integers.
2. Another drawback was that i was only able to come up with the addition, multiplication, subtraction and division of the two variables. I couldn't include more operations due to the time limit.
3. I personally feel that this code is not the best one for this project, so work out and let me know if a better and efficient code comes up.
This was all from my side on this project. Go on, make your own calculator and give your feedbacks on how things worked out for you!!!!