Tocando uma melodia com o Arduino: Ode à Alegria, de Beethoven

Tocando uma melodia com o Arduino: Ode à Alegria, de Beethoven

Anteriormente mostramos como tocar notas musicais específicas usando o Arduino, inclusive com a reprodução de uma escala musical pré-determinada. Neste novo projeto, vamos aplicar essas técnicas para reproduzir uma melodia bastante conhecida, a Ode à Alegria, parte da Nona Sinfonia de Beethoven. É uma melodia simples, portanto indicada para esta tarefa. Posteriormente iremos alterar nosso código para tocar músicas mais complexas e mais longas.

A figura abaixo mostra a partitura da melodia que iremos reproduzir:

Ode à Alegria, de Beethoven, no Arduino

Circuito

A figura a seguir mostra o circuito a ser utilizado, que é o mesmo que empregamos no projeto anterior, "tocando uma escala musical com Arduino":

Tocar notas musicais no Arduino

Precisaremos apenas de um Arduino (qualquer versão), um alto-falante ou buzzer, e um resistor de 150Ω, além de fios conectores e uma matriz de contatos pequena.

Código

Neste programa precisamos incluir o arquivo de cabeçalho pitches.h, o qual já utilizamos em um projeto anterior, e que contém o mapeamento das frequências das notas musicais para um nome de constante. Porém, aqui, eu modifiquei o conteúdo do arquivo, eliminando a palavra "NOTE" que aparece em cada nome de nota, e deixando apenas o padrão _XY, com X sendo o nome da nota em notação musical, e Y o número da oitava. Assim por exemplo, a nota NOTE_C4 será representada apenas por _C4. Fiz isso para simplificar  e diminuir o tamanho do código, pois ele terá muitas dezenas de notas, e pode ficar confuso.

Vamos ao código da aplicação:

#include "pitches.h"
int falante = 8;
float bpm = 80;
int T;
int minima, seminima, seminimaAumentada, colcheia;
int nota[] = {
 _B4, _B4, _C5, _D5, _D5, _C5, _B4, _A4, _G4, _G4, _A4, _B4, _B4, _A4, _A4,
 _B4, _B4, _C5, _D5, _D5, _C5, _B4, _A4, _G4, _G4, _A4, _B4, _A4, _G4, _G4,
 _A4, _A4, _B4, _G4, _A4, _B4, _C5, _B4, _G4, _A4, _B4, _C5, _B4, _A4, _G4, _A4, _D4,
 _B4, _B4, _C5, _D5, _D5, _C5, _B4, _A4, _G4, _G4, _A4, _B4, _A4, _G4, _G4
};

/* Tempos: 
1 = colcheia
2 = seminima
3 = seminima + colcheia
4 = minima
*/

int tempo[] ={
 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 4,
 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 4,
 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2,
 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 4
};

void setup() {
 minima = round((1 / (bpm / 60)) * 1000 * 2);
 seminima = round((1 / (bpm / 60)) * 1000);
 seminimaAumentada = round((1 / (bpm / 60)) * 1500);
 colcheia = round((1 / (bpm / 60)) * 500);
 // Serial.begin(9600); // para debug
}
void loop() {
 // Tocar cada nota durante o tempo especificado:
 for (int i = 0; i < 62; i++) {
   switch (tempo[i]) {
   case 1:
     T = colcheia;
     break;
   case 2:
     T = seminima;
     break;
   case 3:
     T = seminimaAumentada;
     break;
   case 4:
     T = minima; 
     break;
 }
 /* Visualizando os tempos (para debug):
 Serial.println(minima);
 Serial.println(seminima);
 Serial.println(seminimaAumentada);
 Serial.println(colcheia);
 */
 tone(falante, nota[i], T);
 delay(T);
 }
}

Explicando o código

Neste código usaremos as seguintes variáveis:

  • falante - Variável para armazenar o número do pino onde está conectado o alto-falante ou buzzer. 
  • bpm - Nesta variável vamos armazenar um número que indicará o andamento da música (sua "velocidade"). bpm significa "batidas por minuto".
  • T - A variável T receberá o valor do tempo que deve ser aplicado a cada nota durante sua execução (duração da nota).
  • minima, seminima, seminimaAumentada, colcheia - Essas variáveis determinam o valor da duração para cada tipo de nota, pois algumas notas possuem duração mais longa do que outras.

Também criaremos dois arrays (vetores) para armazenar as notas e seus respectivos tempos de duração:

  • O array nota[] contém as notas da melodia a ser reproduzida, na sequência correta, como fizemos no artigo sobre escalas musicais no Arduino.
  • O array tempo[] armazenará um número que será usado para calcular a duração de cada nota tocada, também na sequência correta de reprodução da melodia. Assim, a primeira posição deste array possui a duração da nota na primeira posição no array nota[], e assim sucessivamente.

No array tempo[] utilizamos números para representar as durações das notas tocadas. Em nosso código, o número 1 simboliza uma colcheia, o valor 2 representa uma seminima, o valor 3 uma semínima aumentada ( 1 tempo e 1/2), e o valor 4 representa uma mínima (2 tempos).

Na rotina de setup é calculado o valor de tempo em milissegundos de cada tipo de nota, de acordo com o andamento (variável bpm). A duração de cada nota depende do andamento da música, que é dado pelo valor armazenado em bpm. Assim, valores maiores de bpm farão a música ser executada mais rapidamente, e vice-versa.

Na rotina de loop usamos uma estrutura de decisão Switch / Case para determinar a duração a ser aplicada a cada nota tocada, de acordo com o valor armazenado no array tempo[] e com a duração de cada tipo de nota, calculada na rotina de setup.

E, finalmente, chamamos a função tone() para executar a nota na posição i do array nota[], usando a duração T determinada, e a função delay() na sequência faz o Arduino aguardar a nota ser executada antes de reproduzir a próxima nota da música.

Após carregar o código, basta esperar alguns instantes e a melodia da Ode à Alegria (Ode to Joy) de Beethoven será reproduzida no alto-falante.

É isso aí!

Até a próxima!

 

Sobre Fábio dos Reis (1182 Artigos)
Fábio dos Reis trabalha com tecnologias variadas há mais de 25 anos, tendo atuado nos campos de Eletrônica, Telecomunicações, Programação de Computadores e Redes de Dados. É um entusiasta de Unix, Linux e Open Source em geral, adora Eletrônica e Astronomia, e estuda idiomas, além de ministrar cursos e palestras sobre diversas tecnologias em São Paulo e outras cidades do Brasil.
Contato: Website

Escreva um comentário

Seu e-mail não será divulgado


*