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!

5/5 - (1 voto)

Related posts

Diferença entre os módulos bluetooth HC-05 e HC-06

by Arduino e Cia
10 anos ago

Como usar serial plotter no Arduino

by Arduino e Cia
5 anos ago

Qual placa Arduino comprar para o seu projeto?

by Arduino e Cia
12 anos ago
Sair da versão mobile