Tocando melodias usando a função Tone() do Arduino

Tempo de leitura: 8 minutes

O Arduino é uma excelente maneira de simplificar e acelerar seus projetos de microcontroladores, graças à sua comunidade de desenvolvedores que fizeram quase tudo parecer simples. Existem muitos projetos Arduino aqui para você experimentar e se divertir. Alguns de seus projetos podem precisar de alguma ação sonora para notificar algo ou apenas para impressionar os espectadores. E se eu lhe disser que quase todas as músicas-tema que podem ser tocadas em um piano podem ser imitadas em seu Arduino com a ajuda de um programa simples e um alto-falante Piezo barato?

Neste tutorial vamos aprender como é simples e fácil Tocar Melodia no Piezo Buzzer ou Alto-falante usando a função Arduino tone(). No final deste tutorial você poderá tocar alguns tons famosos de Pirates of Caribbean, Crazy Frog, Super Mario e Titanic. Você também aprenderá a tocar qualquer música de piano com o Arduino. Confira o vídeo no final.

 

Hardware Necessário:

  • Arduino (qualquer versão – UNO é usado aqui)
  • Alto-falante Piezo/Buzzer ou qualquer outro alto-falante de 8ohm.
  • Protoboard
  • Fios de conexão
  • PushBotton
  • resistor de 1k (opcional)

Entendendo a função Tone() do Arduino:

Antes de podermos entender como funciona um tom () devemos saber como funciona uma campainha Piezo. Podemos ter aprendido sobre cristais piezo em nossa escola, não é nada mais que um cristal que converte vibrações mecânicas em eletricidade ou vice-versa. Aqui aplicamos uma corrente variável (frequência) para a qual o cristal vibra produzindo som. Portanto, para fazer a campainha Piezo fazer algum ruído, temos que fazer o cristal elétrico Piezo vibrar, o tom e o tom do ruído dependem da rapidez com que o cristal vibra. Portanto, o tom e o tom podem ser controlados variando a frequência da corrente.

Ok, então como obtemos uma frequência variável do Arduino? É aqui que entra a função tone(). O tone() pode gerar uma determinada frequência em um pino específico. A duração do tempo também pode ser mencionada, se necessário. A sintaxe para tone() é

Sintaxe

tone(pino, frequência)
tone(pin,o frequência, duração)

Parâmetros

pino: o pino no qual gerar o tom
frequência: a frequência do tom em hertz - unsigned int
duração: a duração do tom em milissegundos (opcional) - unsigned long

Os valores de pin podem ser qualquer um dos seus pins digitais. Eu usei o pino número 8 aqui. A frequência que pode ser gerada depende do tamanho do temporizador em sua placa Arduino. Para UNO e a maioria das outras placas comuns, a frequência mínima que pode ser produzida é 31Hz e a frequência máxima que pode ser produzida é 65535Hz. No entanto, nós humanos podemos ouvir apenas frequências entre 2000Hz e 5000Hz.

 

O arquivo de cabeçalho pitches.h:

Agora, sabemos como produzir algum ruído usando a função arduino tone(). Mas, como sabemos que tipo de tom será gerado para cada frequência?

O Arduino nos deu uma tabela de notas que iguala cada frequência a um tipo específico de nota musical. Esta tabela de notas foi originalmente escrita por Brett Hagman, em cujo trabalho o comando tone() foi baseado. Usaremos esta tabela de notas para tocar nossos temas. Se você é alguém familiarizado com partituras, deve ser capaz de entender essa tabela, para outros como eu, esses são apenas mais um bloco de código.

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978

O código acima é fornecido no arquivo de cabeçalho pitches.h neste arquivo zip, você só precisa baixar e incluir este arquivo em nosso código Arduino conforme fornecido no final deste tutorial ou usar o código fornecido no arquivo zip.

 

Tocando notas musicais no Arduino:

Para tocar uma melodia decente usando Arduino, devemos saber o que constitui essas melodias. Os três principais fatores necessários para tocar um tema são

  1. Valor da nota
  2. Duração da Nota
  3. Tempo

Temos o arquivo de cabeçalho pitches.h para tocar qualquer valor de nota, agora devemos descobrir a duração específica da nota para tocá-la. O tempo nada mais é do que a rapidez com que a melodia deve ser tocada. Depois de saber o valor da nota e a duração da nota, você pode usá-los com o tone() como

tone(pinName, Note Value, Note Duration);

Para os timbres tocados neste tutorial eu dei a você o valor da nota e a duração da nota dentro do arquivo de cabeçalho “themes.h” usando o qual você pode tocá-los em seus projetos. Mas se você tiver algum tom específico em sua mina e quiser tocá-lo em seu projeto, continue lendo…. Caso contrário, pule este tópico e pule para o próximo.

Para tocar qualquer tom específico, você precisa obter a partitura dessa música específica e converter a partitura para o sketch do Arduino lendo o valor da nota e a duração da nota. Se você é um estudante de música, seria um pedaço de bolo para você, senão gastaria algum tempo e quebraria sua cabeça como eu fiz. Mas no final do dia, quando seu tom tocar na campainha Piezo, você verá que seu esforço vale a pena.

Uma vez que você tenha o valor da nota e a duração da nota, carregue-os no programa dentro do arquivo de cabeçalho “themes.h” como mostrado abaixo

//##############**"HE IS A PIRATE" Theme song of Pirates of caribbean**##############//
int Pirates_note[] = {
NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4,
NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, 
NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4,  
NOTE_A3, NOTE_C4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_F4, 
NOTE_F4, NOTE_G4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_C4, NOTE_C4, NOTE_D4,
0, NOTE_A3, NOTE_C4, NOTE_B3, NOTE_D4, NOTE_B3, NOTE_E4, NOTE_F4,
NOTE_F4, NOTE_C4, NOTE_C4, NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4,
NOTE_D4, 0, 0, NOTE_A3, NOTE_C4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_F4,
NOTE_G4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_G4,
NOTE_A4, NOTE_D4, 0, NOTE_D4, NOTE_E3, NOTE_F4, NOTE_F4, NOTE_G4, NOTE_A4, 
NOTE_D4, 0, NOTE_D4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_F4, NOTE_D4
};
int Pirates_duration[] = {
4,8,4,8,4,8,8,8,8,4,8,4,8,4,8,8,8,8,4,8,4,8,
4,8,8,8,8,4,4,8,8,4,4,8,8,4,4,8,8,
8,4,8,8,8,4,4,8,8,4,4,8,8,4,4,8,4,
4,8,8,8,8,4,4,8,8,4,4,8,8,4,4,8,8,
8,4,8,8,8,4,4,4,8,4,8,8,8,4,4,8,8
};
//###########End of He is a Pirate song#############//

O bloco de código acima mostra o valor da nota e a duração da nota do tema “Ele é um pirata” do filme Piratas do Caribe. Você pode adicionar seu tema da mesma forma.

 

Esquema e Hardware:

O esquema deste projeto do Arduino Tone Generator Project é mostrado na figura abaixo:

A conexão é bem simples temos um alto falante Piezo que é conectado ao pino 8 e Terra do Arduino através de um resistor de 1K. Este resistor de 1k é um resistor limitador de corrente, que é usado para manter a corrente dentro dos limites seguros. Também temos quatro interruptores para selecionar a melodia necessária. Uma extremidade do interruptor é conectada ao terra e a outra extremidade é conectada aos pinos 2, 3, 4 e 5, respectivamente. As chaves terão resistores de pull up habilitados internamente usando o software. Como o circuito é bastante simples, ele pode ser conectado usando uma placa de pão, conforme mostrado abaixo:

Explicação do programa Arduino:

Depois de entender o conceito, o programa Arduino é bastante simples. O código completo é fornecido no final do tutorial. Se você não estiver familiarizado com a adição de arquivos de cabeçalho, você pode baixar o código como um arquivo ZIP aqui e enviá-lo diretamente para o seu Arduino.

Os dois acima são os arquivos de cabeçalho que devem ser adicionados. “pitches.h” é usado para igualar cada nota musical a uma frequência específica e “themes.h” contém o valor da nota e a duração da nota de todos os quatro tons.

#include "pitches.h"
#include "themes.h"

Uma função é criada para reproduzir cada tom quando necessário. Aqui quando a função Play_Pirates() é chamada o tom “He is a Pirate” será tocado. Esta função consiste na função tone que produz a frequência no pino número 8. O noTone(8) é chamado para parar a música uma vez que é tocada. Se você quiser tocar seu próprio tom, altere Pirates_note e Pirates_duration para os novos valores de nota e duração que você salvou no valor “themes.h”

void Play_Pirates()
{
  for (int thisNote = 0; thisNote < (sizeof(Pirates_note)/sizeof(int)); thisNote++) {
    int noteDuration = 1000 / Pirates_duration[thisNote];//converte duração para atraso de tempo
    tone(8, Pirates_note[thisNote], noteDuration);
    int pauseBetweenNotes = noteDuration * 1.05; //Aqui 1.05 é o tempo, aumente para tocar mais devagar
    delay(pauseBetweenNotes);
    noTone(8);
    }
}

Os pinos 2, 3, 4 e 5 são usados para selecionar o tom específico a ser tocado. Esses pinos são mantidos altos por padrão usando os resistores internos de pull up usando a linha de código acima. Quando o botão é pressionado, ele é puxado para o chão.

pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);

O bloco de código abaixo é usado para tocar a música quando um botão é pressionado. Ele lê o valor digital de cada botão e quando fica baixo (zero) assume que o botão está pressionado e toca o respectivo tom chamando a função desejada.

if (digitalRead(2)==0)
{ Serial.println("Selected -> 'He is a Pirate' ");  Play_Pirates();  }
if (digitalRead(3)==0)
{ Serial.println("Selected -> 'Crazy Frog' ");  Play_CrazyFrog();  }
if (digitalRead(4)==0)
{ Serial.println("Selected -> 'Mario UnderWorld' ");  Play_MarioUW();  }
if (digitalRead(5)==0)
{ Serial.println("Selected -> 'He is a Pirate' ");  Play_Pirates();  }

 

Funcionamento deste circuito Arduino do Melody Player:

Quando seu código e hardware estiverem prontos, basta gravar o programa em seu Arduino e você poderá tocar o tom simplesmente pressionando os botões. Se você tiver algum problema, dê uma olhada no seu monitor serial para depuração ou use a seção de comentários para relatar o problema e ficarei feliz em ajudá-lo.

Espero que você tenha gostado do projeto e que o use em algum de seu projeto ou crie um novo tom para o seu projeto. Se sim, sinta-se à vontade para compartilhar seu trabalho na seção de comentários.

Código

#include "pitches.h" //add Equivalent frequency for musical note
#include "themes.h" //add Note vale and duration 

void Play_Pirates()
{ 
  for (int thisNote = 0; thisNote < (sizeof(Pirates_note)/sizeof(int)); thisNote++) {

    int noteDuration = 1000 / Pirates_duration[thisNote];//converte duração para atraso de tempo
    tone(8, Pirates_note[thisNote], noteDuration);

    int pauseBetweenNotes = noteDuration * 1.05; //Aqui 1.05 é o tempo, aumente para tocar mais devagar
    delay(pauseBetweenNotes);
    noTone(8); //stop music on pin 8 
    }
}

void Play_CrazyFrog()
{
  for (int thisNote = 0; thisNote < (sizeof(CrazyFrog_note)/sizeof(int)); thisNote++) {

    int noteDuration = 1000 / CrazyFrog_duration[thisNote]; //converte duração para atraso de tempo
    tone(8, CrazyFrog_note[thisNote], noteDuration);

    int pauseBetweenNotes = noteDuration * 1.30;//Aqui 1.30 é o tempo, diminua para tocar mais rápido
    delay(pauseBetweenNotes);
    noTone(8); //stop music on pin 8 
    }
}

void Play_MarioUW()
{
    for (int thisNote = 0; thisNote < (sizeof(MarioUW_note)/sizeof(int)); thisNote++) {

    int noteDuration = 1000 / MarioUW_duration[thisNote];//converte duração para atraso de tempo
    tone(8, MarioUW_note[thisNote], noteDuration);

    int pauseBetweenNotes = noteDuration * 1.80;
    delay(pauseBetweenNotes);
    noTone(8); //para a música no pino 8
    }
}

void Play_Titanic()
{
    for (int thisNote = 0; thisNote < (sizeof(Titanic_note)/sizeof(int)); thisNote++) {

    int noteDuration = 1000 / Titanic_duration[thisNote];//converte duração para atraso de tempo
    tone(8, Titanic_note[thisNote], noteDuration);

    int pauseBetweenNotes = noteDuration * 2.70;
    delay(pauseBetweenNotes);
    noTone(8); //stop music on pin 8 
    }
}

void setup() {
pinMode(2, INPUT_PULLUP); //Button 1 with internal pull up
pinMode(3, INPUT_PULLUP); //Button 2 with internal pull up
pinMode(4, INPUT_PULLUP); //Button 3 with internal pull up
pinMode(5, INPUT_PULLUP); //Button 4 with internal pull up
Serial.begin(9600);
}

void loop() {
    if (digitalRead(2)==0)
      { Serial.println("Selected -> 'He is a Pirate' ");  Play_Pirates();  }
    if (digitalRead(3)==0)
      { Serial.println("Selected -> 'Crazy Frog' ");  Play_CrazyFrog();  }
    if (digitalRead(4)==0)
      { Serial.println("Selected -> 'Mario UnderWorld' ");  Play_MarioUW();  }
    if (digitalRead(5)==0)
      { Serial.println("Selected -> 'Titanic' ");  Play_Titanic();  }
}