Introduction: Arduino Tutorial - Clock - LCD

Picture of Arduino Tutorial - Clock - LCD

Este é um tutorial onde iremos demonstrar e explicar uma montagem de um relógio utilizando um Arduino UNO, que irá indicar a hora e data num LCD através de uma placa RTC, que tem a função de guardar a informação de hora e data, sendo que a sigla RTC significa REAL TIME CLOCK.

Esta informação de hora e data é guardada numa memória, sendo que para isso é necessário alimenta-la, assim esta placa contem uma bateria de Lítio do tipo botão, que mesmo sem alimentação externa a memoria continuará alimentada continuando a RTC a funcionar correctamente.

Alem de ser explicado o funcionamento da placa RTC DS1307, também iremos recordar o funcionamento do LCD 16x2. Vejam também o tutorial "Arduino Tutorial - LCD - Temperature Sensor", onde é utilizado e explicado o funcionamento deste tipo de LCD.

Caso queiram saber mais sobre este tipo de RTC DS1307, as suas características e a sua configurações ou de o LCD 16x2, vejam as suas datasheet (Ver ficheiros abaixo), como também em "https://store.arduino.cc/arduino-uno-rev3" para ver na página oficial do Arduino as especificações detalhadas sobre o Arduino UNO.

Step 1: Montagem

Nesta montagem utilizamos também uma Breadboard onde colocamos as alimentações positivas e negativas de forma a distribuir-las mais facilmente para os vários componentes. Depois realizamos as ligações do LCD 16x2, pois é o componente como mais ligações, por fim ligamos a RTC DS1307 e os botões para navegar no menu de acerto do nosso relógio.

Material necessário:

  • 1x Arduíno UNO;
  • 1x Cabo USB;
  • 1x Breadboard;
  • 1x LCD16x2;
  • 1x Resistência 220;
  • 1x Potenciómetro 10KΩ;
  • 1x RTC DS1307;
  • 3x Botões (Push Button);
  • 3x Resistências 1KΩ.

Instalação do LCD 16x2:

Como podem observar na imagem da montagem completa não utilizamos todos os pinos do LCD, pois cada pino tem uma função especifica (Ver legenda acima). Assim para explicar mais facilmente o funcionamento do LCD, agrupei os seus pinos em 3 grupos, o grupo dos Pinos de Alimentação, o de Pinos de Comunicação e de Pinos de Informação.

Pinos de Alimentação:

  • Gnd;
  • Vcc;
  • V0;
  • LED - ou A (Anodo);
  • LED + ou K (Catodo).

As alimentações do LCD (Gnd e Vcc) são feitas através dos pinos Gnd e +5V do Arduino UNO, pois são estáveis e protegidas não permitindo que existam sobrecargas ou curto-circuitos.

O Pino V0 tem a função de ajustar o contraste dos caracteres, para podermos controlar esse ajuste ligamos este pino uma resistência variável de 10KΩ, a funcionar como um divisor de tensão (Ver imagem acima), alterando assim a tensão entre 0 e 5V.

Os pinos de alimentação do LED de luz de fundo do LCD (A e K) são também ligados aos pinos de Gnd e +5V do Arduino UNO, no entanto, ligamos em série uma resistência de 220Ω para que o brilho não seja demasiado intenso, não permitindo que os LED internos do LCD se danifiquem.

Pinos de Comunicação:

  • RS (Register Select);
  • R/W (Read / Write);
  • E (Enable).

Nos pinos de comunicação apenas teremos de ter atenção ao pino R/W, pois este deve estar ligado a Gnd para que seja permitido escrever no LCD aparecendo assim o caracteres, caso contrario podemos estar a ler o dados guardados na memoria interna do LCD, ficando o LCD em branco.

Pinos de Informação:

  • D0;
  • D1;
  • D2;
  • D3;
  • D4;
  • D5;
  • D6;
  • D7.

Nesta montagem utilizamos todos os pinos de alimentação e comunicação, no entanto, utilizamos apenas 4 dos 8 possíveis pinos de informação, pois podemos realizar esta montagem com metade dos pinos de dados. Isto é possível através da Biblioteca LiquidCrystal.h que utilizamos no código, permitindo ler o Byte (Byte = 8 bits) de informação enviado pelo Arduino dividido em 2 partes, ou seja, 4 bits de cada vez.

Para isso esta Biblioteca controla os pinos de comunicação, de forma a que o LCD saiba qual o tipo e quais os canais de comunicação que receberão a informação (Pinos D4 a D7).

Instalação da RTC DS1307:

Este componente tem a função de determinar a informação de data e hora, fornecendo essa informação de forma precisa, mesmo quando a alimentação externa é desligada por algum motivo. Neste caso utilizámos uma RTC DS1307, que contem 2 linhas de pinos de alimentação externa e de comunicação (Ver imagem acima), no entanto iremos utilizar a linha com menos pinos, pois para esta montagem apenas são necessários os pinos Gnd, Vcc, SDA e SCL .

Pinos de Alimentação:

  • Gnd;
  • Vcc;
  • Bat.

A alimentação externa da RTC (Gnd e Vcc) são feitas através dos pinos Gnd e +5V do Arduino UNO, pois são estáveis e protegidas não permitindo que existam sobrecargas ou curto-circuitos.

O pino Bat apesar de não ser um pino de alimentação externa coloca-mos-o neste grupo, pois este pino está ligado directamente à bateria tipo botão da RTC que serve de alimentação interna, sendo muito utilizado na monitorização da carga desta bateria.

Pinos de Comunicação:

  • SCL;
  • SDA;
  • DS;
  • SQ.

Os pinos de comunicação SCL e SDA da placa RTC fazem parte de um sistema de comunicação chamado I2C (Ver diagrama acima). Onde é possível comunicar com um ou mais equipamentos através de apenas duas únicas linhas, sendo o SDA ou SERIAL DATA a linha que transmite e recebe a informação, no entanto o SCL ou SERIAL CLOCK o responsável por saber quando é que os equipamentos têm que receber ou enviar informação ficando assim todos sincronizados.

Estes pino devem ser ligados aos pino de entrada analógica do Arduino, no entanto, nem todas as entradas analogias têm as funções de comunicação SCL e SDA. O Arduino UNO não tem indicado na placa, Assim as entradas com essa função são A5 e A4, sendo o pino SCL o pino A5 e o pino SDA o pino A4 (Ver imagem acima).

Caso queiram saber mais sobre o sistema de comunicação I2C, vejam a sua explicação detalhada através deste Link "https://goo.gl/TF3FPe".

O pino DS está ligado a um sensor de Temperatura (Ver ficheiro abaixo), sendo este pino que permite transmitir os dados relativos à temperatura que o sensor está a sentir, sendo ligado aos pinos de entrada digitais do Arduino. Tendo esta função não iremos utiliza-lo nesta montagem.

O pino SQ normalmente não é utilizado, pois apenas contem um sinal de onda quadrada, não tendo uma função essencial ou relevante para a utilização da RTC, no entanto, existem muitas montagens onde este é utilizado para ligar um pequeno LED, indicando assim que a RTC está a funcionar correctamente.

Com os equipamento mais complexos montados, colocamos por fim os 3 botões e as suas respectivas resistência de 1KΩ na Breadboard e ligamos-os aos pinos de entradas digitais. Sem estes botões na montagem apenas podemos visualizar a hora e data no LCD, não sendo possível altera-las ou acerta-las, para isso colocamos estes botões na montagem com as funções de MAIS, MENU e MENOS.

Caso queiram saber mais sobre as entradas digitais do Arduino, vejam também o tutorial "Arduino Tutorial - Digital Input - Button - Monitor Serial", onde explicamos esta característica mais detalhadamente.

Step 2: Código

Com a montagem terminada, ligamos o cabo USB e carregamos o respectivo código na placa do Arduino. No código começamos então por importar as bibliotecas LiquidCrystal.h para o LCD 16x2, e as TimeLib.h, a Wire.h e a DS1307RTC.h para a placa RTC DS1307, através do gestor de bibliotecas do software do Arduino.

A biblioteca LiquidCrystal.h facilita muito a programação do código para o LCD, sendo apenas necessário configurar 2 funções para que este fique a funcionar em pleno, o que caso contrario seria muitas mais.

//Definir os pinos de comunicação e informação do LCD:
LiquidCrystal lcd ("RS", "E", "D7", "D6", "D5", "D4");

e

void setup(){
	//Inicia a comunicação com LCD 16x2:
	lcd.begin(2, 16);
}

Para escrever no LCD é necessário primeiro definir o local onde se começará a escrever, ou seja, a coluna e a linha, depois imprimimos o texto que queremos tendo em atenção que este LCD apenas tem 16 colunas e 2 linhas, caso o texto passe esses limites não aparecerão os caracteres.

void loop(){
	//Define a coluna (em 16) e a linha (em 2) do LCD onde escrever:
	lcd.setCursor(0, 0);
	
	//Escreve no LCD:
	lcd.print("Bateria da RTC INOP");
}

As bibliotecas TimeLib.h, Wire.h e DS1307RTC.h permitem interagir com a placa RTC, no entanto, como podem imaginar têm funções diferentes. A TimeLib.h activa as funcionalidades de tempo, como variáveis para os segundos, minutos, hora, dia , mês, etc, facilitando assim os cálculos dos valores de tempo.

void loop(){
	//Variáveis com valores de tempo:
	second();
	minute();
	hour();
	day();
	month();
	year();
	now();	//Hora e data que está defina neste momento.
	
	//Verifica se tempo está definido ou sincronizado:
	timeStatus()
		//Devolve os seguintes valores:
		timeNotSet	//O valor de tempo não está definido;
		timeNeedsSync	//O Valor de tempo foi definido mas a sincronização falhou.
		timeSet		//O Valor de tempo está definido e sincronizado.	
	
	int h, m, s, D, M, A;		// Variáveis para alteração da hora e data.
	setTime (h, m, s, D, M, A);	//Alterar ou definir a hora e data.

	//Configura o valor de tempo sincronizado de outro equipamento.
	setSyncProvider(getTimeFunction);<br>
}

A biblioteca Wire.h activa as funções de comunicação entre equipamentos através do sistema de comunicação I2C. Os pinos de comunicação deste sistema são diferentes nos vários modelos de Arduino, caso queiram saber quais os pinos utilizados vejam o Link "https://www.arduino.cc/en/Reference/Wire".

Por fim a biblioteca DS1307RTC.h activa as funcionalidades que permitem a leitura e escrita na dos dados de tempo guardados na RTC.

void loop(){
	
	int h, m, s, D, M, A;   // Variáveis para alteração da hora e data.<br>
	//Define uma nova hora e data:
	setTime(h, m, s, D, M, A);<br>	
	//Grava na RTC os dados de tempo:
	RTC.set(now());
	//Lê na RTC os dados de tempo:
	RTC.get();
}	

Este é o código completo para a nossa montagem, onde são utilizados os conceitos descritos anteriormente, sendo possível visualizar os hora e data num LCD, alem disso e porque será necessário também acertar o relógio, utilizar-mos os 3 botões inseridos na montagem, sendo possível para navegar num pequeno e simples e acertar os dados individualmente.

#include <TimeLib.h>	//Importar a "TimeLib" library.
#include <Wire.h>	//Importar a "Wire" library.
#include <DS1307RTC.h>   //Importar a "DS1307RTC" library.
 
#include <LiquidCrystal.h>	//Importar a LCD library.
 
//Definir os pinos de comunicação e informação do LCD.
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

int Botao_mais = 2;	//Variável para selecção do pino de entrada.
int Botao_menu = 3;	//Variável para selecção do pino de entrada.
int Botao_menos = 4; 	//Variável para selecção do pino de entrada.

int Num_Menu = 0;	//Variável para selecção da página de acerto do relógio.

int h, m, s, D, M, A;	//Variáveis para alteração da hora e data.

//Variável array de selecção do nome da página do menu de acerto do relógio.
char Lista_menu[] = {' ', 'h', 'm', 's', 'D', 'M', 'Y'};

//Correr a função SETUP apenas uma vez após ser pressionado Reset:
void setup() {
	//Iniciar a comunicação com LCD 16x2:
  	lcd.begin(2, 16);  
	//Definição do tipo de pino (Saída ou Entrada):
	pinMode(Botao_mais, INPUT);
	//Definição do tipo de pino (Saída ou Entrada):
	pinMode(Botao_menu, INPUT);
	//Definição do tipo de pino (Saída ou Entrada):
	pinMode(Botao_menos, INPUT);
	//Função para obter o tempo da RTC.
	setSyncProvider(RTC.get);
	//Verifica se o valor de tempo não está definido.
	if (timeStatus() != timeSet) {
		//Escreve no LCD:
		lcd.print("BAT. do RTC INOP");
		//Atraso para o próximo passo.
		delay(3000);
		//Apaga a informação do LCD.
		lcd.clear();
		//Alteração dos dados de hora e data.
		h = 1;
		m = 1;
		s = 1;
		D = 1;
		M = 1;
		A = 2001;
		//Grava na RTC uma nova hora e data.
		setTime(h, m , s , D , M , A );
		RTC.set(now());
	}
	else {
		//Escreve no LCD.
		lcd.print("RTC OK");
		//Atraso para o próximo passo.
		delay(3000);
		//Apaga a informação do LCD.
		lcd.clear();
	}
}

//Correr a função LOOP repetidamente:
void loop() {
	//Correr a função:
	Selector_Menu();
	
	//Correr a função:
	Relogio();
}

//>>> Selecção do menu:
void Selector_Menu() {
	//Condição para activar o acerto da hora e data do relógio:
	if (digitalRead(Botao_menu) == HIGH) {
		//Apaga a informação do LCD.
		lcd.clear();
		//Altera o valor de selecção do menu.
		Num_Menu = Num_Menu + 1;
		//Condição para seleccionar a página de acerto do relógio.
		if (Num_Menu < 7) {
			//Define a coluna (em 16) e a linha (em 2) do LCD onde escrever:
			lcd.setCursor(15, 0);
			//Escreve no LCD.
			lcd.print(Lista_menu[Num_Menu]);
		}
		//Condição para voltar para a página do relógio.
		else if (Num_Menu > 6) {
			Num_Menu = 0;
		}
	}
}

//>>> Função de escrita dos dados do relógio no LCD:
void Relogio() {
	//Verifica se o valor de tempo está definido.
	if (timeStatus() == timeSet) {
		//Define a coluna (em 16) e a linha (em 2) do LCD onde escrever:
		lcd.setCursor(0, 0);
		//Escreve no LCD:
		if (hour() < 10)
			lcd.print('0');
			lcd.print(hour());
			lcd.print(":");
		if (minute() < 10)
			lcd.print('0');
			lcd.print(minute());
          		lcd.print(":");
        	if (second() < 10)
          		lcd.print('0');
          		lcd.print(second());
      
        	//Define a coluna (em 16) e a linha (em 2) do LCD onde escrever:
        	lcd.setCursor(0, 1);
        	//Escreve no LCD:
        	if (day() < 10)
          		lcd.print('0');
          		lcd.print(day());
          		lcd.print("/");
        	if (month() < 10)
          		lcd.print('0');
          		lcd.print(month());
          		lcd.print("/");
          		lcd.print(year());
      
          	//Atraso para o próximo passo.
          	delay(500);
      	}
      	else {
          	//Escreve no LCD.
          	lcd.print("Bateria do RTC INOP");
          	//Atraso para o próximo passo:
          	delay(3000);
          	//Alteração dos dados de hora e data.
          	h = 1;
          	m = 1;
          	s = 1;
          	D = 1;
          	M = 1;
          	A = 2001;
          	//Grava na RTC uma nova hora e data.
          	setTime(h, m, s, D, M, A);
          	RTC.set(now());
      	}
    
    	//Condição para acerto das "horas":
    	if (Num_Menu == 1) {
        	//Condição para incrementar +1 hora:
        	if (digitalRead(Botao_mais) == HIGH) {
            		h = hour() + 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(h, minute(), second(), day(), month(), year());
            		RTC.set(now());
        	}
        	//Condição para retirar -1 hora:
        	if (digitalRead(Botao_menos) == HIGH) {
            		h = hour() - 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(h, minute(), second(), day(), month(), year());
            		RTC.set(now());
        	}
    	}
    	//Condição para acerto dos "minutos":
    	else if (Num_Menu == 2) {
        	//Condição para incrementar +1 minuto:
        	if (digitalRead(Botao_mais) == HIGH) {
            		m = minute() + 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), m, second(), day(), month(), year());
            		RTC.set(now());
        	}
        	//Condição para retirar -1 minuto:
        	if (digitalRead(Botao_menos) == HIGH) {
            		m = minute() - 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), m, second(), day(), month(), year());
            		RTC.set(now());
        	}
    	}
    	//Condição para acerto dos "segundos":
    	else if (Num_Menu == 3) {
        	//Condição para incrementar +1 segundo:
        	if (digitalRead(Botao_mais) == HIGH) {
            		s = second() + 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), minute(), s, day(), month(), year());
            		RTC.set(now());
      		}
        	//Condição para retirar -1 segundo:
        	if (digitalRead(Botao_menos) == HIGH) {
            		s = second() - 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), minute(), s, day(), month(), year());
            		RTC.set(now());
        	}
    	}
    	//Condição para acerto dos "dias":
    	else if (Num_Menu == 4) {
        	//Condição para incrementar +1 dia:
        	if (digitalRead(Botao_mais) == HIGH) {
            		D = day() + 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), minute(), second(), D, month(), year());
            		RTC.set(now());
        	}
        	//Condição para retirar -1 dia:
        	if (digitalRead(Botao_menos) == HIGH) {
            		D = day() - 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), minute(), second(), D, month(), year());
            		RTC.set(now());
        	}
    	}
    	//Condição para acerto dos "meses":
    	else if (Num_Menu == 5) {
        	//Condição para incrementar +1 mês:
        	if (digitalRead(Botao_mais) == HIGH) {
            		M = month() + 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), minute(), second(), day(), M, year());
            		RTC.set(now());
        	}
        	//Condição para retirar -1 mês:
        	if (digitalRead(Botao_menos) == HIGH) {
            		M = month() - 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), minute(), second(), day(), M, year());
            		RTC.set(now());
        	}
    	}
    	//Condição para acerto dos "anos":
    	else if (Num_Menu == 6) {
        	//Condição para incrementar +1 ano:
        	if (digitalRead(Botao_mais) == HIGH) {
            		A = year() + 1;
            		//Grava na RTC uma nova hora e data.
           		setTime(hour(), minute(), second(), day(), month(), A);
            		RTC.set(now());
        	}
        	//Condição para retirar -1 ano:
        	if (digitalRead(Botao_menos) == HIGH) {
            		A = year() - 1;
            		//Grava na RTC uma nova hora e data.
            		setTime(hour(), minute(), second(), day(), month(), A);
            		RTC.set(now());
        	}
    	}
}

Caso queiram saber mais ou tenham dúvidas sobre estas e outras referências do código, vejam a sua explicação detalhada no site oficial do Arduino, através deste Link "https://www.arduino.cc/en/Reference/HomePage".

Procurem os nossos tutoriais acerca do Arduino, onde explicamos diversas montagens e o funcionamento dos seus componentes, já agora visitem o nosso canal no Youtube, Facebook ou Twitter.

Abraço e bons projectos.

Comments

About This Instructable

894views

12favorites

License:

Bio: Este é um canal para homemakers e DIY onde vai encontrar tutoriais úteis acerca de Electrónica, Arduíno, Robótica e Impressão 3D. Estes têm explicações simples ... More »
More by Crazy Taz Projects:Arduino Tutorial - LDC - MenuArduino Tutorial - Clock - LCDArduino Tutorial - Alarm - Flow Sensor - Monitor Serial
Add instructable to: