///////////////////////////////////////////////////////////////////////
/////////////////////// Bibliotecas //////////////////////////
///////////////////////////////////////////////////////////////////////
#include <WiFi.h> // Para conectar ao Wi-Fi
#include <PubSubClient.h> // Para a comunicação MQTT
#include <EEPROM.h>
///////////////////////////////////////////////////////////////////////
/////////////////////// Config Sensores //////////////////////////
///////////////////////////////////////////////////////////////////////
// Sensor de tensão
// #define SENSITIVITY 192.3024749756f // Ajuste de sensibilidade
// ZMPT101B voltageSensor(6, 60.0); // Pino de leitura do esp e frequencia da rede eletrica
///////////////////////////////////////////////////////////////////////
/////////////////////// Rede //////////////////////////
///////////////////////////////////////////////////////////////////////
// Definindo o nome e a senha da rede Wi-Fi
const char* ssid = "VMR";
const char* password = "Helo2101";
// Defina as credenciais do seu broker MQTT
const char* mqttServer = "broker.hivemq.com";
const int mqttPort = 1883;
const char* mqttUser = ""; // Caso o broker exija autenticação
const char* mqttPassword = ""; // Caso o broker exija autenticação
// Criando os objetos WiFi e MQTT
WiFiClient esp_tomada;
PubSubClient client(esp_tomada);
///////////////////////////////////////////////////////////////////////
/////////////////////// Pinos ////////////////////////////
///////////////////////////////////////////////////////////////////////
// Definindo os pinos analógicos para os sensores
#define s_corrente 5
#define s_tensao 6
// Definindo os pinos para os botões, leds e o relé
const unsigned int rele = 13;
const unsigned int botao_tomada = 12;
const unsigned int led_tomada = 11;
const unsigned int botao_zerar_contagem = 10;
const unsigned int led_zerar_contagem = 8;
const unsigned int botao_reconecar_rede = 1;
const unsigned int led_rede_conectada = 0;
const unsigned int led_esp_ligado = 7;
const unsigned int led_do_esp= 7;
///////////////////////////////////////////////////////////////////////
/////////////////////// Variáveis globais ////////////////////////////
///////////////////////////////////////////////////////////////////////
unsigned int long tempo_atual = millis();
bool tomada;
// Variaveis para os estados dos botões
bool b_tomada = true;
bool zerar_contagem = true;
bool reconecar_rede = true;
// Variaveis elétricas
// Tensão
float v = 0;
float v_rms = 0;
// Corrente
float i = 0;
float i_rms = 0;
// Potencia
float p_rms;
float energia_consumida = 0;
// Variaveis para testes, seram apagadas na conclusão do programa
float cont = 0;
float soma = 0;
float media = 0;
void setup() {
Serial.begin(115200);
pinMode(s_corrente, INPUT);
pinMode(s_tensao, INPUT);
pinMode(rele, OUTPUT);
pinMode(botao_tomada, INPUT_PULLUP);
pinMode(led_tomada, OUTPUT);
pinMode(botao_zerar_contagem, INPUT_PULLUP);
pinMode(led_zerar_contagem, OUTPUT);
pinMode(botao_reconecar_rede, INPUT_PULLUP);
pinMode(led_rede_conectada, OUTPUT);
pinMode(led_esp_ligado, OUTPUT);
digitalWrite(led_esp_ligado, HIGH);
// p_consumida = EEPROM.read(0);
// Tenta conectar ao Wi-Fi
Serial.println("Conectando-se ao Wi-Fi...");
WiFi.begin(ssid, password);
// Definindo o endereço do servidor MQTT
client.setServer(mqttServer, mqttPort);
// Define função de callback para tratar mensagens MQTT
client.setCallback(callback);
client.subscribe("tomada_app:-K/HyLNwbfp$(8_A@aeGWJt*!06gY12ATX~W)z@vjq8`1F4,D");
digitalWrite(led_do_esp, HIGH);
}
void verificando_Wifi() {
static bool conectado;
static unsigned long ultima_verficacao = 0;
const unsigned long intervalo = 5000;
if (WiFi.status() != WL_CONNECTED) {
digitalWrite(led_rede_conectada, LOW);
conectado = false;
// Verifica se já passou o tempo suficiente para tentar reconectar
if (tempo_atual - ultima_verficacao >= intervalo) {
Serial.println("Wi-Fi desconectado! Tentando conectar...");
WiFi.begin(ssid, password);
ultima_verficacao = tempo_atual; // Atualiza o tempo da última tentativa
}
} else if (conectado == false){
conectado = true;
digitalWrite(led_rede_conectada, HIGH);
Serial.println("Wi-Fi conectado!");
}
}
void reconectar_rede(){
WiFi.begin("", "");
}
void publicar(float valor, const char* topico){
if(client.connected())
{
char topico_completo[75];
sprintf(topico_completo, "%s:-K/HyLNwbfp$(8_A@aeGWJt*!06gY12ATX~W)z@vjq8`1F4,D", topico);
String msg = String(valor);
client.publish(topico_completo, msg.c_str());
}
}
// Função que tenta reconectar ao broker MQTT
void reconectar_broker(){
if ((!client.connected()) && (WiFi.status() == WL_CONNECTED))
{
static bool conectado;
static unsigned long ultima_verficacao = 0;
const unsigned long intervalo = 3000;
if ((!client.connected()) && (tempo_atual - ultima_verficacao >= intervalo))
{
Serial.println("Conectando ao broker MQTT...");
client.connect("esp_tomada");
client.subscribe("tomada_app:-K/HyLNwbfp$(8_A@aeGWJt*!06gY12ATX~W)z@vjq8`1F4,D");
ultima_verficacao = tempo_atual; // Atualiza o tempo da última tentativa
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
// Converta o payload para um inteiro
int value = 0;
for (int i = 0; i < length; i++) {
value = (value * 10) + (payload[i] - '0');
}
Serial.print("Valor recebido: ");
Serial.println(value);
switch (value)
{
case 0:
tomada = false;
break;
case 1:
tomada = true;
break;
}
f_tomada();
}
void ler_botoes(){
const unsigned int tempo_bounce = 250;
static unsigned long ultimo_b_tomada;
static unsigned long ultimo_zerar_contagem;
static unsigned long ultimo_reconecar_rede;
b_tomada = digitalRead(botao_tomada);
zerar_contagem = digitalRead(botao_zerar_contagem);
reconecar_rede = digitalRead(botao_reconecar_rede);
if ((b_tomada == LOW) && ((tempo_atual - ultimo_b_tomada) > tempo_bounce))
{
ultimo_b_tomada = tempo_atual;
f_tomada();
} else {
b_tomada = HIGH;
}
if ((zerar_contagem == LOW) && ((tempo_atual - ultimo_zerar_contagem) > tempo_bounce)) {
ultimo_zerar_contagem = tempo_atual;
} else {
zerar_contagem = HIGH;
}
if ((reconecar_rede == LOW) && ((tempo_atual - ultimo_reconecar_rede) > tempo_bounce)) {
ultimo_reconecar_rede = tempo_atual;
reconectar_rede();
} else {
reconecar_rede = HIGH;
}
}
void f_tomada(){ // Função para ligar ou desligar a tomada
if (!b_tomada)
{
tomada = !tomada;
}
if (tomada)
{
publicar(1, "tomada");
digitalWrite(rele, HIGH);
digitalWrite(led_tomada, HIGH);
}else{
publicar(0, "tomada");
digitalWrite(rele, LOW);
digitalWrite(led_tomada, LOW);
}
}
// void rms(float tensao, float corrente){
// const unsigned int amostras = 13; // 40
// static float vetor_v[amostras];
// static float vetor_i[amostras];
// static unsigned long ultima_amostra = 0;
// const unsigned int frequencia = 60;
// const unsigned int intervalo_amostras = 1500; // 500
// // Parâmetros do filtro passa-baixa exponencial
// const float alpha_v = 0.005; // Fator de suavização (entre 0 e 1)
// const float alpha_i = 0.05; // Fator de suavização (entre 0 e 1)
// static float v_filtrado = 0.0;
// static float i_filtrado = 0.0;
// static float v_rms_filtrado = 0.0;
// static float i_rms_filtrado = 0.0;
// // Parâmetros do filtro media movel
// const unsigned int v_tamanho_filtro = 840; // 2400 Quanto maior mais estável e com menos ruído, mas tende a não identificar picos
// const unsigned int i_tamanho_filtro = 84; // 240 Quanto maior mais estável e com menos ruído, mas tende a não identificar picos
// static float v_filtro[v_tamanho_filtro];
// static float i_filtro[i_tamanho_filtro];
// if (micros() - ultima_amostra >= intervalo_amostras){
// ultima_amostra = micros();
// // Movendo as amostras no vetor
// for (int i = 0; i < (amostras-1); i++) {
// vetor_v[i] = vetor_v[i + 1];
// vetor_i[i] = vetor_i[i + 1];
// }
// vetor_v[(amostras-1)] = tensao * tensao;
// vetor_i[(amostras-1)] = corrente * corrente;
// float soma_v = 0;
// float soma_i = 0;
// // Unrolling o loop para melhor desempenho
// for (int i = 0; i < amostras; i += 4) {
// soma_v += vetor_v[i] + vetor_v[i + 1] + vetor_v[i + 2] + vetor_v[i + 3];
// soma_i += vetor_i[i] + vetor_i[i + 1] + vetor_i[i + 2] + vetor_i[i + 3];
// }
// float rms_v_s_filtro = sqrt(soma_v / amostras);
// float rms_i_s_filtro = sqrt(soma_i / amostras);
// // Aplicando o filtro passa-baixa exponencial
// v_rms_filtrado = alpha_v * rms_v_s_filtro + (1 - alpha_v) * v_rms_filtrado;
// i_rms_filtrado = alpha_i * rms_i_s_filtro + (1 - alpha_i) * i_rms_filtrado;
// // Aplicando o filtro media movel
// for (int i = 0; i < (v_tamanho_filtro-1); i++) {
// v_filtro[i] = v_filtro[i + 1];
// }
// v_filtro[(v_tamanho_filtro-1)] = v_rms_filtrado;
// for (int i = 0; i < (i_tamanho_filtro-1); i++) {
// i_filtro[i] = i_filtro[i + 1];
// }
// i_filtro[(i_tamanho_filtro-1)] = i_rms_filtrado;
// soma_v = 0;
// soma_i = 0;
// for (int i = 0; i < v_tamanho_filtro; i += 4) {
// soma_v += v_filtro[i] + v_filtro[i + 1] + v_filtro[i + 2] + v_filtro[i + 3];
// }
// for (int i = 0; i < i_tamanho_filtro; i += 4) {
// soma_i += i_filtro[i] + i_filtro[i + 1] + i_filtro[i + 2] + i_filtro[i + 3];
// }
// v_rms = soma_v/v_tamanho_filtro;
// i_rms = soma_i/i_tamanho_filtro;
// p_rms = v_rms * i_rms;
// // Calcular o tempo desde a última medição
// static unsigned long ultimo_tempo = 0;
// unsigned long tempo_atual = micros();
// unsigned long delta_tempo = tempo_atual - ultimo_tempo; // Tempo em milissegundos
// ultimo_tempo = tempo_atual;
// // Acumular a energia consumida (em Joules)
// static float energia_acumulada;
// energia_acumulada += (p_rms * (delta_tempo / 1000000.0)); // Convertendo ms para segundos
// // Converter energia acumulada de Joules para kWh (1 kWh = 3600000 J)
// energia_consumida = energia_acumulada / 3600000.0;
// }
// }
void rms(float tensao, float corrente){
static unsigned long ultima_amostra = 0;
const unsigned int intervalo_amostras = 1100;
unsigned int long tempo_atual_m = micros();
if (tempo_atual_m - ultima_amostra >= intervalo_amostras)
{
// Serial.println(tempo_atual_m - ultima_amostra);
ultima_amostra = tempo_atual_m;
const unsigned int amostras = 37;
static float vetor_v[amostras];
static float vetor_i[amostras];
// Filtro passa-baixa exponencial
const float alpha_v = 0.001;
const float alpha_i = 0.05;
static unsigned int v_idx = 0; // Índices circulares
static unsigned int i_idx = 0;
// Cálculo do quadrado das tensões e correntes e inserção direta
vetor_v[v_idx % amostras] = tensao * tensao;
vetor_i[i_idx % amostras] = corrente * corrente;
v_idx++;
i_idx++;
float soma_v = 0;
float soma_i = 0;
// Soma dos valores sem loop unrolling
for (int i = 0; i < amostras; i++) {
soma_v += vetor_v[i];
soma_i += vetor_i[i];
}
float rms_v_s_filtro = sqrt(soma_v / amostras);
float rms_i_s_filtro = sqrt(soma_i / amostras);
// Aplicando o filtro passa-baixa exponencial
v_rms = alpha_v * rms_v_s_filtro + (1 - alpha_v) * v_rms;
i_rms = alpha_i * rms_i_s_filtro + (1 - alpha_i) * i_rms;
p_rms = v_rms * i_rms;
// Calcular o tempo decorrido
static unsigned long ultimo_tempo = 0;
unsigned long delta_tempo = tempo_atual_m - ultimo_tempo;
ultimo_tempo = tempo_atual_m;
// Acumular energia consumida
static float energia_acumulada = 0;
energia_acumulada += (p_rms * (delta_tempo / 1000000.0));
// Converter para kWh
energia_consumida = energia_acumulada / 3600000.0;
}
}
void loop(){
tempo_atual = millis();
client.loop();
i = (8*analogRead(s_corrente))/819 -20;
v = (100 * (float(analogRead(s_tensao))))/819 -233;
rms(v, i);
ler_botoes();
verificando_Wifi();
reconectar_broker();
static unsigned long ultima_publi = 0;
if ((tempo_atual - ultima_publi) >= 200)
{
// Serial.println(v_rms);
ultima_publi = tempo_atual;
publicar(v_rms, "tensao");
}
}
Loading
esp32-c6-devkitc-1
esp32-c6-devkitc-1