#include <EspMQTTClient.h>
#include <ArduinoJson.h>
#include <OneWire.h>
#include <DallasTemperature.h>
/**
* Projeto SA – MEDIDOR DE QUALIDADE DA ÁGUA
*
* Este código implementa um sistema de medição de qualidade da água
* utilizando um ESP32, sensores de distância (HC-SR04), temperatura (DS18B20),
* e turbidez (sensor analógico). Os dados são enviados para a plataforma Tago.io
* via MQTT.
*/
#define PINO_TRIG 26 // Pino conectado ao TRIG do HC-SR04
#define PINO_ECHO 27 // Pino conectado ao ECHO do HC-SR04
#define ONE_WIRE_BUS 4 // Pino de dados do DS18B20 conectado ao pino 4 do ESP32
#define ANALOG_PIN 14 // Pino analógico para leitura da qualidade da água
int distanciaAnterior = 0;
int temperaturaAnterior = 0;
int ntuAnterior = 0;
bool mudouValorSensores = false;
char buff_d[7];
char buff_t[7];
int a = 16478; // Coeficiente 'a' da equação quadrática para cálculo de NTU
int b = -65461; // Coeficiente 'b' da equação quadrática para cálculo de NTU
int c = 26763; // Coeficiente 'c' da equação quadrática para cálculo de NTU
// Configuração de conexão Wi-Fi e MQTT
EspMQTTClient client(
"Wokwi-GUEST", // Nome da rede Wi-Fi
"", // Senha da rede Wi-Fi
"mqtt.tago.io", // Endereço do broker MQTT
"Default", // Usuário MQTT (qualquer string)
"32a58d48-fab8-4cf0-959d-ccac5f046210", // Token da plataforma Tago.io
"SA_IOT_2024" // Identificação única do dispositivo (qualquer string)
);
// Configuração do OneWire e do sensor de temperatura DallasTemperature
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
/**
* @brief Calcula o valor de NTU (Turbidez) com base na leitura analógica.
*
* @param leituraAnalogica Leitura analógica do sensor de turbidez.
* @return int Valor de NTU calculado.
*/
int calcularNTU(int leituraAnalogica) {
return a * leituraAnalogica * leituraAnalogica + b * leituraAnalogica + c;
}
/**
* @brief Função chamada periodicamente para realizar medições e publicar os dados.
*
* Esta função mede a distância, a temperatura e a turbidez da água,
* verifica se houve mudanças significativas nos valores e publica
* os dados via MQTT se houver alterações.
*/
void delayedFunction() {
DynamicJsonDocument dados(1024);
String dadosJson;
// Medição da distância
digitalWrite(PINO_TRIG, LOW);
delayMicroseconds(2);
digitalWrite(PINO_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PINO_TRIG, LOW);
long duracao = pulseIn(PINO_ECHO, HIGH);
int distanciaAtual = round((duracao * 0.0343) / 2); // Arredonda para o inteiro mais próximo
// Medição da temperatura
sensors.requestTemperatures();
int temperaturaAtual = round(sensors.getTempCByIndex(0)); // Converte para inteiro
// Lógica para leitura analógica e cálculo do valor de NTU
int somaAnalogValue = 0;
for (int i = 0; i < 100; i++) {
somaAnalogValue += analogRead(ANALOG_PIN); // Lê o valor analógico do pino definido
}
int analogValue = somaAnalogValue / 100; // Calcula o valor médio
int ntuAtual = calcularNTU(analogValue); // Calcula o valor de NTU usando a equação de calibração
// Verifica se houve mudança nos valores dos sensores
if (distanciaAtual != distanciaAnterior) {
mudouValorSensores = true;
distanciaAnterior = distanciaAtual;
}
if (temperaturaAtual != temperaturaAnterior) {
mudouValorSensores = true;
temperaturaAnterior = temperaturaAtual;
}
if (ntuAtual != ntuAnterior) {
mudouValorSensores = true;
ntuAnterior = ntuAtual;
}
// Publica os dados se houve mudança nos sensores
if (mudouValorSensores) {
dados[0]["variable"] = "valor_distancia";
dados[0]["unit"] = "cm";
snprintf(buff_d, sizeof(buff_d), "%d", distanciaAtual);
dados[0]["value"] = buff_d;
dados[1]["variable"] = "valor_temperatura";
dados[1]["unit"] = "°C";
snprintf(buff_t, sizeof(buff_t), "%d", temperaturaAtual);
dados[1]["value"] = buff_t;
dados[2]["variable"] = "turbidez_ntu";
dados[2]["unit"] = "NTU";
snprintf(buff_t, sizeof(buff_t), "%d", ntuAtual);
dados[2]["value"] = buff_t;
serializeJson(dados, dadosJson);
Serial.println("Publicando a leitura dos sensores de qualidade da água....");
Serial.println(dadosJson);
client.publish("le_dados_qualidade_agua", dadosJson);
mudouValorSensores = false; // Reseta a flag após a publicação
}
client.executeDelayed(5000, delayedFunction); // Agenda a próxima execução da função
}
/**
* @brief Configuração inicial do dispositivo.
*
* Esta função é chamada uma vez no início do programa para configurar
* os pinos, iniciar a comunicação serial e inicializar os sensores.
*/
void setup() {
client.enableDebuggingMessages(true);
client.setMaxPacketSize(2048);
client.executeDelayed(5000, delayedFunction);
pinMode(PINO_TRIG, OUTPUT);
pinMode(PINO_ECHO, INPUT);
pinMode(ONE_WIRE_BUS, INPUT); // Configura o pino do sensor DS18B20 como entrada
pinMode(ANALOG_PIN, INPUT); // Configura o pino analógico como entrada
Serial.begin(115200);
sensors.begin(); // Inicializa o sensor DS18B20
}
/**
* @brief Loop principal do programa.
*
* Esta função é chamada continuamente após a função setup().
* Ela mantém a conexão MQTT ativa e processa as mensagens recebidas.
*/
void loop() {
client.loop();
}
/**
* @brief Função chamada quando a conexão MQTT é estabelecida.
*
* Esta função se inscreve no tópico "le_dados_qualidade_agua" para
* receber e processar mensagens publicadas nesse tópico.
*/
void onConnectionEstablished() {
client.subscribe("le_dados_qualidade_agua", [] (const String &payload) {});
}