RTC Arduino com LCD 16×2 e números grandes
Resolvi incrementar o post que eu fiz, sobre o LCD 16×2 (Display LCD Winstar WH1602A), e coloca-lo para funcionar com o DS1307 (RTC), do artigo anterior. A idéia foi juntar os 2 circuitos, e fazer um relógio RTC Arduino e display LCD.
Como eu não fiquei contente com o resultado, porque os números ficaram muito pequenos no LCD, comecei a caçar exemplos para aproveitar a tela inteira e mostrar os números em um formato maior, criando meu próprio programa. O resultado está aqui:
Na imagem abaixo, uma visão geral do circuito utilizado:
Se voce tiver dúvidas no circuito, recomendo a leitura dos posts mencionados, porque a ligação é exatamente a mesma.
Conexão do RTC Arduino com display LCD 16×2
Na imagem abaixo você confere o esquema de ligação dos componentes no Arduino Uno. Estou usando para o RTC o DS1307 e para controle do contraste do display LCD um potenciômetro de 10K. Você pode utilizar outros valores como 1K, 5K, etc.
Como podemos notar, a alimentação do circuito é toda feita por meio do pino 5V do Arduino.
Agora carregue o seguinte programa no Arduino, que usa as bibliotecas LiquidCrystal e Wire, já presentes na IDE do Arduino não exigindo nenhum tipo de instalação.
//Programa: Relogio com numeros customizados //Autor: Arduino e Cia #include <LiquidCrystal.h> //Biblioteca LCD #include "Wire.h" //Biblioteca para uso do RTC DS1307 #define DS1307_ADDRESS 0x68 byte zero = 0x00; LiquidCrystal lcd(12, 11, 5, 4, 3, 2); int numero, minutoanterior1,minutoanterior2,horaanterior1,horaanterior2; int x = 0; //Arrays para criação dos segmentos e customização dos números byte LT[8] = { B01111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; byte UB[8] = { B11111, B11111, B11111, B00000, B00000, B00000, B00000, B00000 }; byte RT[8] = { B11110, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; byte LL[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, B01111 }; byte LB[8] = { B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111 }; byte LR[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11110 }; byte UMB[8] = { B11111, B11111, B11111, B00000, B00000, B00000, B11111, B11111 }; byte LMB[8] = { B11111, B00000, B00000, B00000, B00000, B11111, B11111, B11111 }; void setup() { Wire.begin(); //Associa cada segmento criado, a um número lcd.createChar(0,LT); lcd.createChar(1,UB); lcd.createChar(2,RT); lcd.createChar(3,LL); lcd.createChar(4,LB); lcd.createChar(5,LR); lcd.createChar(6,UMB); lcd.createChar(7,LMB); lcd.begin(16, 2); //Inicializa o LCD //A linha abaixo pode ser retirada apos setar a data e hora //SelecionaDataeHora(); } void loop() { lcd.setCursor(8,0); lcd.print("."); lcd.setCursor(8,1); lcd.print("."); //Chama rotina que extrai as informacoes do DS1307 e mostra no LCD Mostrarelogio(); delay(1000); } void SelecionaDataeHora() //Seta a data e a hora do DS1307 { byte segundos = 00; //Valores de 0 a 59 byte minutos = 44; //Valores de 0 a 59 byte horas = 22; //Valores de 0 a 23 byte diadasemana = 1; //Valores de 0 a 6 - 0=Domgino, 1 = Segunda, etc. byte diadomes = 17; //Valores de 1 a 31 byte mes = 4; //Valores de 1 a 12 byte ano = 13; //Valores de 0 a 99 Wire.beginTransmission(DS1307_ADDRESS); Wire.write(zero); //Stop no CI para que o mesmo possa receber os dados // As linhas abaixo escrevem no CI os valores de data e // hora que foram colocados nas variaveis acima Wire.write(ConverteParaBCD(segundos)); Wire.write(ConverteParaBCD(minutos)); Wire.write(ConverteParaBCD(horas)); Wire.write(ConverteParaBCD(diadasemana)); Wire.write(ConverteParaBCD(diadomes)); Wire.write(ConverteParaBCD(mes)); Wire.write(ConverteParaBCD(ano)); Wire.write(zero); //Start no CI Wire.endTransmission(); } byte ConverteParaBCD(byte val){ //Converte o número de decimal para BCD return ( (val/10*16) + (val%10) ); } byte ConverteparaDecimal(byte val) { //Converte de BCD para decimal return ( (val/16*10) + (val%16) ); } void custom0()//Seleciona os segmentos para formar o numero 0 { lcd.setCursor(x, 0); //Seleciona a linha superior lcd.write((byte)0); //Segmento 0 selecionado lcd.write(1); //Segmento 1 selecionado lcd.write(2); lcd.setCursor(x, 1); //Seleciona a linha inferior lcd.write(3); lcd.write(4); lcd.write(5); } void custom1() //Seleciona os segmentos para formar o numero 1 { lcd.setCursor(x,0); lcd.write(1); lcd.write(2); lcd.setCursor(x+1,1); lcd.write(5); } void custom2() //Seleciona os segmentos para formar o numero 2 { lcd.setCursor(x,0); lcd.write(6); lcd.write(6); lcd.write(2); lcd.setCursor(x, 1); lcd.write(3); lcd.write(7); lcd.write(7); } void custom3() //Seleciona os segmentos para formar o numero 3 { lcd.setCursor(x,0); lcd.write(6); lcd.write(6); lcd.write(2); lcd.setCursor(x, 1); lcd.write(7); lcd.write(7); lcd.write(5); } void custom4() //Seleciona os segmentos para formar o numero 4 { lcd.setCursor(x,0); lcd.write(3); lcd.write(4); lcd.write(2); lcd.setCursor(x+2, 1); lcd.write(5); } void custom5() //Seleciona os segmentos para formar o numero 5 { lcd.setCursor(x,0); lcd.write((byte)0); lcd.write(6); lcd.write(6); lcd.setCursor(x, 1); lcd.write(7); lcd.write(7); lcd.write(5); } void custom6() //Seleciona os segmentos para formar o numero 6 { lcd.setCursor(x,0); lcd.write((byte)0); lcd.write(6); lcd.write(6); lcd.setCursor(x, 1); lcd.write(3); lcd.write(7); lcd.write(5); } void custom7() //Seleciona os segmentos para formar o numero 7 { lcd.setCursor(x,0); lcd.write(1); lcd.write(1); lcd.write(2); lcd.setCursor(x+1, 1); lcd.write((byte)0); } void custom8() //Seleciona os segmentos para formar o numero 8 { lcd.setCursor(x,0); lcd.write((byte)0); lcd.write((byte)6); lcd.write(2); lcd.setCursor(x, 1); lcd.write(3); lcd.write(7); lcd.write(5); } void custom9() //Seleciona os segmentos para formar o numero 9 { lcd.setCursor(x,0); lcd.write((byte)0); lcd.write((byte)6); lcd.write((byte)2); lcd.setCursor(x+2, 1); lcd.write((byte)5); } void Mostrarelogio() { byte minut[2]; String minutostring; String digitosegundos; char buf; Wire.beginTransmission(DS1307_ADDRESS); Wire.write(zero); Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 7); int segundos = ConverteparaDecimal(Wire.read()); int minutos = ConverteparaDecimal(Wire.read()); int horas = ConverteparaDecimal(Wire.read() & 0b111111); int diadasemana = ConverteparaDecimal(Wire.read()); int diadomes = ConverteparaDecimal(Wire.read()); int mes = ConverteparaDecimal(Wire.read()); int ano = ConverteparaDecimal(Wire.read()); x = 0; numero = horas/10; //Condicional para evitar sobreposição de caracteres if (horaanterior1 != minutos %10) { lcd.setCursor(0,0); lcd.print(" "); lcd.setCursor(0,1); lcd.print(" "); horaanterior1 = minutos %10; } //Chama rotina que mostra o numero customizado na tela mostranumero(); x = 4; numero = horas % 10; if (horaanterior2 != minutos %10) { lcd.setCursor(4,0); lcd.print(" "); lcd.setCursor(4,1); lcd.print(" "); horaanterior2 = minutos %10; } mostranumero(); x = 9; numero = minutos/10; if (minutoanterior1 != minutos %10) { lcd.setCursor(9,0); lcd.print(" "); lcd.setCursor(9,1); lcd.print(" "); minutoanterior1 = minutos %10; } mostranumero(); x = 13; numero = minutos % 10; if (minutoanterior2 != minutos %10) { lcd.setCursor(13,0); lcd.print(" "); lcd.setCursor(13,1); lcd.print(" "); minutoanterior2 = minutos %10; } mostranumero(); } void mostranumero() //Mostra o numero na posicao definida por "X" { switch(numero) { case 0:custom0(); break; case 1:custom1(); break; case 2:custom2(); break; case 3:custom3(); break; case 4:custom4(); break; case 5:custom5(); break; case 6:custom6(); break; case 7:custom7(); break; case 8:custom8(); break; case 9:custom9(); break; } }
O que o programa faz é criar blocos customizaveis, que vão formar os números grandes. Depois, associamos essas blocos conforme o caracter a ser gerado, assim, o número 1 será formado pelos blocos 1 (UB), 2 (RT), e 5 (LR), o número 2 será formado pelos blocos 6 (UMB), 6(UMB), 1(UB), 3(LL), 7(LMB) e 7(LMB) e assim por diante. É praticamente um quebra-cabeça, mas mais divertido. 🙂
Tente também alterar essas linhas (byte UB[8], byte LT[8]…..) para modificar o segmento e obter outros efeitos, como cantos retos, mais arredondados, etc.
Abaixo você confere um vídeo do circuito em funcionamento:
Gostou? Confira outros posts usando displays aqui mesmo no Arduino e Cia!
tem como vc me explicar mais sobre a criação dos blocos customizáveis ? o que são esses blocos mostrando no lcd?
Oi Lailla,
Os displays LCD tem 8 posições de memória para que você crie blocos customizáveis, ou, se preferir, caracteres customizáveis. Eu já usei aqui no Arduino e Cia para desenhar, por exemplo, o simbolo de "grau" em sensores de temperatura. Mudando os 0s e 1s dos arrays, você pode criar os caracteres de sua preferencia (seta, sorriso, etc).
Abraço !
Olá, gostaria de saber como ficaria a programação sem o RTC. Utilizando somente os delays do micro do arduino.
Boa tarde,
Boa sugestão. Pode ser feito sim, vou estudar o assunto e tentar fazer um novo post sobre isso.
Abraço !
o que seria o %10 nos codigos
Boa noite Sidnei,
O %10 é usado para calcular o "módulo" de uma divisão, ou seja, o resto de um número dividido pelo outro. No programa, eu uso o %10 para separar os números da hora, por exemplo. Vamos supor que eu tenha o valor 17, e quero separar o 1 e o 7. Para calcular isso, eu faço :
primeiro_digito_hora = 17 / 10 = 1 (estou trabalhando apenas com números inteiros)
segundo_digito_hora =17 % 10 = 7
Você pode encontrar mais informações sobre como utilizar a função % (modulo) com Arduino nesse link : http://arduino.cc/en/Reference/Modulo
Abraço !
Amigo não entendi como vincular os blocos de caracteres aos algarismos..
Exmplo. Estou fazendo um controlador de temperatura e usando um LCD para mostrar a temperatura gostaria de usar os números em blocos de caracteres como usados por vc no post.. Como fazer isso?
Boa noite Ed,
Defina o numero e chame a rotina mostranumero(). Fica mais ou menos assim:
numero = temperatura_lida;
mostranumero()
Claro, vc vai precisar separar os digitos da temperatura lida, digamos que voce mediu a temperatura e ela é de 25 graus.
//primeiro digito, defina como inteiro para ele pegar apenas o numero 2 na divisao
numero = temperatura/10;
mostranumero();
//segundo digito, pega apenas o resto da divisao por 10, ou seja, 5
numero = temperatura%10;
mostranumero();
Basicamente é isso.
Abraço !
Olá. não consigo acertar o relógio, mesmo alterando os valores nas linhas que é para setar o mesmo.
Oi Odilon,
Estranho. ele fica com qual horário ? 00:00 ?
Abraço.
Olá bom dia. desculpe a demora para o retorno.
o relógio fica com a hora do módulo rtc. no caso ficou 04:02
Usei este exemplo no Display LCD 20×4, mas não consigo fazer funcionar.
usei as bibliotecas:
#include Wire.h
#include LCD.h
#include LiquidCrystal_I2C.h
Inicializacao do display
LiquidCrystal_I2C lcd(0x3F,2,1,0,4,5,6,7,3, POSITIVE);
Aqui funciona as informações na tela, mas para uso do código do
"LCD 16×2 + RTC + Numeros Grandes " – não consigo fazer funcionar.
Boa noite Nilton,
Você chegou a testar com um LCD 16×2 ?
Abraço!
Não, porque tenho somente o LCD 20×4.
Gostaria de concluir este projeto no 20×4
O único problema que é que não achei como ver a data , s´mostra a Hora
Oi Ecio,
Realmente, eu coloquei essa opção no programa, mas não cheguei a mostrar na tela. Talvez um botão para alternar entre hora/data seja uma boa opção. 🙂
Abraço!
utilizei o modulo rtc 1307 para fazer esse relogio porém ele apresentou a data e a hora errada da seguinte forma: (Hora : 27:85:85 Data : 85.85.@5 5.85.@5)
o que poderia ser?
Oi Bruno,
Isso parece ser problema de comunicação com o módulo… vc já fez a revisão das soldas dos pinos de conexão ?
Abraço!
Oi eu liguei todos fios igual o esquema mais não acendeu nada,os dois primeiros do display não seria positivo e nagativo
Oi Celso,
Veja se o seu display não é do tipo que tem o controlador HD44780. Se for (ou se você puder testar), utilize o esquema de ligação deste post:
https://www.arduinoecia.com.br/2013/12/lcd-16×2-arduino-hd44780.html
Abraço!
Adilson
Boa tarde. Colega vc tem que dar uma olhada na pinagem do seu display. Com certeza tem a numeração dos pinos. O pino 1 é o negativo, o pino dois é o positivo +5V. Os displays que tem back Light ou a luz de fundo ligar pino 15 no +5V e pino 16 terra ou negativo. Tem que ver o modelo do display. As vezes se vc seguir só o desenho que está aí em cima não da certo. Há displays com pinagem em cima e outros em baixo ok? Estou a disposição.
https://1.bp.blogspot.com/-zchF7rxe9FA/UrmqnPCX4qI/AAAAAAAABvE/zDQKjRG03fw/s640/Pinagem+LCD+HD44780.png
mais esse display que começa com negativo depois positivo tb serve
mais aquele outro tipo tb serve
ola boa tarde como fazer os numero grandes com o modulo i2c? [email protected]
gostaria de saber como faço esse relógio sem o modulo rtc que eu não tenho
fiz um o os números peque-nos mas não consigo adaptar neste.
sou leigo no Arduíno ainda se alguém puder ajudar agradeço dês de já obrigado..
I have succeeded in making this project up and running well.
If possible, can the 2-point display for seconds flash?
How to modify the code?
I am new and not fluent in Arduino, so please help.
Thank you
Hello!
Yes, it is possible. But in this case you must use the millis to prevent the interruption of the program to flash the 2 points interrupting the counting of the time.
I don’t have this program ready, but you can use the post program as a base.
Hug!
Adilson
Hola buenas noches hablo español solo tengo una duda me podrías decir en específico que línea debo eliminar después de haber ya programado el arduino porque en el comentario del programa haces énfasis de eliminar una línea pero nose en específico que línea eliminar
¡Hola Kevin!
La línea es 67. 🙂
¡Saludos!
Adilson
É possível utilizar Display com módulo I2C já incluso nele?
Outra pergunta é como inserir no circuito o botão para alternar entre exibição de data e hora?
Oi Edgar!
É possível sim, eu tenho um artigo sobre isso nesse link: https://www.arduinoecia.com.br/display-lcd-16×2-i2c-numeros-grandes-arduino/
Sobre o botão, é possível colocar sim, mas não tenho ainda nenhum código pronto, vou verificar.
Abraço!
Adilson
Estou com um projeto parecido, com 9 segmentos funciona… mais de 10 (criei 19) não funciona e dá problema nos primeiros que funcionavam. Tem limite ou estou errando algo?