// ==========================================
// 🌐 1. Blynk 模板信息 (填入你自己的 Token)
// ==========================================
#define BLYNK_TEMPLATE_ID "TMPL6Tn7KrDa6"
#define BLYNK_TEMPLATE_NAME "Smart Microgrid"
#define BLYNK_AUTH_TOKEN "-KS5dp5oEuiiPyn1T9ZXE5XyBGTL2ul5"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// ==========================================
// 📍 2. 硬件引脚定义 (Wokwi 模拟版)
// ==========================================
#define LED_PIN 18 // 连接红色 LED (模拟 3W 大灯)
#define FAN_PIN 19 // 连接绿色 LED (模拟风扇)
#define POT_SOLAR 34 // 旋钮 1:模拟太阳能功率变化
#define POT_BAT 35 // 旋钮 2:模拟电池电压变化
LiquidCrystal_I2C lcd(0x27, 20, 4);
BlynkTimer timer;
// Wokwi 专属免密 WiFi,请勿修改
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
void setup() {
Serial.begin(115200);
// 初始化控制引脚
pinMode(FAN_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(FAN_PIN, HIGH); // 模拟软件 NC 逻辑:开机风扇立刻转
digitalWrite(LED_PIN, LOW); // 默认关灯
// 初始化 LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0); lcd.print("WOKWI SIMULATION");
lcd.setCursor(0, 1); lcd.print("Connecting Blynk...");
// 连接 Blynk 云端
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
lcd.setCursor(0, 1); lcd.print("Blynk Connected! ");
delay(1000);
lcd.clear();
// 开启定时器:每 1 秒(1000毫秒)执行一次调度算法,拒绝使用 delay()!
timer.setInterval(1000L, smartMicrogridAlgorithm);
}
void smartMicrogridAlgorithm() {
// --------------------------------------------------
// 🔮 【模拟数据读取】从旋钮读取模拟信号
// --------------------------------------------------
int valSolar = analogRead(POT_SOLAR);
int valBat = analogRead(POT_BAT);
// 将旋钮 1 映射为 0.00W 到 15.00W 的太阳能收入
float solar_W = map(valSolar, 0, 4095, 0, 1500) / 100.0;
// 将旋钮 2 映射为 6.00V 到 8.40V 的电池电压
float load_V = map(valBat, 0, 4095, 600, 840) / 100.0;
// 根据物理公式,反向推算出模拟电流,供仪表盘展示
float solar_mA = (solar_W * 1000.0) / 12.0; // 假设太阳能端恒压 12V
// --------------------------------------------------
// 🔋 【SoC % 计算逻辑】
// --------------------------------------------------
int batterySoC = map(load_V * 100, 600, 840, 0, 100);
batterySoC = constrain(batterySoC, 0, 100); // 限制在 0-100% 之间
// --------------------------------------------------
// 🧠 【Smart EMS 智能甩负荷控制算法】
// --------------------------------------------------
String systemMode = "NORMAL";
int ledStatus = 0;
int fanStatus = 1;
if (batterySoC <= 20) {
digitalWrite(LED_PIN, LOW); // 电量低于 20%,触发生存模式,强制关灯!
systemMode = "SURVIVAL";
ledStatus = 0;
}
else if (batterySoC >= 30) {
digitalWrite(LED_PIN, HIGH); // 电量回充到 30% 以上,恢复健康状态,开灯!
systemMode = "HEALTHY ";
ledStatus = 1;
}
// ⚡ 动态总功耗模拟计算(灯开了功耗就会增加,极其真实)
float load_W = 0.5; // ESP32 基础功耗 0.5W
if (fanStatus == 1) load_W += 1.5; // 加上风扇 1.5W
if (ledStatus == 1) load_W += 3.0; // 加上大灯 3.0W
float load_mA = (load_W * 1000.0) / load_V; // 算出总消耗电流
// 计算微电网财务收支净功率
float net_W = solar_W - load_W;
// --------------------------------------------------
// 🖥️ 【LCD 2004 屏幕显示】
// --------------------------------------------------
lcd.setCursor(0, 0);
lcd.print("Bat: "); lcd.print(load_V, 2); lcd.print("V "); lcd.print(batterySoC); lcd.print("% ");
lcd.setCursor(0, 1);
lcd.print("In : "); lcd.print(solar_W, 2); lcd.print(" W ");
lcd.setCursor(0, 2);
lcd.print("Out: "); lcd.print(load_W, 2); lcd.print(" W ");
lcd.setCursor(0, 3);
lcd.print("Net: ");
if (net_W >= 0) lcd.print("+");
lcd.print(net_W, 2); lcd.print(" W ");
// --------------------------------------------------
// ☁️ 【Blynk 全数据流打包上报】
// --------------------------------------------------
Blynk.virtualWrite(V0, load_V); // V0: 电池电压 (V)
Blynk.virtualWrite(V1, solar_W); // V1: 太阳能功率 (W)
Blynk.virtualWrite(V2, load_W); // V2: 负载总功率 (W)
Blynk.virtualWrite(V3, systemMode); // V3: 系统模式文字
Blynk.virtualWrite(V4, fanStatus); // V4: 风扇开关状态 (1/0)
Blynk.virtualWrite(V5, ledStatus); // V5: 大灯开关状态 (1/0)
Blynk.virtualWrite(V6, solar_mA); // V6: 太阳能电流 (mA)
Blynk.virtualWrite(V7, load_mA); // V7: 负载总电流 (mA)
Blynk.virtualWrite(V8, batterySoC); // V8: 电池百分比 (%)
}
void loop() {
Blynk.run();
timer.run();
}