#define BLYNK_TEMPLATE_ID "TMPL3fXDSrrWP"
#define BLYNK_TEMPLATE_NAME "Smart Plug Basic v1"
#define BLYNK_AUTH_TOKEN "bsbb2Hz4nmZqDAeCtlNOlJSsRaJrZzpn"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
#define RELAY_PIN 3 // D1
#define LED_PIN 8 // D8
#define BUTTON_PIN 4 // D2 -> GND
#define ADC_PIN 0 // D0 -> potentiometer wiper (change if needed)
// Blynk virtual pins
// V1 = main switch (already used)
// V2 = duration menu (+30/+60/...)
const int V_POT_RAW = V5; // raw ADC value (0-4095)
const int V_POT_MV = V6; // voltage in mV
BlynkTimer timer;
// state vars
bool relayState = false;
bool countdownActive = false;
unsigned long countdownEndMillis = 0;
bool lastButtonState = HIGH;
// helper to set relay + LED and sync V1
void setRelay(bool on) {
relayState = on;
digitalWrite(RELAY_PIN, on ? HIGH : LOW);
digitalWrite(LED_PIN, on ? HIGH : LOW);
Blynk.virtualWrite(V1, on ? 1 : 0);
}
/* ---------- BLYNK callbacks for V1 & V2 (unchanged) ---------- */
// V1 - main ON/OFF (app)
BLYNK_WRITE(V1) {
int value = param.asInt();
setRelay(value == 1);
if (value == 0) countdownActive = false;
}
// V2 - Menu for timer
// Item 1: No timer; 2: +30; 3: +60; 4: +90
BLYNK_WRITE(V2) {
int sel = param.asInt();
int minutes = 0;
if (sel == 2) minutes = 30;
else if (sel == 3) minutes = 60;
else if (sel == 4) minutes = 90;
else minutes = 0;
if (minutes > 0) {
setRelay(true);
countdownActive = true;
countdownEndMillis = millis() + (unsigned long)minutes * 60UL * 1000UL;
Serial.print("Countdown started for "); Serial.print(minutes); Serial.println(" min");
} else {
countdownActive = false;
Serial.println("Countdown cancelled from menu");
}
}
/* ---------- Potentiometer reading ---------- */
void readPotAndSend() {
// Read raw ADC
// ESP32 ADC is 12-bit by default -> 0..4095
int raw = analogRead(ADC_PIN);
// Convert to millivolts (approx)
// Reference full-scale = 3.3V = 3300 mV
// Adjust if you calibrate or use attenuation
long mV = (long)raw * 3300L / 4095L;
// Optionally map to percentage:
int percent = map(raw, 0, 4095, 0, 100);
// Send to Blynk
Blynk.virtualWrite(V_POT_RAW, raw);
Blynk.virtualWrite(V_POT_MV, mV);
// Print to serial for debugging
Serial.print("Pot raw: "); Serial.print(raw);
Serial.print(" mV: "); Serial.print(mV);
Serial.print(" %: "); Serial.println(percent);
}
/* ---------- Countdown + Button check ---------- */
void checkCountdown() {
if (countdownActive && millis() > countdownEndMillis) {
countdownActive = false;
setRelay(false);
Serial.println("Countdown finished -> OFF");
}
}
void checkButton() {
bool current = digitalRead(BUTTON_PIN);
if (current == LOW && lastButtonState == HIGH) {
delay(30);
if (digitalRead(BUTTON_PIN) == LOW) {
setRelay(!relayState);
Serial.print("Button pressed -> ");
Serial.println(relayState ? "ON" : "OFF");
// manual press cancels countdown
countdownActive = false;
}
}
lastButtonState = current;
}
/* ---------- setup & loop ---------- */
void setup() {
Serial.begin(115200);
pinMode(RELAY_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(ADC_PIN, INPUT); // analogRead uses this
setRelay(false);
// Start WiFi / Blynk (blocking)
Serial.println("Connecting to Blynk/WiFi...");
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
Serial.println("Blynk connected");
// timers:
timer.setInterval(1000L, checkCountdown); // every 1s
timer.setInterval(1000L, readPotAndSend); // pot every 1s
timer.setInterval(50L, checkButton); // fast button poll
}
void loop() {
Blynk.run();
timer.run();
}Loading
xiao-esp32-c3
xiao-esp32-c3