跳转到内容

为ESP32构建Scratch固件与引脚配置

为ESP32构建Scratch固件与引脚配置

Section titled “为ESP32构建Scratch固件与引脚配置”

什么是Firmata协议?它和mBlock直接编译上传有什么区别?

mBlock的工作方式是:把积木块编译成Arduino C++代码 → 上传到ESP32 → 每次修改都要重新编译。

Firmata是另一种方式:在ESP32上烧录一个特殊的”Firmata固件”,它通过USB串口与PC实时通信。PC上的Scratch程序发送Firmata指令,ESP32执行后返回结果——从而实现实时控制引脚,无需反复烧录

对比维度mBlock直接编译Firmata固件
修改后是否需要编译是,每次都要否,实时生效
适用场景固定逻辑教学反复调试IO状态
脱机运行可以需要持续USB连接
学习曲线中等

哪些场景应该选择Firmata方式?

  • 需要反复调试传感器数值、电机位置
  • 需要实时观察引脚状态变化
  • 工作坊中需要快速切换不同硬件配置
  • 原型验证阶段快速迭代IO方案

如何在ESP32上安装ConfigurableFirmata固件?

  1. 打开Arduino IDE
  2. 进入 项目 > 加载库 > 管理库
  3. 搜索 ConfigurableFirmata 并安装(作者:firmata)——依赖的DHT传感器库会自动安装
  4. 进入 文件 > 示例 > 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_INPUTDIGITAL_OUTPUTANALOG_INPUT 即可。涉及电机或I2C外设时再取消注释对应模块。

如何烧录固件并验证Scratch可以实时控制引脚?

  1. Arduino IDE中选择 工具 > 开发板 > ESP32 Dev Module
  2. 选择正确的串口端口,点击 上传
  3. 打开串口监视器(波特率57600),看到Firmata启动信息即表示烧录成功
  4. 在mBlock中选择 Devices > Arduino Uno,在 Connect 中选择对应串口
  5. 拖入”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引脚有哪些限制需要注意?

  1. GPIO 34-39是纯输入引脚:只能用于模拟输入(PIN_MODE_ANALOG),不能设置为数字输出
  2. ADC2与Wi-Fi冲突:GPIO 25-27、32-33属于ADC2,Wi-Fi开启时不可用——优先使用ADC1(GPIO 32-36)
  3. 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) # LED
board.set_pin_mode(0, board.INPUT) # 按钮
board.set_pin_mode(34, board.ANALOG) # 电位器
# 使用
board.digital_write(2, 1) # 点亮LED
value = board.analog_read(34) # 读取电位器

这种方式适合高级用户,将引脚配置放在主机侧管理。

完整示例:工厂显示屏项目的引脚配置是怎样的?

假设一个工厂显示屏ESP32项目接线如下:

外设GPIO类型
状态LEDGPIO 2数字输出
显示屏背光GPIO 16PWM输出
按钮1GPIO 0数字输入(上拉)
按钮2GPIO 4数字输入
温度传感器(DS18B20)GPIO 5OneWire
电位器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后无响应?

按以下顺序排查:

  1. 固件是否烧录正确? 打开串口监视器(57600),应看到Firmata启动信息。若无输出,固件可能未正确烧录
  2. 串口是否被占用? 关闭所有占用串口的程序(Arduino IDE串口监视器、其他终端等)
  3. 波特率是否匹配? mBlock中波特率设置须与固件一致(默认57600)
  4. 引脚是否已配置? 检查 systemResetCallback() 中是否用 Firmata.setPinMode() 配置了使用的引脚
  5. 是否误用了受限引脚? 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编译固件交付
  1. Firmata固件让Scratch通过USB实时控制ESP32引脚,无需反复编译上传
  2. systemResetCallback() 中调用 Firmata.setPinMode() 预设每个引脚的IO模式
  3. ESP32的ADC引脚有限制:GPIO 34-39只能输入,ADC2在Wi-Fi下不可用
  4. Python/pymata4可在主机侧配置引脚,修改时不需重新烧录ESP32
  5. 建议维护引脚映射文档,并与固件配置保持同步

正在开发商业 IoT 产品?

我们提供 ESP32 ODM 定制设计与制造服务。从原型到量产——编写这套教程的团队,可以和你一起实现。

联系我们 →