// --- Credenciales Blynk (rellena con las tuyas) ---
#define BLYNK_TEMPLATE_ID "TMPL25vWpbLjv"
#define BLYNK_TEMPLATE_NAME "Expansor ESP32"
#define BLYNK_AUTH_TOKEN "ThZyXYC6glYkunMS2oJLN9NLwe_se5bO"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Wokwi-GUEST"; // ← CORREGIDO (case sensitive)
char pass[] = "";
// --- Pines ES32C14 ---
const int IN1 = 19, IN2 = 18, IN3 = 5, IN4 = 17;
const int CH1 = 27, CH2 = 14, CH3 = 12, CH4 = 13;
const int Vi1 = 36, Vi2 = 39, Ii1 = 34, Ii2 = 35;
const int RS485RD = 22;
// --- Variables de estado (comandos desde Blynk) ---
bool cmd_CH1 = false;
bool cmd_CH2 = false;
bool cmd_CH3 = false;
bool cmd_CH4 = false;
// --- Lecturas analógicas ---
float in_value[4];
unsigned long lastMeasureTime = 0;
const unsigned long measureInterval = 1000;
// --- Función para leer sensores ---
void leerSensores() {
digitalWrite(RS485RD, HIGH);
int raw[4];
raw[0] = analogRead(Vi1);
raw[1] = analogRead(Vi2);
raw[2] = analogRead(Ii1);
raw[3] = analogRead(Ii2);
in_value[0] = (float)raw[0] * 3300.0 / 4096.0 / 1000.0 * 53.0 / 10.0 + 0.6;
in_value[1] = (float)raw[1] * 3300.0 / 4096.0 / 1000.0 * 53.0 / 10.0 + 0.6;
in_value[2] = (float)raw[2] * 3300.0 / 4096.0 / 1000.0 + 0.12 / 91.0 * 1000.0;
in_value[3] = (float)raw[3] * 3300.0 / 4096.0 / 1000.0 + 0.12 / 91.0 * 1000.0;
digitalWrite(RS485RD, LOW);
}
// --- Handlers para recibir comandos desde Blynk (Virtual Pins V4-V7) ---
BLYNK_WRITE(V4) {
cmd_CH1 = param.asInt(); // true (1) o false (0)
}
BLYNK_WRITE(V5) {
cmd_CH2 = param.asInt();
}
BLYNK_WRITE(V6) {
cmd_CH3 = param.asInt();
}
BLYNK_WRITE(V7) {
cmd_CH4 = param.asInt();
}
void setup() {
Serial.begin(115200);
// Configurar pines
pinMode(CH1, OUTPUT); pinMode(CH2, OUTPUT);
pinMode(CH3, OUTPUT); pinMode(CH4, OUTPUT);
pinMode(IN1, INPUT_PULLUP); pinMode(IN2, INPUT_PULLUP);
pinMode(IN3, INPUT_PULLUP); pinMode(IN4, INPUT_PULLUP);
pinMode(Vi1, INPUT); pinMode(Vi2, INPUT);
pinMode(Ii1, INPUT); pinMode(Ii2, INPUT);
pinMode(RS485RD, OUTPUT);
digitalWrite(RS485RD, LOW);
// Apagar relés al inicio
digitalWrite(CH1, LOW); digitalWrite(CH2, LOW);
digitalWrite(CH3, LOW); digitalWrite(CH4, LOW);
analogReadResolution(12);
// Configurar la atenuación para TODOS los pines ADC
analogSetAttenuation(ADC_11db);
// Conectar a Blynk
Blynk.begin(auth, ssid, pass);
Serial.println("Conectando a Blynk en Wokwi...");
}
void loop() {
Blynk.run(); // Mantiene la conexión y ejecuta los handlers
if (!Blynk.connected()) {
Serial.println("❌ Blynk NO conectado");
} else {
// Esto solo lo imprimirá una vez para no saturar
static bool yaConectado = false;
if (!yaConectado) {
Serial.println("✅ Blynk conectado");
yaConectado = true;
}
}
// Leer sensores cada 1 segundo y enviar a Blynk
unsigned long currentMillis = millis();
if (currentMillis - lastMeasureTime >= measureInterval) {
lastMeasureTime = currentMillis;
leerSensores();
// IMPRESIÓN EXPLÍCITA DE CADA VALOR (por si printf falla)
Serial.println("=== LECTURAS ANALÓGICAS ===");
Serial.print("Vi1: "); Serial.print(in_value[0], 2); Serial.println(" V");
Serial.print("Vi2: "); Serial.print(in_value[1], 2); Serial.println(" V");
Serial.print("Ii1: "); Serial.print(in_value[2], 2); Serial.println(" mA");
Serial.print("Ii2: "); Serial.print(in_value[3], 2); Serial.println(" mA");
Serial.println("============================");
// Enviar valores a Blynk (Virtual Pins V0-V3)
Serial.println("Enviando a Blynk...");
Blynk.virtualWrite(V0, in_value[0]); // Vi1
Blynk.virtualWrite(V1, in_value[1]); // Vi2
Blynk.virtualWrite(V2, in_value[2]); // Ii1
Blynk.virtualWrite(V3, in_value[3]); // Ii2
}
/*/ --- Detección de flanco descendente para pulsadores físicos
// Este trozo de codigo es para usar pulsadores en vez de switch, pero no trabaja al 100% desde Blynk---
static bool lastIN1 = HIGH, lastIN2 = HIGH, lastIN3 = HIGH, lastIN4 = HIGH;
bool in1 = digitalRead(IN1);
bool in2 = digitalRead(IN2);
bool in3 = digitalRead(IN3);
bool in4 = digitalRead(IN4);
// Si el botón se presiona (pasa de HIGH a LOW), invertimos el comando y actualizamos Blynk
if (in1 == LOW && lastIN1 == HIGH) {
cmd_CH1 = !cmd_CH1;
Blynk.virtualWrite(V4, cmd_CH1);
}
lastIN1 = in1;
if (in2 == LOW && lastIN2 == HIGH) {
cmd_CH2 = !cmd_CH2;
Blynk.virtualWrite(V5, cmd_CH2);
}
lastIN2 = in2;
if (in3 == LOW && lastIN3 == HIGH) {
cmd_CH3 = !cmd_CH3;
Blynk.virtualWrite(V6, cmd_CH3);
}
lastIN3 = in3;
if (in4 == LOW && lastIN4 == HIGH) {
cmd_CH4 = !cmd_CH4;
Blynk.virtualWrite(V7, cmd_CH4);
}
lastIN4 = in4;
// --- Control de salidas (siguen el comando) ---
digitalWrite(CH1, cmd_CH1 ? HIGH : LOW);
digitalWrite(CH2, cmd_CH2 ? HIGH : LOW);
digitalWrite(CH3, cmd_CH3 ? HIGH : LOW);
digitalWrite(CH4, cmd_CH4 ? HIGH : LOW);*/
//-------------------------------------------------------------------
// --- Lógica de Control Combinada (CORRECTA) ---
digitalWrite(CH1, (digitalRead(IN1) == LOW || cmd_CH1) ? HIGH : LOW);
digitalWrite(CH2, (digitalRead(IN2) == LOW || cmd_CH2) ? HIGH : LOW);
digitalWrite(CH3, (digitalRead(IN3) == LOW || cmd_CH3) ? HIGH : LOW);
digitalWrite(CH4, (digitalRead(IN4) == LOW || cmd_CH4) ? HIGH : LOW);
/*/ --- Sincronizar estado con Blynk (solo si cambia) ---
static bool lastCH1 = false, lastCH2 = false, lastCH3 = false, lastCH4 = false;
bool ch1 = digitalRead(CH1);
bool ch2 = digitalRead(CH2);
bool ch3 = digitalRead(CH3);
bool ch4 = digitalRead(CH4);
if (ch1 != lastCH1) {
Blynk.virtualWrite(V4, ch1);
lastCH1 = ch1;
}
if (ch2 != lastCH2) {
Blynk.virtualWrite(V5, ch2);
lastCH2 = ch2;
}
if (ch3 != lastCH3) {
Blynk.virtualWrite(V6, ch3);
lastCH3 = ch3;
}
if (ch4 != lastCH4) {
Blynk.virtualWrite(V7, ch4);
lastCH4 = ch4;
}*/
// --- Sincronización periódica con Blynk (cada 200ms) ---
static unsigned long lastSync = 0;
if (millis() - lastSync > 200) {
lastSync = millis();
Blynk.virtualWrite(V4, digitalRead(CH1));
Blynk.virtualWrite(V5, digitalRead(CH2));
Blynk.virtualWrite(V6, digitalRead(CH3));
Blynk.virtualWrite(V7, digitalRead(CH4));
}
}