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.
Para este projeto, é necessário utilizar:
Para um entendimento mais aprofundado dos componentes utilizados, veja os seguintes artigos, aqui mesmo do blog Eletrogate:
Para execução de uma melodia em um arduino com um buzzer deve-se executar o seguinte passo-a-passo:
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:
Visão Geral do Programa code__RingtoneNokia;
Veja a explicação à seguir:
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_’ .
Quando a nota for uma pausa, devemos escreve-la como ‘NO_SOUND’
Caso alguma partitura possua um ‘♭’ (chamado de bemol), por exemplo em E♭4, devemos converte-la para ‘♯’ (chamado de sustenido).
Para convertermos a nota para sustenido, devemos utilizarmos esta tabela:
No caso do exemplo anterior ficaria RÉ#4 = D#4 = NOTE_DS4.
Quando aparecer um ‘#’ (sustenido), o mesmo é convertido para o caractere ‘S’.
Continuando na função som_RingtoneNokia(), também declaramos uma matriz para armazenar o tempo de cada nota armazenada na matriz da melodia.
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:
Por exemplo: se encontrarmos uma Colcheia, teremos de escrever na matriz o número 8.
Logo após, criamos uma variável para representar a velocidade da melodia.
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).
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:
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:
Para o desenvolvimento de hardware, siga o seguinte diagrama:
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.
Para desenvolvermos o software que irá ser carregado para o microcontrolador do Arduino NANO, utilizaremos algumas bibliotecas:
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.
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.
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.
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.
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’.
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:
No código, inclui-se primeiro as bibliotecas:
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:
Logo após, fazemos a definição de endereços da memória EEPROM utilizados:
Em seguida, definimos os endereços I2C utilizados:
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.
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.
Posteriormente, fazemos a configuração do teclado Matricial I2C.
A seguir, em void setup()
, inicializamos o display LCD, tiramos todos os caracteres da tela do mesmo e ligamos a luz de fundo.
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.
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.
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()
.
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.
Seguidamente, em void loop()
, criamos uma variável para armazenarmos todos os dados do RTC referente àquele momento.
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.
Ainda em loop, executamos a função para verificarmos se devemos acionar o despertador.
Na função feedbackSomClique()
, fazemos a execução de som no buzzer para sinalização de que alguma tecla foi pressionada.
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.
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.
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.
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.
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.
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.
Na função configuraHorarioRTC()
, podemos configurar os atributos do tempo, como hora, minuto, segundo, dia, mês e ano.
Ainda na função configuraHorarioRTC()
, verificamos se a tecla pressionada foi um número (0 à 9).
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:
Na função configuraHorarioDespertador()
, configuramos o horário para ativar o despertador, ou seja, o horário que irá despertar.
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.
Ainda na função configuraHorarioDespertador()
, testamos se a tecla pressionada foi a ‘#’.
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.
Na função configuraSomDespertador()
, é configurado o som à ser tocado quando o despertador for acionado.
Nesta função, exibimos para o usuário uma tela mostrando o som atual à tocar salvo. Todo som tem um índice.
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.
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.
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.
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.
Em seguida, verificamos se o despertador está autorizado à tocar o som. Caso esteja, executamos o som escolhido pelo usuário.
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.
Veja no vídeo abaixo o funcionamento final do projeto:
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.
|
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!