//=================================================================
//
// Exemplo de aplicação com Esp32, LCD I2C 20x4, módulo LDR,
// potenciômetro, DHT22 (na simulação, porém utilizado o DHT11 no
// hardware físico), botão, leds vermelho/verde de indicação de
// modo e barramento de leds para visualização do ajuste quando
// modo local.
//
// Autor: Jorge Sebastião Canova - out/2024
// Prof. na Etec Profa. Anna de Oliveira Ferraz em Araraquara/SP
//
// Bibliotecas ===================================================
#include <DHT.h> // comunicação com DHT11/DHT22
#include <WiFi.h> // conexão com rede WiFi
#include <LiquidCrystal_I2C.h> // controle do LCD I2C
#include <ESP32Servo.h> // controle do Servomotor
#include <WebSocketsServer.h> // conexão via WebSockets
// Definições e apelidos =========================================
#define dhttype DHT11 // modelo do sensor, DHT11 ou DHT22
#define dhtpin 23 // recebe dados do DHT
#define potpin 33 // recebe tensão do potenciômetro
#define servopin 16 // gera PWM para o servo
#define ldrd0pin 17 // recebe sinal digital do LDR (D0)
#define ldra0pin 32 // recebe sinal analógico do LDR (A0)
#define ledpin 18 // controla os leds
#define buttonpin 5 // recebe estado do botão
// Variáveis e constantes ========================================
const int leds[10] = {4,0,2,15,13,12, // sequência dos pinos
14,27,26,25}; // dos leds em linha
//const char* ssid = "teste"; // nome e senha de acesso à
//const char* password = "teste"; // rede WiFi
const char* ssid = "Wokwi-GUEST"; // nome e senha de acesso à
const char* password = ""; // rede WiFi
byte grau[8] = { B00001100, B00010010, B00010010, // máscara para
B00001100, B00000000, B00000000, // símbolo do
B00000000, B00000000}; // grau --> °
DHT dht(dhtpin, dhttype); // instâncias dos objetos
Servo servo; // dht, servo, lcd e websks
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
WebSocketsServer websks = WebSocketsServer(81);
float dhttemp; // valor da temperatura
float dhtumid; // valor da umidade relativa
unsigned int ldrvalord0; // estado on/off do LDR
unsigned int ldrvalora0; // nível analógico do LDR
unsigned int servoangulo, servoanguloremoto; // ângulos do servo
unsigned int potvalor; // valor do potenciômetro
byte potlocal = 0; // configuração potenciômetro local/remoto
byte oldstate = 0; // último estado do botão
unsigned long ultimotempo1 = 0; // ultimo tempo de envio
const unsigned long intervalotempo1 = 5000; // intervalo de envio
unsigned long ultimotempo2 = 0; // ultimo tempo de envio
const unsigned long intervalotempo2 = 300; // intervalo de envio
// Prototipação ==================================================
void atualizar_mascara();
void atualizar_leds();
// Função setup() ================================================
void setup() {
// Configurando I/Os digitais
pinMode(ldrd0pin, INPUT);
pinMode(buttonpin, INPUT);
pinMode(ledpin, OUTPUT);
digitalWrite(ledpin, LOW);
for (int i=0;i<10;i++) {
pinMode(leds[i], OUTPUT);
digitalWrite(leds[i], LOW);
}
// Iniciando Monitor Serial
Serial.begin(115200);
// Iniciando Servo
servo.attach(servopin,600,2300);
servo.write(0);
// Iniciando sensor DHT
dht.begin();
Serial.println("Iniciando Sensor DHT...");
// Iniciando display
Serial.println("Iniciando LCD I2C...");
lcd.init();
lcd.backlight();
lcd.clear();
lcd.createChar(0, grau);
// Conectando à rede Wifi
Serial.print("Conectando à rede "); Serial.print(ssid);
Serial.print("...");
lcd.setCursor(0,0); lcd.print("Conectando a rede ");
lcd.setCursor(0,1); lcd.print(ssid); lcd.print("..."); WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password,6);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
lcd.setCursor(0,2); lcd.print("Conectado!");
lcd.setCursor(0,3); lcd.print("IP:"); lcd.print(WiFi.localIP());
Serial.print(" WiFi connectado! IP: ");
Serial.println(WiFi.localIP());
// Iniciando servidor WebSocket
websks.begin();
websks.onEvent(websksevent); // callback de eventos do WebSocket
delay(2000);
lcd.clear();
}
// Função loop() =================================================
void loop() {
websks.loop(); // servidor WebSocket em execução
unsigned long tempoatual = millis();
if (tempoatual - ultimotempo2 >= intervalotempo2) {
ultimotempo2 = tempoatual;
ler_parametros(); // executa leitura de sensores e variáveis
atualizar_mascara(); // atualiza display e saídas
atualizar_leds(); // atualizar sequência de leds
}
if (tempoatual - ultimotempo1 >= intervalotempo1) {
ultimotempo1 = tempoatual;
String msgparametros = String(dhttemp)+";"+
String(dhtumid)+";"+
String(ldrvalord0)+";"+
String(ldrvalora0)+";"+
String(servoangulo)+";"+
String(servoanguloremoto)+";"+
String(potvalor)+";"+
String(potlocal)+";"+
WiFi.localIP().toString(false);
websks.broadcastTXT(msgparametros);
}
}
// Função ler_parametros() ======================================
void ler_parametros() {
// Leitura de valores de temperatura e umidade do DHT
dhttemp = dht.readTemperature();
dhtumid = dht.readHumidity();
if (isnan(dhtumid) || isnan(dhttemp)) {
Serial.println("Falha! DHT não conectado!");
}
// Leitura de valores analógico e digital do LDR
ldrvalora0 = analogRead(ldra0pin);
ldrvalord0 = digitalRead(ldrd0pin);
// Leitura do valor analógico do potenciômetro
potvalor = analogRead(potpin);
// Definindo ângulo do servo a partir do estado manual/auto
if (potlocal) servoangulo = map(potvalor, 0, 4095, 0, 180);
else servoangulo = servoanguloremoto;
// Botão para inversão do estado manual/auto
if (digitalRead(buttonpin) && !oldstate) {
oldstate = 1;
potlocal = !potlocal;
}
if (!digitalRead(buttonpin)) oldstate = 0;
}
// Função atualizar_mascara() ===================================
void atualizar_mascara() {
// Escrevendo dados do DHT
lcd.setCursor(0,0); lcd.print("DHT:");
lcd.print(dhttemp); lcd.write((byte)0); lcd.print("C ");
lcd.print(dhtumid); lcd.print("% ");
// Escrevendo dados do LDR
lcd.setCursor(0,1); lcd.print("LDR:");
lcd.print(ldrvalora0); lcd.print(" ");
if (ldrvalord0==1) lcd.print("On "); else lcd.print("Off");
// Escrevendo dados do potenciômetro e estado remoto/local
lcd.setCursor(0,2); lcd.print("Pot:");
lcd.print(potvalor); lcd.print(" ");
lcd.print(servoangulo); lcd.write((byte)0);
if (potlocal) lcd.print(" local "); else lcd.print(" remoto ");
// Escrevendo IP
lcd.setCursor(0,3); lcd.print("IP: ");
lcd.print(WiFi.localIP());
// Ajustando posição do servo
servo.write(servoangulo);
// Controle leds manual/auto
digitalWrite(ledpin,!potlocal);
}
// Função atualizar_leds() ======================================
void atualizar_leds() {
// Controlando leds a partir do valor de angulo do servo
for (int i = 0; i<10; i++) {
digitalWrite(leds[i],servoangulo>=i*18);
}
}
// Função websksevent() =========================================
void websksevent(uint8_t numero_msg, WStype_t type,
uint8_t * conteudo_recebido,
size_t tamanho_conteudo) {
switch(type) { // Verifica o tipo de evento
case WStype_DISCONNECTED: // desconectou-se
Serial.printf("[%u] Desconectou!\n", numero_msg);
break;
case WStype_CONNECTED: // conectou-se
Serial.printf("[%u] Conectou!\n", numero_msg);
websks.sendTXT(numero_msg, "Conectou");
break;
case WStype_TEXT: // mensagem recebida
Serial.printf("[%u] Recebeu pelo Socket o texto: %s.\n",
numero_msg, conteudo_recebido);
int valor = atoi((char *)conteudo_recebido);
if (valor >= 0 && valor <= 180) {
servoanguloremoto = valor;
}
break;
}
}