| Módulo | Conector Interface | Pino Arduino | Notas |
|---|---|---|---|
| SDA — Dados I2C | LCD_SDA | A4 | Barramento de dados I2C |
| SCL — Relógio I2C | LCD_SCL | A5 | Relógio I2C — 100 kHz |
| VCC | 5V | 5V | Consumo ~30 mA com retroiluminação |
| GND | GND | GND | — |
LiquidCrystal_I2C0x27. Se o LCD não aparecer, testa 0x3F.
Para descobrir o endereço certo corre o sketch I2C Scanner disponível nos exemplos do IDE.
| Método | Descrição | Exemplo |
|---|---|---|
| lcd.init() | Inicializa o LCD | No setup() |
| lcd.backlight() | Liga retroiluminação | lcd.backlight() |
| lcd.noBacklight() | Desliga retroiluminação | lcd.noBacklight() |
| lcd.clear() | Limpa todo o ecrã | lcd.clear() |
| lcd.setCursor(col, lin) | Posiciona cursor (col 0–15, lin 0–1) | lcd.setCursor(0, 1) |
| lcd.print(valor) | Escreve texto, int, float ou char | lcd.print("Temp: ") |
| lcd.createChar(id, bitmap) | Cria carácter 5×8 personalizado (0–7) | lcd.createChar(0, grau) |
| lcd.write(id) | Escreve carácter personalizado | lcd.write(0) |
| lcd.scrollDisplayLeft() | Faz scroll do ecrã para a esquerda | No loop() |
| lcd.home() | Move cursor para (0,0) | lcd.home() |
Primeiro contacto com o LCD. Mostra uma mensagem fixa nas duas linhas e pisca a retroiluminação.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// addr 0x27, 16 colunas, 2 linhas
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0); // Coluna 0, Linha 0 (1.ª linha)
lcd.print("Kit C Domotica");
lcd.setCursor(0, 1); // Coluna 0, Linha 1 (2.ª linha)
lcd.print("LED Portugal!");
}
void loop() {
// Pisca retroiluminação 3×
for (int i = 0; i < 3; i++) {
lcd.noBacklight();
delay(400);
lcd.backlight();
delay(400);
}
delay(3000);
}
Mostra em tempo real a luminosidade (LDR) na primeira linha e o estado do PIR na segunda.
Actualiza sem usar clear() para evitar flickering — sobrescreve os caracteres directamente.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define LDR A0
#define PIR 2
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
pinMode(PIR, INPUT);
lcd.init();
lcd.backlight();
// Cabeçalhos fixos — escrevemos só uma vez
lcd.setCursor(0, 0); lcd.print("Luz:");
lcd.setCursor(0, 1); lcd.print("PIR:");
}
void loop() {
int luz = analogRead(LDR);
int mov = digitalRead(PIR);
// Actualiza valor da luz (col 5 para não apagar "Luz:")
lcd.setCursor(5, 0);
lcd.print(luz);
lcd.print(" "); // Limpa dígitos antigos
// Actualiza estado do PIR
lcd.setCursor(5, 1);
lcd.print(mov == HIGH ? "Movimento!" : "Sem mov. ");
delay(400);
}
lcd.clear() a cada ciclo (que pisca o ecrã),
reposiciona o cursor com setCursor() e sobrescreve só os valores que mudam.
Os espaços extras a seguir (" ") limpam os dígitos que possam ter ficado do valor anterior.
Fazer scroll de uma mensagem maior que 16 caracteres e criar um efeito de ticker de notícias.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
lcd.init();
lcd.backlight();
}
void loop() {
// Método 1: Scroll automático integrado
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Casa Inteligente");
lcd.setCursor(0, 1);
lcd.print("LED Portugal PRR");
delay(2000);
// Faz scroll para a esquerda 16× (sai do ecrã)
for (int i = 0; i < 16; i++) {
lcd.scrollDisplayLeft();
delay(200);
}
delay(1000);
// Método 2: Ticker — mensagem longa com scroll manual
String msg = " ** Sistema OK: Luz, Gas, PIR, Janela, Porta ** ";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ticker:");
for (int pos = 0; pos < msg.length() - 16; pos++) {
lcd.setCursor(0, 1);
lcd.print(msg.substring(pos, pos + 16));
delay(250);
}
}
O LCD suporta 8 caracteres personalizados (índices 0–7) definidos numa grelha 5×8 píxeis. Útil para criar ícones de temperatura °, setas ↑↓, coração ♥ ou símbolos da casa.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Símbolo de grau ° — grelha 5×8 em binário (cada byte = linha)
byte grau[8] = {
0b01100, // ░▓▓░░
0b10010, // ▓░░▓░
0b10010, // ▓░░▓░
0b01100, // ░▓▓░░
0b00000,
0b00000,
0b00000,
0b00000
};
// Ícone de casa
byte casa[8] = {
0b00100,
0b01110,
0b11111,
0b10001,
0b10101,
0b10001,
0b11111,
0b00000
};
// Seta para cima
byte setaCima[8] = {
0b00100,
0b01110,
0b11111,
0b00100,
0b00100,
0b00100,
0b00000,
0b00000
};
void setup() {
lcd.init();
lcd.backlight();
// Regista chars personalizados (índices 0–7)
lcd.createChar(0, grau);
lcd.createChar(1, casa);
lcd.createChar(2, setaCima);
lcd.setCursor(0, 0);
lcd.write(1); // ícone casa
lcd.print(" Temp: 24");
lcd.write(0); // símbolo grau
lcd.print("C");
lcd.setCursor(0, 1);
lcd.write(2); // seta cima
lcd.print(" Tendencia: sobe");
}
void loop() { }
O LCD funciona como painel de monitorização — alterna entre dois ecrãs a cada 3 segundos: o ecrã A mostra luz e movimento, o ecrã B mostra gás e estado geral.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define LDR A0
#define MQ2_ANA A1
#define PIR 2
LiquidCrystal_I2C lcd(0x27, 16, 2);
int ecra = 0; // 0 = ecrã A, 1 = ecrã B
unsigned long ultimaTroca = 0;
const unsigned long INTERVALO = 3000; // Troca a cada 3s
void setup() {
pinMode(PIR, INPUT);
lcd.init();
lcd.backlight();
lcd.print("Casa Domotica");
lcd.setCursor(0, 1);
lcd.print("LED Portugal");
delay(2000);
lcd.clear();
}
void loop() {
int luz = analogRead(LDR);
int gas = analogRead(MQ2_ANA);
bool mov = digitalRead(PIR) == HIGH;
bool gasAlerta = gas > 600;
// Troca de ecrã com millis (não bloqueia o loop)
if (millis() - ultimaTroca > INTERVALO) {
ecra = 1 - ecra; // Alterna 0↔1
ultimaTroca = millis();
lcd.clear();
}
if (ecra == 0) {
// Ecrã A: Luz + PIR
lcd.setCursor(0, 0);
lcd.print("Luz:"); lcd.print(luz); lcd.print(" PIR:");
lcd.print(mov ? "ON " : "OFF");
lcd.setCursor(0, 1);
lcd.print(gasAlerta ? "!! GAS ALERTA !!" : "Estado: NORMAL ");
} else {
// Ecrã B: Gás + estado geral
lcd.setCursor(0, 0);
lcd.print("Gas:"); lcd.print(gas); lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(gasAlerta ? "ALARME DE GAS! " : "Casa Segura ");
}
}
millis()