#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
// --- Configurações de WiFi ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// --- Configurações MQTT ---
const char* mqttserver = "test.mosquitto.org";
const int mqttport = 1883;
// --- Tópicos ---
#define TOPIC_PREFIX "eduardo_esp32_lcd"
WiFiClient espClient;
PubSubClient client(espClient);
// --- Configuração dos PINOS I2C (Manual) ---
#define I2C_SDA 16
#define I2C_SCL 17
// --- Configuração do LCD I2C (20x4) ---
LiquidCrystal_I2C lcd(0x27, 20, 4);
// --- Pinos do Hardware ---
#define LED1_PIN 13
#define LED2_PIN 12
#define POT_PIN 33
#define LDR_PIN 35
#define DHT_PIN 32
#define DHTTYPE DHT22
#define BTN1_PIN 14
#define BTN2_PIN 27
// --- NOVOS PINOS: ULTRASSONICO ---
#define TRIG_PIN 26
#define ECHO_PIN 25
DHT dht(DHT_PIN, DHTTYPE);
// --- Variáveis de Controle ---
unsigned long lastMsg = 0;
const long interval = 2000;
int lastBtn1State = HIGH;
int lastBtn2State = HIGH;
// --- Protótipos ---
void setup_wifi();
void callback(char* topic, byte* payload, unsigned int length);
void reconnect();
void checkButtons();
long readUltrasonicDistance(); // Nova função
void setup() {
Serial.begin(115200);
// Inicia I2C nos pinos manuais
Wire.begin(I2C_SDA, I2C_SCL);
// Inicialização do LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Inicializando...");
// Configuração dos Pinos
pinMode(LED1_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
pinMode(POT_PIN, INPUT);
pinMode(LDR_PIN, INPUT);
pinMode(BTN1_PIN, INPUT_PULLUP);
pinMode(BTN2_PIN, INPUT_PULLUP);
// Configuração do Ultrassônico
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
dht.begin();
setup_wifi();
client.setServer(mqttserver, mqttport);
client.setCallback(callback);
lcd.clear();
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
checkButtons();
unsigned long now = millis();
if (now - lastMsg > interval) {
lastMsg = now;
// 1. Sensores Analógicos
int potValue = analogRead(POT_PIN);
float potPorcentagem = (potValue / 4095.0) * 100.0;
int ldrValue = analogRead(LDR_PIN);
float ldrPorcentagem = (ldrValue / 4095.0) * 100.0;
// 2. Sensor DHT
float h = dht.readHumidity();
float t = dht.readTemperature();
// 3. Sensor Ultrassônico (NOVO)
long distanciaCM = readUltrasonicDistance();
if (isnan(h) || isnan(t)) {
Serial.println("Falha sensor DHT!");
return;
}
// --- Publicando MQTT ---
client.publish(TOPIC_PREFIX "/pot", String(potPorcentagem, 0).c_str());
client.publish(TOPIC_PREFIX "/ldr", String(ldrPorcentagem, 0).c_str());
client.publish(TOPIC_PREFIX "/temp", String(t, 1).c_str());
client.publish(TOPIC_PREFIX "/hum", String(h, 1).c_str());
client.publish(TOPIC_PREFIX "/dist", String(distanciaCM).c_str()); // Publica dist
// --- Atualizando LCD (Dashboard) ---
// Linha 0: Temp e Umidade
lcd.setCursor(0, 0);
lcd.print("T:" + String(t, 1) + "C H:" + String(h, 0) + "% ");
// Linha 1: Pot e LDR
lcd.setCursor(0, 1);
lcd.print("P:" + String((int)potPorcentagem) + "% L:" + String((int)ldrPorcentagem) + "% ");
// Linha 2: Distância
lcd.setCursor(0, 2);
lcd.print("Distancia: " + String(distanciaCM) + " cm ");
// Linha 3: Reservada para MSG recebida (não limpamos aqui para persistir a msg)
Serial.printf("Dados: T=%.1f D=%ld cm\n", t, distanciaCM);
}
}
// --- Função para ler o HC-SR04 ---
long readUltrasonicDistance() {
// Limpa o Trigger
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
// Envia pulso de 10us
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Lê o tempo de resposta (timeout de 30ms para evitar travar o WiFi)
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
// Calcula a distância: Distancia = (Tempo * VelocidadeSom) / 2
// Velocidade do som no ar ~= 0.034 cm/us
long distance = duration * 0.034 / 2;
return distance;
}
void checkButtons() {
int currentBtn1 = digitalRead(BTN1_PIN);
int currentBtn2 = digitalRead(BTN2_PIN);
if (currentBtn1 != lastBtn1State) {
lastBtn1State = currentBtn1;
String status = (currentBtn1 == LOW) ? "PRESSIONADO" : "SOLTO";
client.publish(TOPIC_PREFIX "/btn1", status.c_str());
delay(50);
}
if (currentBtn2 != lastBtn2State) {
lastBtn2State = currentBtn2;
String status = (currentBtn2 == LOW) ? "PRESSIONADO" : "SOLTO";
client.publish(TOPIC_PREFIX "/btn2", status.c_str());
delay(50);
}
}
void setup_wifi() {
delay(10);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
// Exibe mensagem recebida na Linha 3
if (String(topic) == TOPIC_PREFIX "/display") {
lcd.setCursor(0, 3);
// Preenche com espaços antes para limpar lixo antigo
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(message);
}
// Comandos de LED
if (String(topic) == TOPIC_PREFIX "/led1") {
if (message == "1" || message == "on" || message == "ON") digitalWrite(LED1_PIN, HIGH);
else if (message == "0" || message == "off" || message == "OFF") digitalWrite(LED1_PIN, LOW);
}
if (String(topic) == TOPIC_PREFIX "/led2") {
if (message == "1" || message == "on" || message == "ON") digitalWrite(LED2_PIN, HIGH);
else if (message == "0" || message == "off" || message == "OFF") digitalWrite(LED2_PIN, LOW);
}
}
void reconnect() {
while (!client.connected()) {
// Escreve na linha de mensagens que está tentando conectar
lcd.setCursor(0, 3);
lcd.print("MQTT: Conectando...");
String clientId = "ESP32-" + String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
client.publish(TOPIC_PREFIX "/status", "Online");
client.subscribe(TOPIC_PREFIX "/led1");
client.subscribe(TOPIC_PREFIX "/led2");
client.subscribe(TOPIC_PREFIX "/display");
lcd.setCursor(0, 3);
lcd.print("MQTT: Online! ");
} else {
delay(5000);
}
}
}