Projetos

Despertador Arduino Com Melodia Personalizável

Eletrogate 7 de setembro de 2021

Introdução

Com a intervenção humana sobre o tempo da natureza, se fez cada vez mais presente o uso do relógio. Hoje as relações sociais se dão por meio do tempo do relógio.

E neste post de hoje, iremos ver como desenvolver um relógio utilizando a placa arduino, que além de exibir o horário atual, irá contar com as funções de despertador,  e com ajuste de horário atual, além do ajuste do toque desejado para o despertador.


Como Executar Melodia em um Arduino com Buzzer

Para execução de uma melodia em um arduino com um buzzer deve-se executar o seguinte passo-a-passo:

  • Monte este esquema utilizando um arduino e um buzzer:

Esquemático

Eibição Partitura Nokia Tune

Caso deseje esta mesma partitura para abrir no MuseScore, baixe aqui; Em seguida abra o arquivo .mid baixado com o software MuseScore.

  • Com a partitura aberta com software MuseSore, selecione a primeira nota clicando com o mouse na mesma.

Explicação

  • Após a seleção da nota, pode-se observar no canto inferior esquerdo o nome da nota.

Explicação

  • E também é possível observar a duração da nota:

Explicação

Com estes dados (Altura e Duração da Nota), é possível converter a melodia da partitura para código executável para o arduino com um buzzer.

Para isso faça o download clicando na imagem à seguir,  extraia o arquivo .ZIP, e na pasta /code__Ringtone_Nokia abra o código arduino:

Código e Arquivo de Partitura Nokia Tune

Visão Geral do Programa code__RingtoneNokia;Explicação

Veja a explicação à seguir:

  • Fazemos a inclusão do “NotasMusicais.h” e definimos o pino do buzzer. O arquivo “NotasMusicais.h” deve estar dentro da pasta do código, juntamente com o arquivo .ino;

Explicação

  • Logo após em void setup() configuramos o pino do Buzzer como saída.

Explicação

  • Em void loop() não escrevemos nada. Na função som_RingtoneNokia(), declaramos uma matriz para armazenar as notas à serem tocadas em sequência.

Explicação

A música possui 7 notas musicais básicas: DÓ – RÉ – MI – FÁ – SOL – LÁ – SI, as quais as mesmas são representadas, respectivamente, por: C– D– E– F – G – A – B;

Os nomes das notas da matriz melodia estão no arquivo “NotasMusicais.h”. Os nomes que estão nesta matriz são os mesmos que vimos no processo de identificação da altura da nota no software MuseScore acrescidos de ‘NOTE_’ .

Explicação

Neste caso ficaria NOTE_E5.

Quando a nota for uma pausa, devemos escreve-la como ‘NO_SOUND’

Explicação

Neste caso ficaria NO_SOUND

Caso alguma partitura possua um ‘♭’ (chamado de bemol), por exemplo em E♭4, devemos converte-la para ‘♯’ (chamado de sustenido).

Explicação

Neste cas ficaria NOTE_DS4

Para convertermos a nota para sustenido, devemos utilizarmos esta tabela:

Explicação

No caso do exemplo anterior ficaria RÉ#4 = D#4 = NOTE_DS4.

Quando aparecer um ‘#’ (sustenido), o mesmo é convertido para o caractere ‘S’.

Explicação

Neste caso ficaria NOTE_GS4

 

Continuando na função som_RingtoneNokia(), também declaramos uma matriz para armazenar o tempo de cada nota armazenada na matriz da melodia.

Explicação

Nesta matriz, devemos escrever o índice correspondente de cada nota visualizada no processo de identificação da duração da nota no software MuseScore, utilizando a seguinte tabela:

Explicação

Por exemplo: se encontrarmos uma Colcheia, teremos de escrever na matriz o número 8.

Explicação

Neste caso ficaria 8

Logo após, criamos uma variável para representar a velocidade da melodia.

Explicação

Em seguida, armazenamos o número total de notas que forma definidas na matriz melodia. Para isso, pegamos o tamanho da matriz (em bytes) e dividimos pelo primeiro item da matriz (todos os itens da matriz são do mesmo tipo, neste caso int).

Explicação

Após, iniciamos a execução da música dentro da estrutura de repetição for, que irá ficar repetindo até todas as notas estiverem sido executadas:

Explicação

A nota é reproduzida, especificamente, com o comando tone. No comando tone(), deve-se informar como parâmetros: tone(pino, frequência, duração), sendo pino o número da porta que está conectado o buzzer, a frequência sendo a nota à ser tocada e a duração sendo o tempo da nota. Para mais detalhes da função tone(), consulte a documentação.

Após o carregamento do código para o arduino, a execução irá reproduzir este som:


Hardware do Despertador

Para o desenvolvimento de hardware, siga o seguinte diagrama:

Esquemático

O hardware é composto de um Arduino NANO como microcontrolador, um display LCD 16×2 com comunicação I2C para exibição dos dados, um Teclado Matricial com comunicação I2C para entrada de dados do usuário, um buzzer para acionar o alarme do despertador e dar o feedback de clique do teclado, um RTC DS3231 para armazenar o horário mesmo após o desligamento do sistema e um botão para parar de tocar o despertador quando o mesmo estiver acionado.

Utilizaremos o display LCD para exibir o horário atual, além de exibir as configurações para alteração. O Teclado servirá para mudarmos alguma configuração no sistema.


Software do Despertador

Para desenvolvermos o software que irá ser carregado para o microcontrolador do Arduino NANO, utilizaremos algumas bibliotecas:

  • RTClib.h;

Para instalar a biblioteca RTClib, abra o gerenciador de Bibliotecas da Arduino IDE, na barra de pesquisa digite: ‘RTClib’. Clique para instalar no resultado que corresponder o nome da biblioteca e o autor da biblioteca. O autor da biblioteca é a ‘Adafruit’. Para mais informações da biblioteca, acesse este link.

Instalação Biblioteca

  • Keypad.h;

Para instalar a biblioteca Keypad, abra o gerenciador de Bibliotecas da Arduino IDE, na barra de pesquisa digite: ‘Keypad’. Clique para instalar no resultado que corresponder o nome da biblioteca e o autor da biblioteca. O autor da biblioteca é o ‘Community https://github.com/Chris–A/Keypad’. Para mais informações da biblioteca, acesse este link.

Instalação Biblioteca

  • Keypad_I2C.h;

Para instalar a biblioteca Keypad_I2C, acesse o link https://github.com/joeyoung/arduino_keypads/archive/refs/heads/master.zip. Na Arduino IDE, em Sketch -> Incluir biblioteca -> Adicionar biblioteca .ZIP; Selecione o arquivo .ZIP que foi feito o download anteriormente através do link. Para mais informações da biblioteca, acesse este link.

Instalação biblioteca

  • Wire.h;

A biblioteca Wire.h é uma biblioteca nativa da IDE Arduino, o que significa que ela já está instalada. Para informações detalhadas desta biblioteca, acesse este link.

  • LiquidCrystal_I2C.h;

Para instalar a biblioteca LiquidCrystal_I2C, abra o gerenciador de Bibliotecas da Arduino IDE, na barra de pesquisa digite: ‘LiquidCrystal_I2C’. Clique para instalar no resultado que corresponder o nome da biblioteca e o autor da biblioteca. O autor da biblioteca é o ‘Marco Schwartz’.

Instalação biblioteca

Após instaladas as bibliotecas, faça o download do seguinte arquivo .ZIP, descompacte-o e abra o código arduino Relogio_Despertador_com_Arduino_Nano.ino:

Clique nesta imagem e faça o download do código arduino

No código,  inclui-se primeiro as bibliotecas:

Explicação

O arquivo "NotasMusicais.h" deve-se estar juntamente com o arquivo .ino, dentro da pasta do código.

O arquivo "NotasMusicais.h" tem o seguinte código:

#define NO_SOUND 0
#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  
/*DÓ Central*/#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

Após a inclusão das bibliotecas, fazemos a definição de pinos utilizados:

Explicação

Logo após, fazemos a definição de endereços da memória EEPROM utilizados:

Explicação

Em seguida, definimos os endereços I2C utilizados:

Explicação

Após, criamos um objeto da classe RTC_DS3231 para obtermos e configurarmos dados do RTC. Também declaramos variáveis para armazenarmos na memória RAM (volátil) os dados necessários da EEPROM.

Explicação

Seguidamente, criamos variáveis para controle e armazenagem de dados do Despertador. Também criamos uma variável para controlar em que tela do menu principal estamos.

Explicação

Posteriormente, fazemos a configuração do teclado Matricial I2C.

Explicação

A seguir, em void setup(), inicializamos o display LCD, tiramos todos os caracteres da tela do mesmo e ligamos a luz de fundo.

Explicação

Logo depois, ainda no setup, configuramos o buzzer e o botão de desligamento do despertamento como porta de saída. Também inicializamos o teclado I2C.

Explicação

Logo após, ainda dentro do setup, verificamos através de uma estrutura condicional (if) se o hardware do RTC foi encontrado. Caso não o tenhamos encontrado, entramos em um laço de repetição (while) para ficarmos verificando continuamente se o hardware do mesmo foi identificado.

Explicação

Em seguida, verificamos se o RTC está com o horário regulado. Caso o RTC tenha perdido a energia (até mesmo da bateria) temos como identificar que o mesmo está com o horário errado nesta etapa. Caso confirmarmos que o RTC possui horário errado, chamamos a função para acertar a hora manualmente através da função configuraHorarioRTC().

Explicação

Logo em seguida, ainda dentro do setup,  armazenamos em variáveis os dados que estavam dentro da memória EEPROM através do método read(). Neste método, devemos informar o endereço da memória EEPROM à ser lido os dados. Também armazenamos na variável de controle o estado à que o botão deverá estar para desativar o despertador. Isto é, o estado inverso da leitura digital da porta à que o botão está conectado.

Explicação

Seguidamente, em void loop(), criamos uma variável para armazenarmos todos os dados do RTC referente àquele momento.

Explicação

Posteriormente, ainda no loop, testamos dentro de um switch() a variável indiceMenu. Caso a mesma possua o valor 0, mostramos a tela principal em que é exibido o horário, a temperatura e a data. Caso a variável possua o valor 1, exibimos o menu de opções do Relógio e do Despertador.

Explicação

Ainda em loop, executamos a função para verificarmos se devemos acionar o despertador.

Explicação

Na função feedbackSomClique(), fazemos a execução de som no buzzer para sinalização de que alguma tecla foi pressionada.

Explicação

Na função telaPrincipal_mostraTempo(), fazemos a exibição na tela do LCD o horário, a temperatura atual e a data atual. É necessário informar à função como parâmetros a hora, o minuto, o segundo, a temperatura, o dia, o mês e o ano.

Explicação

Ainda dentro da função telaPrincipal_mostraTempo(), verificamos se alguma tecla foi pressionada. Caso a tecla ‘*’ foi pressionada, invertemos o  índice da variável índiceMenu.

Explicação

Na função telaSecundaria_ExibeOpcoesMenu(), exibimos as opções do menu: ‘Data e Hora’ e ‘Despertador’. Também verificamos as teclas pressionadas para entrarmos ou sairmos das opções.

Explicação

Ainda na função telaSecundaria_ExibeOpcoesMenu(), verificamos se alguma tecla foi pressionada. Caso a tecla ‘A’ foi pressionada, decrementamos a variável de controle de menu. Caso a tecla ‘B’ foi pressionada, incrementamos a variável de controle de menu. Caso a tecla ‘*’ foi pressionada, saímos do menu. Caso a tecla ‘#’ foi pressionada, entramos no menu correspondente.

Explicação

Na função telaDespertador(), exibimos as opções do sub-menu: ‘Configurar Horário’, ‘ON/OFF Despertador’ e ‘Som ao Despertar’. Também verificamos as teclas pressionadas para entrarmos ou sairmos das opções.

Explicação

Ainda na função telaDespertador(), verificamos se alguma tecla foi pressionada. Caso a tecla ‘A’ foi pressionada, decrementamos a variável de controle de menu. Caso a tecla ‘B’ foi pressionada, incrementamos a variável de controle de menu. Caso a tecla ‘*’ foi pressionada, saímos do menu. Caso a tecla ‘#’ foi pressionada, entramos na opção correspondente.

Explicação

Na função configuraHorarioRTC(), podemos configurar os atributos do tempo, como hora, minuto, segundo, dia, mês e ano.

Explicação

Ainda na função configuraHorarioRTC(), verificamos se a tecla pressionada foi um número (0 à 9).

Explicação

Caso a tecla pressionada foi um número, fazemos o ajuste das variáveis do tempo (hora, minuto, segundo, etc.) de acordo com o valor da variável  indexVariavelASerAjustada. Esta variável (indexVariavelASerAjustada) define qual variável do tempo iremos alterar.

Ainda na função configuraHorarioRTC(), testamos se a tecla pressionada foi a ‘#’. Caso sim, fazemos a remoção de caracteres que não são números das variáveis do tempo. Estes caracteres são ‘/’ e ‘:’. E então alteramos o horário atual do RTC para o configurado, através do método adjust(), em que é passado como parâmetro um objeto DateTime. Este objeto DateTime, neste caso, é composto pelos seguintes parâmetros, respectivamente:

  • Ano: ano completo (intervalo: 2000–2099) ou o deslocamento do ano 2000 (intervalo: 0–99);
  • Mês: Número do mês (1–12);
  • Dia: Dia do mês (1–31);
  • Hora: hora (0–23);
  • Min: minuto (0–59);
  • Seg:  segundo (0–59).

Explicação

Na função configuraHorarioDespertador(), configuramos o horário para ativar o despertador, ou seja, o horário que irá despertar.

Explicação

Nesta mesma função, também verificamos se a tecla pressionada foi um número (0 à 9). Caso for um número, fazemos o ajuste das variáveis do despertador (hora e minuto) de acordo com o valor da variável  indexVariavelASerAjustada.

Explicação

Ainda na função configuraHorarioDespertador(), testamos se a tecla pressionada foi a ‘#’.

Explicação

Caso foi esta tecla pressionada, fazemos a remoção do caractere  ‘:’ que não é número, da variável hora. Também testamos se a conversão de todas variáveis do despertador para o tipo int não retorne 0 (o que indicaria que é inválida a conversão). Caso a conversão de todas as variáveis se mostre válida, gravamos a hora e o minuto para despertar na memória EEPROM, através do método update(), em que é passado como parâmetro o endereço do valor à ser atualizado e o novo valor à ser gravado.

Explicação

Na função configuraSomDespertador(), é configurado o som à ser tocado quando o despertador for acionado.

Explicação

Nesta função, exibimos para o usuário uma tela mostrando o som atual à tocar salvo. Todo som tem um índice.

Explicação

Este índice é uma variável do tipo int chamada indiceConsulta. O valor desta variável é que estará gravada na memória EEPROM.

Verificamos se alguma tecla foi pressionada. Se a tecla pressionada foi a ‘#’, então salvamos o valor do índice do som á ser tocado na memória EEPROM. Também fazemos a verificação e o ajuste do valor máximo e mínimo da variável que armazena o índice do som à tocar.

Na função configuraAtivacaoDespertador(), podemos ativar ou desativar a função despertador.

Explicação

Nesta função, verificamos se alguma tecla foi pressionada. Caso alguma foi pressionada, verificamos se foi a ‘#’. Caso sim, salvamos na memória EEPROM o valor do índice que indica se o despertador deve estar ligado ou desligado.

Explicação

Na função verificaSeDeveDespertar(DateTime agora), é feita a verificação se deve ou não despertar. Passamos como parâmetro para esta função um objeto DateTime com o horário atual.

Explicação

Nesta função, testamos se o despertador está no modo ativo (ligado). Caso esteja ativo, testamos se a hora atual é igual à hora de despertar e se o minuto atual é igual ao minuto à despertar e testamos se o segundo atual é igual á 0. Caso estas condições sejam todas verdadeiras, autorizamos o despertador tocar o som e atribuímos à variável de controle de “desligar” o despertador para com o valor inverso à leitura digital da porta conectado ao botão.

Explicação

Em seguida, verificamos se o despertador está autorizado à tocar o som. Caso esteja, executamos o som escolhido pelo usuário.

Explicação

As funções despertaSom_RingtoneNokia(), despertaSom_RingtoneOpening(), despertaSom_RingtoneClassico() e despertaSom_RingtoneBeepOnce() seguem o mesmo princípio do código explicado em Como executar melodia em um Arduino com buzzer descrito anteriormente.


Funcionamento Final

Veja no vídeo abaixo o funcionamento final do projeto:


Conclusão

Com este projeto, é possível extrair projetos variados, que exijam um menu para LCD, ou que necessite de um uso para o RTC como Despertador.

Caso tenha ficado alguma dúvida, nos contate através dos comentários.

Espero que o tenha ajudado e até a próxima.

Tenha a Metodologia Eletrogate na sua Escola! Conheça nosso Programa de Robótica Educacional.


Sobre o Autor


Michel Galvão

Hobbysta em Sistemas Embarcados e IoT. Tem experiência em Automação Residencial e Agrícola.


Eletrogate

7 de setembro de 2021

A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.

Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!

Eletrogate Robô

Cadastre-se e fique por
dentro de novidades!