Tuesday 15 January 2013

♫♫♫ Playing Music on Arduino and AVR's ATTiny13 ♫♫♫


This blog is all about mixing MUSIC and Microcontrollers. Arduino can play tunes  using just one speaker and nothing else(yes!!! you got it right...just one speaker). Although, we can add a MOSFET to increase the current. The circuit is simple and is:



or if you don't want to use a transistor connect a speaker(or a piezo buzzer) between Arduino pin 10 and GND. Now the code part:


/*
* It sends a square wave of the appropriate frequency to the piezo, generating
* the corresponding tone.
*
* The calculation of the tones is made following the mathematical
* operation:
*
*       timeHigh = period / 2 = 1 / (2 * toneFrequency)
*
* where the different tones are described as in the table:
*
* note frequency period timeHigh
* c         261 Hz         3830 1915
* d         294 Hz         3400 1700
* e         329 Hz         3038 1519
* f         349 Hz         2864 1432
* g         392 Hz         2550 1275
* a         440 Hz         2272 1136
* b         493 Hz         2028 1014
* C    523 Hz        1912 956
*

*/
/* Header File*/
#include<util/delay.h>

/* Global Variables*/
int speakerPin = 10;                                              //Speaker is connected to DIGITAL PIN 10 on Arduino
int length = 11;                                                  //The number of notes in the song
char notes[] = "ccggaagffeeddc ";                                  //These are the notes for tune "HAPPY BIRTHDAY"
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };    //(beats*tempo) signifies duration for which a particular note is played
int tempo = 280;                                                  //tempo specifies the speed at which the signal is played.
                                                                  //To increase the speed, decrease the value of tempoand vice versa

/* Function Definitions*/

/*
  This function generates a tone of frequency
  specified by playNote function.
*/
void playTone(int tone, int duration) 
{
  for (long i = 0; i < duration * 1000L; i += tone * 2) 
  {
    digitalWrite(speakerPin, HIGH);
    _delay_us(tone);
    digitalWrite(speakerPin, LOW);
    _delay_us(tone);
  }
}

/* 
   This functions reads one note at a time,
   determines the T_HIGH(high time) corresponding to
   note. for example: 'c' corresponds to a frequency
   of 261Hz. Thus time period, T=1/261=3830usec. For
   simplicity, we consider duty cycle of 50%.
   T_HIGH=T_LOW=T/2
*/
void playNote(char note, int duration) 
{
  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
  
  // play the tone corresponding to the note name
  for (int i = 0; i < 8; i++)
  {
    if (names[i] == note) 
    {
      playTone(tones[i], duration);
    }
  }
}

void setup() 
{
  pinMode(speakerPin, OUTPUT);
}

void loop() 
{
  for (int i = 0; i < length; i++) {
   if (notes[i] == ' ') 
   {
      _delay_ms(beats[i] * tempo); // rest
   }
   else 
   {
      playNote(notes[i], beats[i] * tempo);
   }
    _delay_ms(tempo / 2);  // pause between notes
  }
}


The code is well commented and easy to understand. 
Here, we define an array called "notes" and "beats":

char notes[] = "ccggaagffeeddc ";
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };

These are the notes for "Happy Birthday" song and beats basically signifies the duration of a particular note(the relation being, duration=beats*tempo). 

The variable "length" specifies the length or the number of notes in the song.
int length = 11;

Here we also have two user defined functions called :

void playTone(int tone, int duration)
void playNote(char note, int duration)

The function playNote() reads one note at a time, determines the T_HIGH(high time) corresponding to   note. for example: 'c' corresponds to a frequency of 261Hz. Thus time period, T=1/261=3830usec. For   simplicity, we consider duty cycle of 50%.Thus T_HIGH=T_LOW=T/2=1915usec.

The function playTone() generates a tone of frequency specified by playNote function.

void setup() initialises pin 10 of Arduino as output.

void loop() takes one note at a time and sends it to function playNote().

One can also generate any sound/tone of choice just by changing 3 lines in the code.
1) char notes[]
2) int beats[]
3) int length

You can play "Twinkle Twinkle little stars" by setting
1) char notes[]={“ccggaagffeeddc “};
2) int beats[]= { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
3) int length=15;

I will post the video soon....!!!!
Till then enjoy....

*****************************************************************

The above code can also be implemented using 16-bit timer and counter of ATMEGA168/328. The timer is configured in fast PWM mode using WGM3:0= 15. For entire code

No comments:

Post a Comment