可以 —— 手机通过免费的 Blynk IoT 云端就能开关继电器:在 console.blynk.cloud 建一个模板,把它的三行 #define 复制到下面 sketch 的最顶端,再用三根杜邦线把 5 V 继电器模块接上 ESP32。这篇还把大多数教程跳过的那部分补齐:断网时照样能用的开关。
用手机控制继电器需要什么?
Blynk 继电器项目是一条四环链路:手机上的 Blynk App 跟 Blynk 云端对话,云端把每一次开关经家里的 Wi-Fi 推送到 ESP32,再由 ESP32 的一个引脚驱动继电器模块,让它的触点去切换真正的负载 —— 12 V 风扇、LED 灯条或水泵。
材料清单 —— 手机控制继电器,全程免焊
Parts list
| Item | Price | Qty | |
|---|---|---|---|
NodeMCU ESP32 Wi-Fi + Bluetooth Development Board CH340/CP2012 - For IOT Project - ESP32 30PIN EXPANSION BOARD32DEVBD-X32ECH34 | RM8.90 |
可选的 30 针扩展板,正好安放这块 DevKit —— 每个引脚都在 5V 和 GND 电源轨旁引出,还带一个 DC 圆孔电源座。等你开始加更多继电器和传感器时,它就是那块整洁的底座。
紫色的 ESP32-C2 开发板是这块 DevKit 的紧凑型单核 RISC-V 兄弟款,面向 ESP-IDF 开发 —— Arduino 标准的板卡管理器并不支持 C2,所以它跟不了这篇 Arduino IDE 教程;所有 Blynk 例程写的都是经典 30 针 CH340 DevKit。同一系列继电器还有 12 V 线圈版 —— 按你手头已有的电源来选线圈电压;5 V 版直接吃 USB 供电就够。
Blynk 的 Template、Datastream 和 Auth Token 是什么?
Blynk IoT 的一切都围绕三个概念。Template(模板)是一件产品的蓝图:有哪些数据通道、仪表盘长什么样。Device(设备)是照着蓝图生出来的一块真实的板子,而 Auth Token 就是这台设备的登录钥匙 —— 一串很长的随机字符,告诉云端是谁在连接、它能控制什么。Datastream(数据流)是 App 和板子之间的一条命名通道;我们用的是虚拟引脚 V0,传 0 或 1。
整套设置在 console.blynk.cloud 上五分钟搞定 —— Blynk 官方的快速设置指南和这里的步骤一一对应:Developer Zone → My Templates → New Template(硬件选 ESP32,连接方式 WiFi)。在模板里添加一条 Datastream,绑定虚拟引脚 V0,类型 Integer,范围 0–1;再在网页仪表盘上加一个绑定 V0 的 Switch 挂件。然后从模板 New Device 创建设备 —— 它的 Device Info 页会把那三行 #define 摆好等你复制。手机仪表盘是另外一套:在 Blynk IoT App 里打开这台设备,点扳手图标,加一个绑定 V0 的 Button 挂件,模式选 Switch —— 在那之前 App 里只会是一片空白。
那三行必须放在所有 #include 的上面:#include 本质是文本粘贴,Blynk 库在被粘贴进来的那一刻就要读这些 define。放低了库就什么都看不见 —— 编译会停在库自己的报错上:“Please specify your BLYNK_TEMPLATE_ID and BLYNK_TEMPLATE_NAME”。
把 Token 当密码看待 —— 拿到它的人可以在世界任何角落操作你的继电器,所以别让它出现在聊天记录、截图和公开代码仓库里。已经泄露的话,在控制台删掉这台设备、用同一个模板重建一台 —— 新设备带全新的 Token,泄露的那串就此作废。
想先看别人把控制台设置在屏幕上完整点一遍?
继电器模块怎么接到 ESP32?
1 路继电器模块的控制侧是一个标着 IN、DC−、DC+ 的三位螺丝端子,不是排针 —— 所以材料清单配的是公对母杜邦线:母头套上 DevKit 出厂焊好的排针,裸露的公头压进螺丝端子拧紧。
| 继电器端子 | DevKit 引脚 | 原因 |
|---|---|---|
| DC+ | VIN | 线圈是一颗 5 V 电磁铁 —— VIN 把 USB 口的 5 V 直通出来 |
| DC− | GND | 线圈电流和控制信号的公共回路 |
| IN | D26 | GPIO26 —— 一个普通的全功能输出脚,上电起就安安静静 |
负载接在另一侧边缘的输出端子上:COM 在中间,旁边是 NO(常开),所以继电器不吸合电路就是断开的。继电器说到底只是接进负载自家供电线路里的一个开关:负载电源的正极进 COM,从 NO 出来接负载,负极直通。线圈电源接 VIN,别接 3V3 脚:SRD-05VDC 线圈阻值约 70 Ω,5 V 下电流约 70 mA —— 对 USB 供电不值一提(更多见我们的 ESP32 供电指南)。3V3 脚也拉不动它:Songle 标称吸合电压是额定线圈电压的 75% —— 约 3.75 V —— 3.3 V 可能永远吸不上衔铁。
复位时 ESP32 会采样它的 strapping 引脚 —— GPIO0、2、5、12 和 15 —— 来决定怎么启动,采样过程中还会拨动它们,于是每次重启继电器都要咔哒一下。GPIO34、35、VP 和 VN 则是另一种不合适:只进不出,根本没有输出驱动。D26 两个毛病都没有。
黑色的触发选择跳线出厂就插在 L 挡(低电平触发)—— 保持原样别动。低触发正是 5 V 模块听得懂 3.3 V 主板的关键:ESP32 的引脚从来不需要输出 5 V,只需要从光耦输入 LED 灌入几毫安电流,而这股电流来自模块自己的 DC+ 电源。把 IN 拉低,电流流通 —— 继电器吸合。用 3.3 V 把 IN 驱到高电平时,整条输入链路上只剩 5 − 3.3 = 1.7 V,远低于指示 LED 和光耦 LED 串联导通所需的约 3 V —— 所以开和关两种状态都干净利落。
安全先讲清楚:蓝色继电器方块上印着市电级的触点参数,但这个项目严格只开关低压直流负载。开关市电需要外壳、爬电距离和线缆应力消除 —— 裸露在桌面上的模块一样都没有;触点侧的正确做法见我们的继电器安全指南。

Blynk ESP32 代码长什么样?
这份 sketch 围绕 Blynk.config() 搭建,而不是所有复制粘贴例程都在用的 Blynk.begin() —— 这个选择就是整个离线功能的核心,下一节细讲。从 Library Manager 安装 Volodymyr Shymanskyy 写的 Blynk 库,板卡选 ESP32 Dev Module,换上你自己的三行 #define 和 Wi-Fi 信息 —— 网络名必须是 2.4 GHz 频段,ESP32 的射频根本看不见 5 GHz 专属的 SSID —— 然后上传。
// Blynk + ESP32 手机控制继电器,带离线手动备援。
// 这三行 define 必须一直放在所有 #include 之前 - Blynk 库
// 在被 include 的那一刻就要读它们。真实的值请从你自己
// console.blynk.cloud 的设备页复制;这里只是占位符。
#define BLYNK_TEMPLATE_ID "TMPL_PASTE_YOURS"
#define BLYNK_TEMPLATE_NAME "Phone Relay"
#define BLYNK_AUTH_TOKEN "PASTE-YOUR-OWN-TOKEN-HERE" // 机密 - 绝不外传
#define BLYNK_PRINT Serial // 连接日志显示在串口监视器
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
const char WIFI_SSID[] = "YourWiFiName";
const char WIFI_PASS[] = "YourWiFiPassword";
const int RELAY_PIN = 26; // 丝印 D26 - 开机不乱动
const int BOOT_BTN = 0; // DevKit 自带的 BOOT 键
const int RELAY_ON = LOW; // 触发跳线出厂在 L 挡(低电平 = 开)
const int RELAY_OFF = HIGH;
bool relayState = false; // 继电器当前应有的状态
unsigned long lastRetry = 0;
const unsigned long RETRY_EVERY = 30000UL; // 两次云端重连的间隔毫秒数
void applyRelay() {
digitalWrite(RELAY_PIN, relayState ? RELAY_ON : RELAY_OFF);
}
// App 上的 V0 开关每次变化都会执行
BLYNK_WRITE(V0) {
relayState = param.asInt(); // 1 = 开,0 = 关
applyRelay();
}
// 云端连接每次(重新)建立时执行
BLYNK_CONNECTED() {
Blynk.syncVirtual(V0); // 向服务器要回 V0 最后的值
}
void setup() {
pinMode(RELAY_PIN, OUTPUT);
applyRelay(); // 先确保继电器处于关闭
pinMode(BOOT_BTN, INPUT_PULLUP); // 按下 = LOW
Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PASS); // 在后台开始连 Wi-Fi
Blynk.config(BLYNK_AUTH_TOKEN); // 只做配置 - 绝不阻塞
Blynk.connect(5000); // 尝试 5 秒,连不上也继续往下走
}
void loop() {
if (Blynk.connected()) {
Blynk.run(); // 维持云端连接
} else if (millis() - lastRetry > RETRY_EVERY) {
lastRetry = millis(); // 每 30 秒一次限时重试
if (WiFi.status() == WL_CONNECTED) Blynk.connect(5000);
}
// 手动备援:不管有没有网,BOOT 键都能切换继电器
static bool lastBtn = HIGH;
bool btn = digitalRead(BOOT_BTN);
if (lastBtn == HIGH && btn == LOW) { // 检测到新一次按下
delay(30); // 消抖
if (digitalRead(BOOT_BTN) == LOW) {
relayState = !relayState;
applyRelay();
if (Blynk.connected()) Blynk.virtualWrite(V0, relayState);
}
}
lastBtn = btn;
}
编译出来 913,759 字节 —— 约占 DevKit 应用空间的 69%。拨一下 App 里的开关,继电器不到一秒就应声动作。桌上还没有继电器?把 RELAY_PIN 改成 2,再把 RELAY_ON 和 RELAY_OFF 的值对调,同一个模板就能在 DevKit 板载的蓝色 LED 上跑经典的 Blynk LED 点亮熄灭演示 —— 那是一个 strapping 引脚,闪灯没问题,接继电器万万不可。
断网了,开关怎么还能用?
Blynk.begin() 就是多数 Blynk 开关连墙上开关都不如的原因。它在库内部是两个不设时限的等待:先是一个循环转到 Wi-Fi 连上为止,然后 while(connect() != true) {} 一直等云端应答。路由器关着,sketch 就永远出不了 setup():没有 loop、没有按键,继电器冻结在最后的状态。
替代写法把工作拆开:Blynk.config() 只保存 Token 和服务器名,所以它不可能阻塞;Blynk.connect(5000) 尝试五秒后无论成败都返回,让 sketch 继续跑;loop 里则在 Wi-Fi 正常时每 30 秒重试一次。代价是:重试进行中按键最多等五秒,每半分钟一次 —— 两个数字都可以自己调。
手动备援用的是 DevKit 自带的 BOOT 键(GPIO0)—— 它只在复位那一刻特殊,芯片靠采样它决定要不要进入烧录模式;之后它就是一个带上拉的普通输入脚,按下读到 LOW。sketch 盯住这个跳变沿,按一下就切换继电器。
断网后连接恢复时,BLYNK_CONNECTED() 触发,syncVirtual(V0) 把服务器上开关的最后状态重放下来 —— 以 App 的设定为准,手机上显示的永远是真相。想让墙边按键的状态说了算?把那一行换成 Blynk.virtualWrite(V0, relayState),改成把板子的状态推上去。

真实客户身上常见的错误
“so can include with the blynk?” —— 从医疗机器人 FYP 到 ESP32-CAM 视频流,什么项目都有人这么问 —— 答案几乎都是可以:Blynk 可以挂到 sketch 已经在做的任何事情上,条件只有两个。三行 define 放到最顶端,以及 loop() 里不许有任何阻塞 —— 一个长 delay() 会饿死 Blynk.run(),云端等不到心跳,App 就显示设备离线。慢工作请用 millis() 计时,就像上面的重试计时器那样。
“what you gonna monitor in the blynk?” —— 答案是:你给了 Datastream 什么,它就监测什么。这里的 V0 是把命令往下送到继电器;监测只是同一套机制往上用 —— 每个读数一条 Datastream,在传感器代码里用 Blynk.virtualWrite() 写上去,同一个模板就装得下。
把带着有效 Auth Token 的代码贴进群聊。为了求助,整份 sketch 连 Token 一起被转发出去 —— 刷到的每个人从此都能拨动你的继电器。分享代码前先把它抹掉;已经泄露的按上文换一台设备。
用只能充电的 USB 线上传。板子通电、灯也亮,看着一切正常,但串口就是不出现 —— 线里四根芯少了两根数据线。材料清单里的 USB-C 数据线就是为这个配的;端口还是不出现的话,我们的 ESP32 上传失败排查指南把整条链路走一遍。
常见问题
为什么 Blynk 报 “Invalid auth token”?
sketch 里的 Token 已经对不上任何设备 —— 复制时丢了一个字符、设备泄露后被删除重建、或者模板来自另一个账号。到 Device Info 页把三行重新复制一遍,再上传。
免费版 Blynk 够用吗?
够 —— 一个模板、一台设备加一个开关挂件,稳稳落在免费档以内。Blynk 会不时调整限额,所以以控制台里的套餐页为准,别信教程里印着的数字。
能改用 12 V 继电器模块吗?
可以,前提是你的系统本来就有 12 V 电源:DC+ 接那个电源,DC− 接和 ESP32 共通的地,IN 照旧接 D26 —— 光耦的工作方式完全一样。把 12 V 线圈接在 DevKit 的 5 V VIN 上,是绝对吸合不了的。
为什么 ESP32 一重启继电器就自己咔哒响?
IN 线接在了 strapping 引脚上 —— GPIO0、2、5、12 或 15 —— 芯片每次复位都会拨动它们来决定怎么启动。挪到安静的全功能输出脚上,比如 D26、D27、D25 或 D33。

手机能控制继电器之后,同一套接线可以直接带进我们的其他项目:离线语音控制继电器用语音指令驱动的正是这块模块,而 ESP32-CAM 视频流指南补上许多 FYP 题目里的摄像头那一半。模板、Token、三根线 —— 继电器从此听你口袋的话。
最后更新:2026年8月。有问题?WhatsApp 联系我们。



NodeMCU ESP32 Wi-Fi + Bluetooth Development Board CH340/CP2012 - For IOT Project - ESP-32 (CH340)
Relay Module 3.3V 5V 12V 1/2/4/8 Ways Optocoupler Trigger Relay Module 1 2 4 8 Channel Relay Module - 5V RELAY MODULE(1WAY)
40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-F 20CM
Data Cable Type-A Type-C MicroUSB Type-B 0.5m 1m 30cm 0.3m 100cm Data Transfer Upload Code - TYPE-A TO TYPE-C CABLE (1.0M)
NodeMCU ESP32 Wi-Fi + Bluetooth Development Board CH340/CP2012 - For IOT Project - ESP32 30PIN EXPANSION BOARD