Tocando músicas com o Arduino

Seguindo a série de tutoriais usando o Arduino, hoje vou demonstrar como usar speakers para produzir sons. Para quem não sabe o que são e para que servem os speakers, aí vai uma breve explicação: Speakers são nada mais nada menos que auto-falantes, (mini auto-falantes). Eu disse que seria uma breve explicação!!!

Pois bem, com um speaker existe a possibilidade de criar sistemas de hardware que podem emitir alertas, tocar musicas, irritar os familiares, amigos entre muitas outras utilidades. Com o uso do Arduino essas possibilidades aumentam a partir do momento que você descobre como combina-los.

Para esse tutorial vamos precisar de:

1 Placa Arduino.
1 Speaker (No meu caso vou usar um de 8Ω ou 0.3w, retirado de um aparelho de fax antigo).
1 Resistor 1000Ω (Opcional).
1 Led (Opcional).

Com os componentes em mão, precisamos conhecer um pouco sobre as notas musicais e como elas são representadas através de códigos no Arduino.
Sabemos que existem 7 notas musicais básicas, também chamadas de notas naturais, são elas: Dó, Ré, Mí, Fá, Sol, Lá, Sí, representadas respectivamente por C, D, E, F, G, A, H. Logo temos:

C (dó natural)
D (ré natural)
E (mi natural)
F (fá natural)
G (sol natural)
A (lá natural)
H (si natural)

Existe ainda variâncias dessas notas as quais são chamadas de Bemol e sustenido que são representadas por:

Ces (dó bemol), C (dó natural), Cis (dó sustenido)
Des (ré bemol), D (ré natural), Dis (ré sustenido)
Es (mi bemol), E (mi natural), Eis (mi sustenido)
Fes(fá bemol), F (fá natural), Fis (fá sustenido)
Ges (sol bemol), G (sol natural), Gis (sol sustenido)
As (lá bemol), A (lá natural), Ais (lá sustenido)
B (si bemol), H (si natural), His (si sustenido)

Agora que conhecemos um pouco das notas musicais, vamos ver como elas são representadas via código de programação. As notas musicais podem ser obtidas em hardware através de ondas quadradas que possuem uma constante V = +5v e frequências que podem ser modificadas ao longo do percurso em que a onda é gerada. Sim, parece um pouco difícil de entender, mas na verdade não é. Ao final do tutorial existe 4 links onde podem ser encontradas informações sobre isso.

Na tabela abaixo podemos ver as notas e suas respectivas frequências, peridodo, e tempo em que ficam no estado HIGH (ligada).

Até agora foi só teoria, então vamos com um pouco de pratica. A montagem do circuito é muito fácil, veja a figura abaixo:

Esse é um dos esquemas que você pode montar para tocar sons. É tão simples que até minha vó (83 anos) conseguiu montar. rsrsrsrs. Outro possivel esquema é este, no qual eu utilizo um resitor para controlar o volume do som e um led para ficar piscando conforme as notas são tocadas.

Os códigos que serão mostrados logo abaixo são utilizados no primeiro esquema (aquele que a vovó montou), caso queria utiliza-los no segundo esquema deverá adaptar conforme a necessidade para poder acender o led.

Nesse primeiro exemplo de código vamos há uma breve demonstração que foi retirada da pagina Arduino Playground.

int speakerPin = 11;

int length = 15; // número de notas
char notes[] = "ccggaagffeeddc "; // espaços representam pausas
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
int tempo = 300;

void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(tone);
  }
}

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

  // toque o tom correspondente ao nome da nota
  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(beats[i] * tempo); // rest
    } else {
      playNote(notes[i], beats[i] * tempo);
    }

    // pausa entre notas
    delay(tempo / 2);
  }
}

Para podermos usar o código abaixo é necessário a inclusão de uma biblioteca chamada pitches.h. Essa biblioteca facilita a escrita de códigos correspondentes as notas musicais pois ja define em seu escopo a maior parte delas. Faça o download e logo após inclua na pasta das bibliotecas do arduino. No linux a pasta encontra-se em /usr/share/arduino/libraries.

Esse código é um pouco mais aprimorado e faz a alegria de todos NERDS de plantão. Copie, cole na IDE do arduino faça o upload e descubra porque. O código foi escrito por Ricardo Caetano e pode ser encontrado AQUI.

/***************************************************\
| MUSICBOX DUINO - Classic game theme               |
|                           |
|                                                   |
| NEECduino with ATmega328:                         |
|                                                   |
|  -> 8-ohm speaker from digital pin 10 to ground;  |
|                                                   |
| Created on 5 May 2011 by Ricardo Caetano          |
\***************************************************/

#include "pitches.h"

// Indica a duração das notas, ex: colcheia -> tr = 4, ...
#define se 6
#define tr 4
#define co 3
// Define a velocidade de reprodução, quanto menor mais rápido...
#define SMbpm 150

// As notas...
int tonesA[] = {NOTE_E5, NOTE_E5,0,NOTE_E5,0, NOTE_C5, NOTE_E5,0, NOTE_G5,0,0, NOTE_G4,0,0};
int tonesB[] = {NOTE_C5,0,0, NOTE_G4,0,NOTE_E4,0,0,NOTE_A4,0, NOTE_B4,0,NOTE_AS4, NOTE_A4,0,NOTE_G4,NOTE_E5,NOTE_G5,NOTE_A5,0,NOTE_F5,NOTE_G5,0,NOTE_E5,0,NOTE_C5,NOTE_D5,NOTE_B4,0};
int tonesC[] = {NOTE_C3,0,NOTE_G5,NOTE_FS5,NOTE_F5,NOTE_DS5,NOTE_C4,NOTE_E5,NOTE_F3,NOTE_GS4,NOTE_A4,NOTE_C5,NOTE_C4,NOTE_A4,NOTE_C5,NOTE_D5};
int tonesD[] = {NOTE_C3,0,NOTE_G5,NOTE_FS5,NOTE_F5,NOTE_DS5,NOTE_G3,NOTE_E5,0,NOTE_C6,0,NOTE_C6,NOTE_C6,0,NOTE_G3,0};
int tonesE[] = {NOTE_C3,0,NOTE_DS5,0,0,NOTE_D5,0,NOTE_C5,0,0,NOTE_G3,NOTE_G3,0,NOTE_C3,0};
int tonesF[] = {NOTE_C5,NOTE_C5,0,NOTE_C5,0,NOTE_C5,NOTE_D5,0,NOTE_E5,NOTE_C5,0,NOTE_A4,NOTE_G4,0,NOTE_G2,0};
int tonesG[] = {NOTE_C5,NOTE_C5,0,NOTE_C5,0,NOTE_C5,NOTE_D5,NOTE_E5,NOTE_F3,0,0,NOTE_C3,0,NOTE_G2,0};
int tonesH[] = {NOTE_E5,NOTE_E5,0,NOTE_E5,0,NOTE_C5,NOTE_E5,0,NOTE_G5,0,0,NOTE_G4,0,0};
int tonesI[] = {NOTE_E5,NOTE_C5,0,NOTE_G4,NOTE_G3,0,NOTE_GS4,0,NOTE_A4,NOTE_F5,NOTE_F3,NOTE_F5,NOTE_A4,NOTE_C4,NOTE_F3,0};
int tonesJ[] = {NOTE_B4,NOTE_A5,NOTE_A5,NOTE_A5,NOTE_G5,NOTE_F5,NOTE_E5,NOTE_C5,NOTE_G3,NOTE_A4,NOTE_G4,NOTE_C4,NOTE_G3,0};
int tonesK[] = {NOTE_B4,NOTE_F5,0,NOTE_F5,NOTE_F5,NOTE_E5,NOTE_D5,NOTE_C5,NOTE_E4,NOTE_G3,NOTE_E4,NOTE_C4,0,0};

// ... e respectivas durações
int durationA[] = {co,co,co,co,co,co,co,co,co,co,se,co,co,se};
int durationB[] = {co,co,co,co,se,co,co,co,co,co,co,co,co,co,co,tr,tr,tr,co,co,co,co,co,co,co,co,co,co,se};
int durationC[] = {co,co,co,co,co,co,co,co,co,co,co,co,co,co,co,co};
int durationD[] = {co,co,co,co,co,co,co,co,co,co,co,co,co,co,co,co};
int durationE[] = {co,co,co,co,co,co,se,co,co,co,co,co,co,co,co};
int durationF[] = {co,co,co,co,co,co,co,co,co,co,co,co,co,co,co,co};
int durationG[] = {co,co,co,co,co,co,co,co,co,co,co,co,se,co,co};
int durationH[] = {co,co,co,co,co,co,co,co,co,co,se,co,co,se};
int durationI[] = {co,co,co,co,co,co,co,co,co,co,co,co,co,co,co,co};
int durationJ[] = {tr,tr,tr,tr,tr,tr,co,co,co,co,co,co,co,co};
int durationK[] = {co,co,co,co,tr,tr,tr,co,co,co,co,co,co,se};

char melody[] = "abbcdcecdcefgfhbbijikijikfgfhijik";

// Número de notas
int numberA = 14;
int numberB = 29;
int numberC = 16;
int numberD = 16;
int numberE = 15;
int numberF = 16;
int numberG = 15;
int numberH = 14;
int numberI = 16;
int numberJ = 14;
int numberK = 14;
int melodynum = 33;

// Define o pin para ligar o piezo
int piezopin = 11;

// Função que recebe uma faixa (notas e durações) e o número de notas
void play(int tones[], int duration[], int number, int bpm){
  int i;

  for (i = 0; i < number; i++) {

    int lenght = bpm*duration[i];
    tone(piezopin, tones[i],lenght);

    // Pausas para que as notas não fiquem coladas umas às outras
    if(duration[i]==se)
      delay(bpm/0.5);
    if(duration[i]==tr)
      delay(bpm/.75);
    if(duration[i]==co)
      delay(bpm);

    // Pára de tocar a nota
    noTone(piezopin);
   }
}

// Função que recebe uma string que contém as faixas para criar uma música (e o seu tamanho)
void playall(char melody[], int num){

  int i;

  for(i=0;i
    if(melody[i]=='a')
      play(tonesA, durationA, numberA, SMbpm);
    if(melody[i]=='b')
      play(tonesB, durationB, numberB, SMbpm);
    if(melody[i]=='c')
      play(tonesC, durationC, numberC, SMbpm);
    if(melody[i]=='d')
      play(tonesD, durationD, numberD, SMbpm);
    if(melody[i]=='e')
      play(tonesE, durationE, numberE, SMbpm);
    if(melody[i]=='f')
      play(tonesF, durationF, numberF, SMbpm);
    if(melody[i]=='g')
      play(tonesG, durationG, numberG, SMbpm);
    if(melody[i]=='h')
      play(tonesH, durationH, numberH, SMbpm);
    if(melody[i]=='i')
      play(tonesI, durationI, numberI, SMbpm);
    if(melody[i]=='j')
      play(tonesJ, durationJ, numberJ, SMbpm);
    if(melody[i]=='k')
      play(tonesK, durationK, numberK, SMbpm);
    }
}

void setup() {
  playall(melody,melodynum);
}

void loop() {
}

E para finalizarmos ficamos com o código de um dos themas mais famosos do filme Star Wars. Se você pensou na Marcha Imperial você acertou! Esse código não precisa da biblioteca pitches.h, basta copiar e fazer o upload para a placa e divertir-se.

Quando encontrei esse código não constava autor, então não pude referenciar os créditos. O link onde encontrei pode ser visto AQUI. Repare também que o autor faz uso de um led conectado ao pino 13 para piscar conforme as notas vão sendo tocadas, para isso você pode utilizar o segundo esquema mostrado acima.

int ledPin = 13;

int speakerPin = 11;
//speaker connected to one of the PWM ports

#define c 261
#define d 294
#define e 329
#define f 349
#define g 391
#define gS 415
#define a 440
#define aS 455
#define b 466
#define cH 523
#define cSH 554
#define dH 587
#define dSH 622
#define eH 659
#define fH 698
#define fSH 740
#define gH 784
#define gSH 830
#define aH 880
//frequencies for the tones we're going to use
//used http://home.mit.bme.hu/~bako/tonecalc/tonecalc.htm to get these

void setup()
{
  pinMode(ledPin, OUTPUT);
  // sets the ledPin to be an output
  pinMode(speakerPin, OUTPUT);
  //sets the speakerPin to be an output
}

void loop() 	// run over and over again
{
  march();
}

void beep (unsigned char speakerPin, int frequencyInHertz, long timeInMilliseconds)
{
    digitalWrite(ledPin, HIGH);
    //use led to visualize the notes being played

    int x;
    long delayAmount = (long)(1000000/frequencyInHertz);
    long loopTime = (long)((timeInMilliseconds*1000)/(delayAmount*2));
    for (x=0;x    {
        digitalWrite(speakerPin,HIGH);
        delayMicroseconds(delayAmount);
        digitalWrite(speakerPin,LOW);
        delayMicroseconds(delayAmount);
    }

    digitalWrite(ledPin, LOW);
    //set led back to low

    delay(20);
    //a little delay to make all notes sound separate
}

void march()
{
    //for the sheet music see:
    //http://www.musicnotes.com/sheetmusic/mtd.asp?ppn=MN0016254
    //this is just a translation of said sheet music to frequencies / time in ms
    //used 500 ms for a quart note

    beep(speakerPin, a, 500);
    beep(speakerPin, a, 500);
    beep(speakerPin, a, 500);
    beep(speakerPin, f, 350);
    beep(speakerPin, cH, 150);

    beep(speakerPin, a, 500);
    beep(speakerPin, f, 350);
    beep(speakerPin, cH, 150);
    beep(speakerPin, a, 1000);
    //first bit

    beep(speakerPin, eH, 500);
    beep(speakerPin, eH, 500);
    beep(speakerPin, eH, 500);
    beep(speakerPin, fH, 350);
    beep(speakerPin, cH, 150);

    beep(speakerPin, gS, 500);
    beep(speakerPin, f, 350);
    beep(speakerPin, cH, 150);
    beep(speakerPin, a, 1000);
    //second bit...

    beep(speakerPin, aH, 500);
    beep(speakerPin, a, 350);
    beep(speakerPin, a, 150);
    beep(speakerPin, aH, 500);
    beep(speakerPin, gSH, 250);
    beep(speakerPin, gH, 250);

    beep(speakerPin, fSH, 125);
    beep(speakerPin, fH, 125);
    beep(speakerPin, fSH, 250);
    delay(250);
    beep(speakerPin, aS, 250);
    beep(speakerPin, dSH, 500);
    beep(speakerPin, dH, 250);
    beep(speakerPin, cSH, 250);
    //start of the interesting bit

    beep(speakerPin, cH, 125);
    beep(speakerPin, b, 125);
    beep(speakerPin, cH, 250);
    delay(250);
    beep(speakerPin, f, 125);
    beep(speakerPin, gS, 500);
    beep(speakerPin, f, 375);
    beep(speakerPin, a, 125);

    beep(speakerPin, cH, 500);
    beep(speakerPin, a, 375);
    beep(speakerPin, cH, 125);
    beep(speakerPin, eH, 1000);
    //more interesting stuff (this doesn't quite get it right somehow)

    beep(speakerPin, aH, 500);
    beep(speakerPin, a, 350);
    beep(speakerPin, a, 150);
    beep(speakerPin, aH, 500);
    beep(speakerPin, gSH, 250);
    beep(speakerPin, gH, 250);

    beep(speakerPin, fSH, 125);
    beep(speakerPin, fH, 125);
    beep(speakerPin, fSH, 250);
    delay(250);
    beep(speakerPin, aS, 250);
    beep(speakerPin, dSH, 500);
    beep(speakerPin, dH, 250);
    beep(speakerPin, cSH, 250);
    //repeat... repeat

    beep(speakerPin, cH, 125);
    beep(speakerPin, b, 125);
    beep(speakerPin, cH, 250);
    delay(250);
    beep(speakerPin, f, 250);
    beep(speakerPin, gS, 500);
    beep(speakerPin, f, 375);
    beep(speakerPin, cH, 125);

    beep(speakerPin, a, 500);
    beep(speakerPin, f, 375);
    beep(speakerPin, c, 125);
    beep(speakerPin, a, 1000);
    //and we're done \ó/
}

Veja o video de demonstração. A qualidade é péssima, mas da para ter uma noção!

Então é isso, espero que tenham gostado e se divertido bastante com esse tutorial. Até a próxima.
Para fazer download de todos os códigos e esquemas de montagem basta clicar AQUI.

Referencias

Referencia 1 (Artigo sobre ondas quadradas)
Referencia 2 (Pagina Arduino Playground, utilização de speakers)
Referencia 3 (Wikipédia, sobre sons).
Referencia 4 (Artigo sobre notas musicais e hardware).

Anúncios
por ferpinheiro Postado em Arduino

3 comentários em “Tocando músicas com o Arduino

  1. Line 49 is incomplete, it must be “for (x=0;x<loopTime;x++) {"

    It works also on Launchpad MSP430 using Energia!

  2. Olá amigo!
    Parabéns pelo artigo e pelo blog testei os códigos e ficou muito bom!
    Gostaria de pedir a autorização para divulgar um vídeo no meu canal no youtube sobre a canção com o pitches do Mario Bros.
    Bem eu há algum tempo tb fiz uma versão porém essa versão do seu artigo ficou ótima
    Darei devidos créditos a seu blog, obrigado!
    Gostei muito, que você assim como eu compartilha os projetos no blog.
    Eu tb possuo 1 de arduino
    Parabéns!

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s