// Gian Ferrari
// Turma 1 - Embarcados
// Atividade2: Controle Climático de estufa
// FUNÇÃo: ESP32 #1 Leituras dos Sensorer <-> EMQX / MQTTX WEB
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <math.h>
#include <ESP32Servo.h>
// ---- WiFi Wokwi -------------------------------------
const char* WIFI_SSID = "Wokwi-GUEST";
const char* WIFI_PASSWORD = "";
// ---- MQTT (MQTTX WEB / EMTX) ----------------
const char* EMQX_BROKER = "broker.emqx.io";
const int EMQX_PORT = 1883;
const char* EMQX_CLIENTID = "";
const char* EMQX_SUB_TOPIC = "esp32_Gian_Atividade2_Sub"; // recebe comando releOn
const char* EMQX_PUB_TOPIC = "esp32_Gian_Atividade2"; // publica dados
// ---- DHT22 ------------------------------------------
#define DHTPIN 15
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// ---- LDR --------------------------------------------
#define LDR_PIN 34
const float GAMMA = 0.7;
const float RL10 = 50;
const float ADC_MAX = 4095.0;
const float VREF = 3.3;
const float R_DIV_OHMS = 10000.0;
// ---- SERVO ------------------------------------------
#define SERVO_PIN 18
Servo servo;
int servoPos = 90; // posição inicial
// ---- RELÉ -------------------------------------------
#define RELAY_PIN 16
bool releOn = false; // estado do relé (vem do MQTT)
// Se no seu relé for "ativo em LOW", mude para true
const bool RELAY_ACTIVE_LOW = false;
// ---- Variáveis --------------------------------------
char msg[255];
float temperatura = 18.0;
float umidade = 40.0;
float lux = 0.0;
WiFiClient espClientEMQX;
PubSubClient emqx(espClientEMQX);
String clientIdStr;
void setRelay(bool on) {
releOn = on;
if (RELAY_ACTIVE_LOW) {
digitalWrite(RELAY_PIN, on ? LOW : HIGH);
} else {
digitalWrite(RELAY_PIN, on ? HIGH : LOW);
}
}
// ---- Callback MQTT: recebe 0/1 e aciona relé --------
void emqxCallback(char* topic, byte* payload, unsigned int length) {
char buf[32];
unsigned int n = (length < sizeof(buf) - 1) ? length : (sizeof(buf) - 1);
memcpy(buf, payload, n);
buf[n] = '\0';
bool comandoValido = false;
// Espera 0/1
if (!comandoValido) {
if (strchr(buf, '1')) {
releOn = true;
comandoValido = true;
} else if (strchr(buf, '0')) {
releOn = false;
comandoValido = true;
}
}
digitalWrite(RELAY_PIN, releOn ? HIGH : LOW);
Serial.print("[EMQX] Comando relé recebido: ");
Serial.print(buf);
Serial.print(" -> releOn=");
Serial.println(releOn ? "1" : "0");
}
// ---- Conexão WiFi -----------------------------------
void connectWiFi() {
Serial.print("[WiFi] Conectando...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\n[WiFi] Conectado!!!");
}
// ---- Conexão MQTT (MQTTX WEB / EMQX) -----------------
void connectEMQX() {
emqx.setServer(EMQX_BROKER, EMQX_PORT);
emqx.setCallback(emqxCallback);
while (!emqx.connected()) {
Serial.print("[EMQX] Conectando... ");
if (emqx.connect(EMQX_CLIENTID)) {
Serial.println(" conectado!");
emqx.subscribe(EMQX_SUB_TOPIC);
} else {
Serial.print("falhou (rc=");
Serial.print(emqx.state());
Serial.println("). Tentando novamente em 2s...");
delay(2000);
}
}
}
unsigned long lastMsg = 0;
// ---- Setup ------------------------------------------
void setup() {
Serial.begin(115200);
dht.begin();
pinMode(LDR_PIN, INPUT);
analogReadResolution(12);
servo.attach(SERVO_PIN, 500, 2400);
servo.write(servoPos);
pinMode(RELAY_PIN, OUTPUT);
setRelay(false); // inicia desligado
connectWiFi();
connectEMQX();
}
// ---- Loop -------------------------------------------
void loop() {
if (!emqx.connected())
connectEMQX();
emqx.loop();
unsigned long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
// ---- DHT22 --------------------------------------
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) return;
temperatura = t;
umidade = h;
// ---- LDR ----------------------------------------
int analogValue = analogRead(LDR_PIN);
float voltage = (analogValue / ADC_MAX) * VREF;
if (voltage < 0.001) voltage = 0.001;
if (voltage > VREF - 0.001) voltage = VREF - 0.001;
float resistance = R_DIV_OHMS * voltage / (VREF - voltage);
lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1.0 / GAMMA));
// ---- SERVO (Lux → Ângulo) -----------------------
float luxClamped = constrain(lux, 0.0, 100000.0);
servoPos = (int)(180.0 - (luxClamped / 100000.0) * 180.0);
servo.write(servoPos);
// ---- EMQX publish -------------------------------
snprintf(msg, sizeof(msg),
"{\"temperatura\": %.2f, \"umidade\": %.1f, \"lux\": %.1f, \"rele\": %d}",
temperatura, umidade, lux, (int)releOn);
emqx.publish(EMQX_PUB_TOPIC, msg);
// ---- Serial -------------------------------------
Serial.print("[EMQX] Publicado: ");
Serial.println(msg);
}
}