为ESP32构建Scratch固件与引脚配置
为ESP32构建Scratch固件与引脚配置
Section titled “为ESP32构建Scratch固件与引脚配置”- 已完成 Scratch可视化编程入门 中的mBlock安装
- Arduino IDE已安装ESP32 Arduino Core
- ESP32开发板通过USB连接电脑
什么是Firmata协议?它和mBlock直接编译上传有什么区别?
mBlock的工作方式是:把积木块编译成Arduino C++代码 → 上传到ESP32 → 每次修改都要重新编译。
Firmata是另一种方式:在ESP32上烧录一个特殊的”Firmata固件”,它通过USB串口与PC实时通信。PC上的Scratch程序发送Firmata指令,ESP32执行后返回结果——从而实现实时控制引脚,无需反复烧录。
| 对比维度 | mBlock直接编译 | Firmata固件 |
|---|---|---|
| 修改后是否需要编译 | 是,每次都要 | 否,实时生效 |
| 适用场景 | 固定逻辑教学 | 反复调试IO状态 |
| 脱机运行 | 可以 | 需要持续USB连接 |
| 学习曲线 | 低 | 中等 |
哪些场景应该选择Firmata方式?
- 需要反复调试传感器数值、电机位置
- 需要实时观察引脚状态变化
- 工作坊中需要快速切换不同硬件配置
- 原型验证阶段快速迭代IO方案
如何在ESP32上安装ConfigurableFirmata固件?
- 打开Arduino IDE
- 进入 项目 > 加载库 > 管理库
- 搜索
ConfigurableFirmata并安装(作者:firmata)——依赖的DHT传感器库会自动安装 - 进入 文件 > 示例 > ConfigurableFirmata > ConfigurableFirmata,打开示例项目
固件中哪些功能模块可以启用或禁用?
打开 ConfigurableFirmata.ino,文件开头有一组 #define 宏控制功能模块:
/* 模块选择:根据项目需要取消注释 */#define FirmataSerial Serial // 使用USB串口(默认)// #define SERIAL_BAUD 115200 // 波特率,默认57600
#define DIGITAL_INPUT_PULLUP // 启用数字输入(带上拉)#define DIGITAL_INPUT // 启用数字输入#define DIGITAL_OUTPUT // 启用数字输出#define ANALOG_INPUT // 启用模拟输入#define ANALOG_OUTPUT // 启用PWM模拟输出// #define SERVO // 启用舵机控制// #define I2C // 启用I2C// #define STEPPER // 启用步进电机// #define ONEWIRE // 启用OneWire(如DS18B20)// #define DHT // 启用DHT温湿度传感器对于大多数IoT项目,保留 DIGITAL_INPUT、DIGITAL_OUTPUT、ANALOG_INPUT 即可。涉及电机或I2C外设时再取消注释对应模块。
如何烧录固件并验证Scratch可以实时控制引脚?
- Arduino IDE中选择 工具 > 开发板 > ESP32 Dev Module
- 选择正确的串口端口,点击 上传
- 打开串口监视器(波特率57600),看到Firmata启动信息即表示烧录成功
- 在mBlock中选择 Devices > Arduino Uno,在 Connect 中选择对应串口
- 拖入”set pin 2 to HIGH”积木块——ESP32内置LED应立即亮起,无需编译等待
如何将项目的IO引脚映射告诉Firmata固件?
Firmata固件不会预先知道你的项目中哪些引脚接了LED、哪些接了传感器。你需要在 systemResetCallback() 函数中,用 Firmata.setPinMode() 明确声明每个引脚的IO模式:
void systemResetCallback() { /* 请在下方按项目实际接线配置引脚模式 */
// ---- 数字输出 ---- Firmata.setPinMode(2, PIN_MODE_OUTPUT); // LED指示灯 (GPIO 2) Firmata.setPinMode(16, PIN_MODE_OUTPUT); // 继电器 (GPIO 16) Firmata.setPinMode(17, PIN_MODE_OUTPUT); // 蜂鸣器 (GPIO 17)
// ---- 数字输入 ---- Firmata.setPinMode(0, PIN_MODE_INPUT); // 按键 (GPIO 0, 板上按键) Firmata.setPinMode(5, PIN_MODE_INPUT); // 限位开关 (GPIO 5)
// ---- 模拟输入(ADC) ---- Firmata.setPinMode(34, PIN_MODE_ANALOG); // 电位器 (ADC1_CH6, GPIO 34) Firmata.setPinMode(35, PIN_MODE_ANALOG); // 光敏电阻 (ADC1_CH7, GPIO 35) Firmata.setPinMode(36, PIN_MODE_ANALOG); // 模拟传感器 (ADC1_CH0, GPIO 36 — SVP) Firmata.setPinMode(39, PIN_MODE_ANALOG); // 模拟传感器 (ADC1_CH3, GPIO 39 — SVN)
// ---- PWM输出(LED模拟调光) ---- Firmata.setPinMode(4, PIN_MODE_PWM); // LED调光 (GPIO 4) Firmata.setPinMode(18, PIN_MODE_PWM); // 电机调速 (GPIO 18) // ESP32 PWM注意事项:并非所有GPIO都支持PWM // 推荐使用 GPIO 2,4,5,12-19,21-23,25-27,32-33
// ---- 舵机(取消上方SERVO的注释后才生效) ---- // Firmata.setPinMode(13, PIN_MODE_SERVO); // 舵机信号线 (GPIO 13) // Firmata.setPinMode(14, PIN_MODE_SERVO); // 舵机信号线 (GPIO 14)
// ---- I2C(取消上方I2C的注释后才生效) ---- // Wire.begin(); // 默认 SDA=GPIO21, SCL=GPIO22}配置完成后重新编译上传,Scratch端只需使用对应引脚的积木块即可控制硬件。
ESP32的ADC引脚有哪些限制需要注意?
- GPIO 34-39是纯输入引脚:只能用于模拟输入(
PIN_MODE_ANALOG),不能设置为数字输出 - ADC2与Wi-Fi冲突:GPIO 25-27、32-33属于ADC2,Wi-Fi开启时不可用——优先使用ADC1(GPIO 32-36)
- GPIO 6-11被Flash占用:这些引脚连接了ESP32的外部Flash,不建议作为普通IO使用
能否不修改固件,从Scratch积木中直接设定引脚模式?
部分工具支持在积木中运行时设定:
when Arduino starts set pin 2 to OUTPUT ← 运行时自动设置(部分工具支持) set pin 2 to HIGH ← 点亮LED但这种方式有局限性——某些工具不支持动态设置引脚模式。推荐做法:在 systemResetCallback() 中一次性配好所有引脚,Scratch端只需读写。
能否用Python代替Scratch来配置引脚?
可以。使用Python + pymata4在主机侧配置,修改引脚映射时无需重新烧录ESP32:
from pymata4 import pymata4
board = pymata4.Pymata4(com_port="/dev/cu.usbserial-XXXX")
# 配置引脚board.set_pin_mode(2, board.OUTPUT) # LEDboard.set_pin_mode(0, board.INPUT) # 按钮board.set_pin_mode(34, board.ANALOG) # 电位器
# 使用board.digital_write(2, 1) # 点亮LEDvalue = board.analog_read(34) # 读取电位器这种方式适合高级用户,将引脚配置放在主机侧管理。
完整示例:工厂显示屏项目的引脚配置是怎样的?
假设一个工厂显示屏ESP32项目接线如下:
| 外设 | GPIO | 类型 |
|---|---|---|
| 状态LED | GPIO 2 | 数字输出 |
| 显示屏背光 | GPIO 16 | PWM输出 |
| 按钮1 | GPIO 0 | 数字输入(上拉) |
| 按钮2 | GPIO 4 | 数字输入 |
| 温度传感器(DS18B20) | GPIO 5 | OneWire |
| 电位器 | GPIO 34 | 模拟输入 |
对应的 systemResetCallback() 配置:
void systemResetCallback() { Firmata.setPinMode(2, PIN_MODE_OUTPUT); // 状态LED Firmata.setPinMode(16, PIN_MODE_PWM); // 显示屏背光调光 Firmata.setPinMode(0, PIN_MODE_INPUT); // 按钮1(板上自带上拉) Firmata.setPinMode(4, PIN_MODE_INPUT); // 按钮2 Firmata.setPinMode(5, PIN_MODE_INPUT); // 温度传感器(OneWire) Firmata.setPinMode(34, PIN_MODE_ANALOG); // 电位器}- ConfigurableFirmata示例在Arduino IDE中编译通过并上传到ESP32
- 串口监视器(57600波特率)显示Firmata启动信息
- 在
systemResetCallback()中正确配置了项目所用的IO引脚模式 - mBlock通过Firmata协议成功连接ESP32,引脚控制积木块实时生效
Scratch通过Firmata连接ESP32后无响应?
按以下顺序排查:
- 固件是否烧录正确? 打开串口监视器(57600),应看到Firmata启动信息。若无输出,固件可能未正确烧录
- 串口是否被占用? 关闭所有占用串口的程序(Arduino IDE串口监视器、其他终端等)
- 波特率是否匹配? mBlock中波特率设置须与固件一致(默认57600)
- 引脚是否已配置? 检查
systemResetCallback()中是否用Firmata.setPinMode()配置了使用的引脚 - 是否误用了受限引脚? GPIO 6-11连接Flash、GPIO 34-39只能输入——确认你使用的引脚支持对应功能
ESP32的ADC2引脚读取不到数值?
Wi-Fi开启时ADC2(GPIO 25-27、32-33)不可用。将模拟传感器改接到ADC1引脚(GPIO 32-36)即可解决。
- Firmata方式用于实时交互场景:反复调试IO状态时,比反复编译上传高效得多
- 引脚配置文档化:在项目中维护引脚映射表(Excel/Google Sheet或Markdown),与
systemResetCallback()中的配置保持同步 - 区分开发与交付阶段:原型调试用Firmata+Scratch快速迭代,最终产品用Arduino IDE或PlatformIO编译固件交付
- Firmata固件让Scratch通过USB实时控制ESP32引脚,无需反复编译上传
- 在
systemResetCallback()中调用Firmata.setPinMode()预设每个引脚的IO模式 - ESP32的ADC引脚有限制:GPIO 34-39只能输入,ADC2在Wi-Fi下不可用
- Python/pymata4可在主机侧配置引脚,修改时不需重新烧录ESP32
- 建议维护引脚映射文档,并与固件配置保持同步
我们提供 ESP32 ODM 定制设计与制造服务。从原型到量产——编写这套教程的团队,可以和你一起实现。
联系我们 →