通过点灯科技云平台实现LED控制
292.10.通过点灯科技云平台实现LED控制
#define BLINKER_WIFI // 选择 Blinker 的 Wi-Fi 接入方式。
#define led 4 // 把本课使用的 ESP32-CAM 闪光灯 GPIO4 命名为 led。
#include <Blinker.h> // 引入 Blinker 库的声明。
#include "ESP32_CAM_SERVER.h" // 引入配套摄像头服务文件;这里不展开其内部实现。
BlinkerButton Button1("led"); // 建立按键组件对象;"led" 是与 App 组件键名对应的字符串。
void button1_callback(const String & state) // 定义收到该按键指令时执行的回调;state 保存传来的状态。
{ // 开始按键回调。
BLINKER_LOG("get button state: ", state); // 把收到的按键状态写到 Blinker 串口调试日志。
digitalWrite(led, !digitalRead(led)); // 读出 GPIO4 当前电平、取反,再写回 GPIO4。
} // 结束按键回调。
char auth[] = "c56be051d11f"; // 视频中的设备 Secret Key;复现时换成自己的密钥。
char ssid[] = "302"; // 视频中的 Wi-Fi 热点名称;复现时换成自己的热点名。
char pswd[] = "12345678"; // 视频中的 Wi-Fi 热点密码;不是 Blinker 账号密码。
bool setup_camera = false; // 标记摄像头服务尚未由下方代码启动。
void dataRead(const String & data) // 定义收到未由已绑定组件处理的数据时调用的回调。
{ // 开始处理收到的数据。
BLINKER_LOG("Blinker readString: ", data); // 将收到的内容写到串口调试日志。
Blinker.vibrate(); // 向 App 发送手机振动请求。
uint32_t BlinkerTime = millis(); // 读取本次开机以来经过的毫秒数。
Blinker.print("millis", BlinkerTime); // 以 millis 为键把该数值发送给 App。
} // 结束 dataRead 回调。
void setup() // 定义上电或复位后执行一次的初始化函数。
{ // 开始初始化。
Serial.begin(115200); // 以 115200 波特率启动串口。
BLINKER_DEBUG.stream(Serial); // 把 Blinker 的调试输出指向串口。
pinMode(led,OUTPUT); // 将 GPIO4 设置成数字输出。
digitalWrite(led, LOW); // 启动时输出低电平,让闪光灯初始熄灭。
Blinker.begin(auth,ssid,pswd); // 用设备密钥、热点名和密码接入 Blinker。
Blinker.attachData(dataRead); // 注册通用数据回调。
Button1.attach(button1_callback); // 把 Button1 的指令与按键回调关联。
} // 结束初始化。
void loop() // 定义 Arduino 反复执行的主循环。
{ // 开始本轮循环。
Blinker.run(); // 维持 Blinker 通信并处理收到的指令。
if (Blinker.connected() && !setup_camera) // 连接建立且尚未启动摄像头服务时进入。
{ // 开始首次启动摄像头的分支。
setupCamera(); // 调用配套文件中的摄像头与本地视频流服务初始化。
setup_camera = true; // 记录已执行过初始化,避免每轮重复调用。
Blinker.printObject("video", "{\"str\":\"mjpg\",\"url\":\"http://"+ WiFi.localIP().toString() + "\"}"); // 向 App 的 video 组件发送视频格式和本机局域网 URL。
} // 结束首次启动摄像头的分支。
} // 结束本轮循环,随后再次进入 loop。
一、通过点灯科技云平台实现LED控制
本节承接第 291 节的 ESP32-CAM 视频组件实验:保留原有联网、摄像头服务和视频 URL 逻辑,增加 App 按键组件与板载白色闪光灯的控制。上方抄录的是视频烧录时的 Blinker_ESP32_CAM.ino 主草图业务代码(去掉原注释并逐行加教学注释),没有把 ESP32_CAM_SERVER.h 中的库实现抄进来。视频公开展示的 Secret Key 与热点凭据只作课堂记录;自己复现时必须替换,勿公开真实密钥和密码。Blinker 官方 ESP32-CAM 示例
1.1 点灯科技云平台官网
- 视频打开
diandeng.tech,进入“开发文档 → 快速开始 → ESP32 WiFi 接入”,参考完整示例中的BlinkerButton对象、按键回调和attach()注册写法。页面上方还有 Arduino 开发环境与库的安装说明;本节沿用上一节已经装好的环境,并非重新安装。Blinker 官方 ESP32/Wi-Fi 入门 - 本节的控制路径可以分成:App 按键发出带键名的指令 → Blinker 设备收到 →
Button1匹配led→ 回调切换 GPIO4 电平 → 白色闪光灯亮或灭。视频画面仍由板子提供的局域网 HTTP/MJPG 服务读取,和按键指令不是同一份数据;“云平台控制 LED”不等于视频帧也上传到云端。Blinker 按键组件接口、摄像头示例服务
1.2 完整示例程序
- 官方文档的完整示例采用
BlinkerButton Button1("btn-abc")、button1_callback、Button1.attach(button1_callback),并以digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN))演示翻转 LED。本节只把这些与按键有关的示例语句移入上一节的摄像头草图,再按实际板子把示例的LED_BUILTIN改为自定义的led(GPIO4),没有把示例里的计数器、数字组件等无关代码一起复制。官方完整示例及按键说明 - 代码块保留视频中的变量名、键名和调用形式。
BlinkerButton Button1("led")中Button1是程序里的 C++ 对象名,"led"是 App 组件通信使用的键名;App 上显示的文字可以另设为“灯”。原笔记称“都叫 LED”会误导:视频最终代码和 App 标签均为小写led,应按字面一致填写,而不是只看显示文字。
1.3 代码分析
1.3.1 组件对象新建
#define BLINKER_WIFI沿用上节的 Wi-Fi 接入配置;#define led 4是预处理替换,编译时把后文的led换成数字4。它不是 Blinker 组件键名的定义:BlinkerButton Button1("led")中的字符串是另一件事,恰好也写作小写led。- 在 App 编辑界面给按键组件填键名
led,才能与Button1("led")匹配;Button1、led宏、"led"字符串分别是对象名、引脚代号、组件键名,不要混为一谈。大小写不一致或多了空格都可能匹配失败。BlinkerButton 官方接口
1.3.2 按键处理函数编写
void button1_callback(const String & state)是收到该组件指令后调用的函数,不是 ESP32-CAM 上新增了一个实体按键,也不是 App 每次屏幕触摸都会无条件调用。视频最终将 App 组件设置为“开关按键”,官方说明这种模式发送"on"/"off";普通按键模式则可能发送"tap"、"press"、"pressup"。BlinkerButton 模式与状态值BLINKER_LOG("get button state: ", state)是设备侧串口调试输出,需串口保持连接且配置好BLINKER_DEBUG.stream(Serial)才便于查看;它不是把这段英文文本主动写入 App 的 Monitor。若要向 App 发送组件状态,官方提供Button1.print(...),但视频最终代码没有这句,精校源码不擅自补入。Blinker 调试配置、按键print()digitalRead(led)读 GPIO4 当前数字电平;前面的!把LOW/0变成HIGH/1,或把HIGH/1变成LOW/0;digitalWrite(led, ...)再写回,因此本例是每收到一次回调就翻转一次。它没有依据传入的state决定输出电平,所以不能理解成“收到on必定写 HIGH、收到off必定写 LOW”。设备重启、App 状态不同步或重复指令时,界面开关与实物灯可能不一致;这属于视频示例的局限,不能未经授权修改上方原代码。官方按钮状态定义
1.3.3 处理函数代码拷贝
- 视频查引脚图后确认选的是 ESP32-CAM 白色闪光灯所接的 GPIO4,不是把“GPL 4”当成另一种接口。其
#define led 4、pinMode(led,OUTPUT)、回调里的digitalWrite(led, !digitalRead(led))指向同一编号;若把示例中的LED_BUILTIN留在一处,则可能不是本板这盏灯。Zephyr ESP32-CAM 板级定义:GPIO4 为高电平有效的 Flash LED - 板上还可能见到红色状态灯,本课控制的是白色补光/闪光灯,不要把二者或板子的复位键混淆。读板级资料时先找板型
AI Thinker ESP32-CAM,再找Flash LED → GPIO4,最后看有效电平:资料标为GPIO_ACTIVE_HIGH,即 GPIO4 高电平对应闪光灯点亮、低电平对应熄灭;其他开发板不可照搬此引脚与极性。Zephyr 板级定义 - 从硬件角度理解:GPIO 是 ESP32 的控制信号端,软件写
HIGH/LOW改变管脚输出;板上的供电、白色闪光灯和驱动器构成电流回路,LED 有电流才会发光。ESP32-CAM V1.6 参考原理图中,GPIO4 对应HS2_DATA1信号,连接到LED_FLASH驱动支路,支路中有Q1 S8050三极管;高电平让驱动支路导通,低电平使其截止。因此不能把digitalWrite理解为向灯“发送网络消息”,也不要把一颗大功率闪光 LED 不经合适的驱动与限流设计直接接到芯片 GPIO 上。GPIO4 同时连向 microSD 的数据线,用 SD 卡相应模式时可能冲突,本视频并未启用 SD 卡。ESP32-CAM V1.6 原理图、Zephyr 板卡硬件说明 - 视频中的所谓“86 行”是当时 IDE 的行号,受文件头注释和编辑影响会变化。真正关键的是把
Button1.attach(button1_callback)放进setup(),由库在识别到led指令时调用对应函数;只定义对象和函数而不注册,按键不会进入该回调。Blinkerattach()说明
1.3.4 LED口初始化
pinMode(led,OUTPUT)将 GPIO4 设为输出;接着digitalWrite(led, LOW)指定本次启动后的初始低电平,于是白色闪光灯初始熄灭。初始LOW →第一次回调取反为HIGH、灯亮;第二次回调HIGH → LOW、灯灭。原笔记“初始低电平状态下第一次按下”只有完成这两句初始化之后才成立,未初始化时不能凭空假设引脚电平。- 对新手而言,
HIGH/LOW是管脚相对 GND 的数字高/低电平,不是“云平台上的高/低权限”,也不是给灯直接设置亮度;这段代码只有开/关,没有 PWM 调光。板载闪光灯工作时需有稳定供电,若灯亮时板子重启或 Wi-Fi 掉线,应先检查供电与接线,而不能单凭 App 离线判定程序逻辑错误。ESP32-CAM V1.6 原理图
1.3.5 代码上传
- 视频连接下载线,在 Arduino IDE 选
AI Thinker ESP32-CAM和对应串口后点击上传(原笔记“点击上的”是 OCR 错字)。上传时视频先显示旧的pinMode(led,OUPUT)编译报错;随后代码画面已经改成OUTPUT并继续编译、烧录,不能把旧错误当成最终程序仍然失败。视频末尾控制灯成功。Espressif ESP32 下载模式说明 - ESP32-CAM 若用外置 USB 转串口器并需手动进入下载模式,通常让 GPIO0 在复位时接 GND;烧录完成后移开 GPIO0—GND 下载连接,再复位以运行程序。视频说“拔掉下载线”是其实际操作画面,复现时还必须保留或重新提供可靠的供电与共地;不要在断电且无供电情况下期待设备上线。Espressif 启动模式说明
1.3.6 组件编辑
- 视频在 Blinker App 中打开已有设备,进入组件编辑,拖入一个按键组件,在参数里把“组件键名”改为小写
led。这一步才使 App 的组件发来的指令对应Button1("led");原笔记只说“名字一样”却未分清键名与显示文本。 - 视频左侧还保留上一节的
video视频组件,板子的loop()也继续发送视频组件的 MJPG URL。两种组件可在同一设备页面并存:视频组件负责看画面,按键组件负责发控制指令,不需要重新改摄像头服务源码。
1.3.7 样式设置
- “显示文本”可填“灯”,按钮大小、图标、颜色、背景透明度按喜好设置;这些只是 App 界面外观,不能替代通信键名
led。编辑完按界面确认并保存。视频中的操作发生于当时的 App 版本,新版本位置或名称可能不同。 - 视频中对开发板按复位键,是为了进入后续烧录/启动流程;复位键不负责保存 App 组件配置。按复位会让
setup()重新运行,GPIO4 再次被设为LOW,所以灯会回到初始关闭状态。
1.3.8 程序烧录
- 视频一边等待编译和上传,一边调 App 布局,最后将按钮类型切到开关按键,并在页面底部加入 Monitor 调试窗口。按钮类型要和课堂展示一致;但由于程序不读取
state决定输出,仅通过取反切换,开关的画面状态不具备设备真实状态的强一致保证。Blinker 按键模式与状态反馈 - 原笔记说“调试窗口关联 67—77 行代码”不准确:视频草图的那段是
dataRead()通用数据回调,里面会请求振动、回传millis;绑定到Button1的按键指令走button1_callback()。视频 Monitor 画面可见类似{"led":"on"}的通信记录;它不是BLINKER_LOG("get button state: ", state)自动在手机上打印的文本。要看后者应检查设备串口日志。Blinker 通用数据与按键回调、调试说明 - IDE 显示写入完成、校验通过后,让板子退出下载模式,复位启动,再开启视频所用手机热点;等待板子连接热点和 Blinker 平台。热点名称、密码必须对应草图里的
ssid、pswd,而实际复现应换成自己的值。
1.3.9 设备查看状态
- 视频先确认手机热点显示有设备连接,再在 Blinker App 的设备列表下拉刷新,等设备从离线变为在线。热点“有设备连接”只证明 Wi-Fi 关联,App 显示在线还要看 Blinker 通信是否成功;下拉两次仍离线不是硬件故障的严格判定,应检查供电、热点名称/密码、设备密钥、网络连通性和串口日志。
- 进入设备页后,上方视频组件恢复画面,点击“灯”开关时白色闪光灯亮,再点一次熄灭;Monitor 记录里可看到
led的on/off指令。原笔记中的“ESB 32K”“GPL口”“高电瓶”分别应为 ESP32-CAM、GPIO 引脚、高电平。 - 验证时区分四层:App 组件键名正确 → 指令到达设备 → 回调执行并写 GPIO4 → 白灯实际亮灭。如果设备在线但灯不响应,先查
led键名与按键模式,再看串口是否打印get button state:,最后查 GPIO4、LED 和供电;不要只看界面开关的图标就认定硬件真的改变了状态。视频示例每次回调取反,也没有从设备主动用Button1.print()回报真实灯态。Blinker 按键组件接口
核对依据
- 本地
videos/292.10.通过点灯科技云平台实现LED控制.mp4的最终 Arduino 草图、App 组件编辑、烧录结果和 LED 控制演示;对照transcripts/292.10.通过点灯科技云平台实现LED控制.txt与原始notes/md/292.10.通过点灯科技云平台实现LED控制.md。 - 上节精校稿
notes/md_proofread_version/291.9.连接点灯科技云平台.md与课程配套 Blinker 摄像头示例,用于核对本节未改动的联网、摄像头及视频 URL 部分;官方 Blinker ESP32 Wi-Fi 教程、Arduino 组件接口。 - ESP32-CAM V1.6 原理图及 Zephyr AI-Thinker ESP32-CAM 板级资料,用于核对 GPIO4、闪光灯有效电平与 microSD 复用关系。