外设管理页面是 FastBee 系统的硬件抽象层配置中心,通过 Web 界面将物理硬件(GPIO引脚、传感器、通信接口等)映射为系统可识别的虚拟外设对象。所有配置存储在 /config/peripherals.json 文件中。
出厂默认外设配置作为安全模板发布,硬件外设均为 enabled: false。首次添加或导入外设时,请先确认实际接线、引脚可用性和供电,再启用外设。
外设配置列表新增外设时,先选择类型,再填写名称、引脚和类型特定参数。未确认接线前保持“启用”关闭,保存后再逐个验证。
新增外设弹窗
外设接入与验证流程外设上线建议先保存为禁用状态,确认日志和单项动作正常后再启用;继电器、电机、Modbus 等会产生现场动作的对象尤其要先做单项验证。
外设类型选型地图新增外设前先按选型地图确认类型大类,再填写 ID、名称、引脚和类型参数;这样能减少把传感器、总线设备和虚拟 Modbus 子设备混在一起配置的概率。
外设配置数据模型排查配置问题时建议按数据模型顺序走一遍:先确认页面字段和 JSON 是否一致,再看保存校验是否通过,最后确认运行时驱动是否被初始化以及外设执行、MQTT、日志是否引用同一个外设 ID。
外设类型参数速查矩阵新增外设时可以先按参数矩阵核对必填字段和启用前检查项,再进入具体类型章节。特别是 ADC、I2C、UART/RS485、运动控制和虚拟外设,参数漏填或版本能力不匹配时很容易表现为“保存成功但运行失败”。
| 概念 | 说明 | 示例 |
|---|
| 外设ID | 唯一标识符,用于规则引用 | led1, dht_temp, relay_pump |
| 外设类型 | 硬件类型编码(type值) | 12=数字输出, 38=传感器 |
| 引脚配置 | 物理GPIO引脚编号数组 | [15], [4, 5](I2C的SDA,SCL) |
| 参数(params) | 类型特定的配置项 | {initialState: 1}, {baudrate: 115200} |
| 启用状态 | 控制外设是否初始化 | enabled: true 时占用硬件资源 |
进入外设管理页面
- 点击左侧菜单 外设配置
- 页面显示现有外设列表(表格形式)
点击新增按钮
填写基本信息(左列)
| 字段 | 必填 | 说明 | 示例 |
|---|
| 外设ID | 否 | 留空自动生成(格式:periph_<timestamp>) | led_room |
| 名称 | ✅ | 显示名称,建议有业务含义 | 客厅主灯 |
| 外设类型 | ✅ | 从下拉框选择硬件类型 | 数字输出 |
| 启用 | - | 开关控制,启用后占用引脚 | 首次建议关闭,确认后启用 |
配置引脚和参数(右列)
- 引脚配置:输入GPIO编号,多个引脚用逗号分隔
- 动态参数区:根据类型自动显示对应参数表单
保存配置
- 点击 保存 按钮
- 系统验证后写入
peripherals.json - 列表自动刷新显示新外设
┌─────────────────────────────────────────────┐
│ 新增外设 [×] │
├─────────────────────────────────────────────┤
│ 【左列:基本配置】 【右列:引脚和参数】 │
│ 外设ID: [led_1____] 引脚配置: [2,4,5___] │
│ 名称: [客厅灯____] ┌─────────────────┐ │
│ 类型: [数字输出▼] │ GPIO参数 │ │
│ 启用: [●══○____] │ 初始状态: [低▼] │ │
│ └─────────────────┘ │
├─────────────────────────────────────────────┤
│ [取消] [保存] │
└─────────────────────────────────────────────┘
- 在外设列表中找到目标外设
- 点击该行的 编辑 按钮(蓝色)
- 模态窗自动填充当前配置
- 修改需要调整的字段
- 点击 保存 确认更改
- ⚠️ 外设ID不可修改:编辑时ID字段为只读
- ⚠️ 引脚变更会重新初始化:修改引脚后外设会重新初始化
- ⚠️ 引用检查:如果有规则引用该外设,修改ID会导致规则失效
| 方式 | 操作 | 效果 |
|---|
| 列表快捷操作 | 点击 启用/禁用 按钮 | 立即切换状态 |
| 编辑模态窗 | 切换 启用 开关后保存 | 保存后生效 |
| 状态值 | 状态名称 | 含义 | 资源占用 |
|---|
| 0 | 禁用 | 外设未初始化 | ❌ 不占用GPIO |
| 1 | 启用 | 已初始化待运行 | ✅ 占用引脚 |
| 2 | 已初始化 | 驱动加载完成 | ✅ 占用引脚 |
| 3 | 运行中 | 正常工作 | ✅ 占用引脚 |
| 4 | 错误 | 初始化失败 | ⚠️ 可能占用 |
- 临时停用:禁用而不删除,保留配置
- 调试隔离:禁用冲突的外设排查问题
- 节省资源:禁用未使用的外设释放GPIO
- 点击该行的 删除 按钮(红色)
- 系统弹出确认对话框
- 确认后从
peripherals.json 移除
- ❌ 删除不可恢复:配置永久丢失(除非有备份)
- 🔗 检查引用:删除前确认没有规则引用该外设
- 💡 建议先禁用:不确定时先禁用观察几天
下拉框选项:
- 全部外设:显示所有类型
- 通信接口:UART, I2C, SPI, CAN, USB
- GPIO接口:数字输入/输出, PWM, 中断, 触摸
- 模拟信号:ADC, DAC
- 调试接口:JTAG, SWD
- 专用外设:LCD, 传感器, 舵机, 步进电机等
- 每页显示 10条 记录
- 底部显示分页导航(上一页/页码/下一页)
- 总数超过10条时自动分页
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|
| initialState | 整数 | 0 | 0 或 1 | 初始电平状态 |
0 = 低电平(LED灭/继电器断开)1 = 高电平(LED亮/继电器闭合)
{
"id": "led_main",
"name": "主LED",
"type": 12,
"enabled": true,
"pins": [15],
"params": {
"initialState": 0
}
}
- 低电平点亮:LED负极接GPIO,正极串联电阻接VCC
- 高电平点亮:LED正极接GPIO,负极串联电阻接GND
- 电阻计算:
R = (VCC - Vf) / If(红色LED约220Ω)
| type值 | 类型名称 | 内部电阻 | 空闲状态 | 适用场景 |
|---|
| 11 | 数字输入 | 无 | 浮空(不确定) | 有外部上拉/下拉的传感器 |
| 13 | 数字输入(上拉) | 内部上拉 | 高电平(1) | 按键(按下接地) |
| 14 | 数字输入(下拉) | 内部下拉 | 低电平(0) | 按键(按下接VCC) |
| 参数 | 类型 | 默认值 | 说明 |
|---|
| debounceMs | 整数 | 50 | 消抖时间(毫秒),防止按键抖动误触发 |
{
"id": "btn_power",
"name": "电源按键",
"type": 13,
"enabled": true,
"pins": [0],
"params": {
"debounceMs": 50
}
}
- ⚠️ GPIO0限制:启动时GPIO0为高电平,拉低会进入下载模式
- 按键接线:一端接GPIO,一端接GND(上拉模式)
- 消抖处理:机械按键必须设置debounceMs,建议30-100ms
- LED呼吸灯
- 电机调速
- 舵机控制(专用舵机类型更方便)
- 蜂鸣器音调
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|
| initialState | 整数 | 0 | 0 或 1 | 初始电平 |
| pwmFreq | 整数 | 1000 | 1~40000000 | PWM频率(Hz) |
| pwmResolution | 整数 | 8 | 1~16 | 分辨率(位) |
| defaultDuty | 整数 | 0 | 0~2^resolution-1 | 默认占空比 |
| 分辨率 | 最大值 | 50%占空比 | 适用场景 |
|---|
| 8位 | 255 | 127 | LED调光、简单电机 |
| 10位 | 1023 | 511 | 精确调光 |
| 12位 | 4095 | 2047 | 高精度控制 |
| 16位 | 65535 | 32767 | 音频PWM |
{
"id": "pwm_led",
"name": "呼吸灯",
"type": 17,
"enabled": true,
"pins": [4],
"params": {
"initialState": 0,
"pwmFreq": 1000,
"pwmResolution": 8,
"defaultDuty": 0
}
}
| 场景 | 推荐频率 | 原因 |
|---|
| LED调光 | 1000 Hz | 人眼不闪烁 |
| 电机调速 | 20000 Hz | 超出听觉范围,无噪音 |
| 舵机 | 50 Hz | 标准舵机协议 |
| 蜂鸣器 | 1000~4000 Hz | 可听音调 |
- Modbus RTU通信
- 串口调试
- 4G模块(EC801E)
- GPS模块
双引脚:39,40
顺序:引脚1=RX(接收), 引脚2=TX(发送)
ESP32引脚 39 → 外部设备的TX(接收外部数据)
ESP32引脚 40 → 外部设备的RX(发送数据到外部)
| 参数 | 类型 | 默认值 | 可选值 | 说明 |
|---|
| baudrate | 整数 | 115200 | 1200~921600 | 波特率 |
| dataBits | 整数 | 8 | 5,6,7,8 | 数据位 |
| stopBits | 整数 | 1 | 1,2 | 停止位 |
| parity | 整数 | 0 | 0=无,1=奇,2=偶 | 校验位 |
| 波特率 | 适用场景 |
|---|
| 9600 | GPS模块、老设备 |
| 19200 | 部分传感器 |
| 115200 | 最常用,4G模块、调试 |
| 921600 | 高速数据传输 |
{
"id": "uart_modbus",
"name": "Modbus串口",
"type": 1,
"enabled": true,
"pins": [39, 40],
"params": {
"baudrate": 9600,
"dataBits": 8,
"stopBits": 1,
"parity": 0
}
}
- 交叉连接:TX接RX,RX接TX
- 共地:必须连接GND
- 电平匹配:ESP32为3.3V,5V设备需电平转换
| 传感器 | dataField | 单位 | 接线 |
|---|
| DHT11/DHT22 | temperature, humidity | ℃, % | 单GPIO数据引脚 |
| DS18B20 | temperature | ℃ | 单GPIO(单总线) |
| HC-SR04 | distance | cm | 双GPIO(TRIG, ECHO) |
| SHT31/SHT30 | temperature, humidity | ℃, % | I2C(需启用I2C驱动) |
| AHT20/AHT21 | temperature, humidity | ℃, % | I2C |
| BH1750 | light | lux | I2C |
| BMP280 | temperature, pressure | ℃, hPa | I2C(S3-full) |
| MPU6050 | temperature, gyro_x/y/z, accel_x/y/z | ℃, °/s, m/s² | I2C(S3-full) |
DHT/DS18B20:单引脚 [21]
HC-SR04:双引脚 [5, 18](TRIG, ECHO)
| 参数 | 类型 | 默认值 | 说明 |
|---|
| sensorType | 字符串 | "dht" | 传感器类型标识 |
| dataField | 字符串 | "temperature" | 主要数据字段 |
{
"id": "dht_living",
"name": "客厅温湿度",
"type": 38,
"enabled": true,
"pins": [21],
"params": {
"sensorType": "dht",
"dataField": "temperature"
}
}
外设执行规则中使用传感器读取动作(actionType=19):
{
"type": 19,
"actionType": 19,
"targetPeriphId": "dht_living",
"actionValue": "{\"dataField\":\"temperature\"}"
}
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|
| minPulseUs | 整数 | 500 | 200~1000 | 0°脉宽(微秒) |
| maxPulseUs | 整数 | 2400 | 2000~3000 | 180°脉宽(微秒) |
| defaultAngle | 整数 | 90 | 0~180 | 默认角度 |
{
"id": "servo_camera",
"name": "摄像头舵机",
"type": 41,
"enabled": true,
"pins": [13],
"params": {
"minPulseUs": 500,
"maxPulseUs": 2400,
"defaultAngle": 90
}
}
- 颜色定义:红=VCC(5V),棕/黑=GND,橙/黄=信号
- 供电:多个舵机需外部5V电源
- 信号电平:ESP32输出3.3V,大部分舵机可识别
四引脚:11,10,9,13
顺序:IN1, IN2, IN3, IN4
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|
| stepsPerRev | 整数 | 2048 | 1~4096 | 每圈步数 |
| speed | 整数 | 8 | 1~30 | 默认转速(RPM) |
| 电机型号 | 每圈步数 | 减速比 | 推荐RPM |
|---|
| 28BYJ-48 | 2048(半步) | 1:64 | 5~15 |
| NEMA 17 | 200(整步) | 1:1 | 10~30 |
{
"id": "stepper_curtain",
"name": "窗帘步进电机",
"type": 42,
"enabled": true,
"pins": [11, 10, 9, 13],
"params": {
"stepsPerRev": 2048,
"speed": 10
}
}
- 驱动板:必须使用ULN2003等驱动板,不能直连
- 供电:5V外接电源,ESP32 GPIO仅提供控制信号
- 顺序:IN1→IN4对应驱动板IN1→IN4
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|
| ledCount | 整数 | 1 | 1~64 | 灯珠数量 |
| brightness | 整数 | 64 | 0~255 | 默认亮度 |
| ESP32型号 | 推荐最大数量 | 原因 |
|---|
| ESP32 slim | 16颗 | 内存限制 |
| ESP32-S3 full | 64颗 | PSRAM支持 |
{
"id": "neopixel_strip",
"name": "RGB灯带",
"type": 45,
"enabled": true,
"pins": [4],
"params": {
"ledCount": 8,
"brightness": 64
}
}
- 方向:DIN→DOUT串联,箭头方向为数据流向
- 供电:每颗灯珠60mA(全亮白色),需计算总电流
- 电容:电源端加1000μF电容稳压
- 电阻:DIN串联330Ω电阻减少信号反射
- OLED显示屏
- 传感器(SHT31、AHT20、BH1750、BMP280、MPU6050)
- RTC时钟模块(DS3231)
- EEPROM存储
双引脚:21,22
顺序:引脚1=SDA(数据), 引脚2=SCL(时钟)
| 参数 | 类型 | 默认值 | 可选值 | 说明 |
|---|
| frequency | 整数 | 100000 | 100000/400000 | I2C频率(Hz) |
| address | 整数 | 0 | 0~127 | 从机地址(0=主机模式) |
| 频率 | 模式 | 适用场景 | |------|------|---------|| | 100kHz | 标准模式 | 大部分I2C设备,稳定可靠 | | 400kHz | 快速模式 | 高速传感器,需设备支持 |
{
"id": "i2c_bus",
"name": "I2C总线",
"type": 2,
"enabled": true,
"pins": [21, 22],
"params": {
"frequency": 100000,
"address": 0
}
}
- 上拉电阻:I2C需要4.7kΩ上拉电阻(大部分模块已内置)
- 总线拓扑:所有设备并联在SDA和SCL上
- 地址冲突:每个设备必须有唯一地址
- 线长限制:建议<1米,长距离需降低频率
- SD卡模块
- TFT显示屏
- FLASH存储器
- 高速ADC/DAC
四引脚:18,23,19,5
顺序:SCK, MOSI, MISO, CS
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|
| frequency | 整数 | 1000000 | 1000~80000000 | SPI频率(Hz) |
| mode | 整数 | 0 | 0~3 | SPI模式(CPOL,CPHA) |
| 模式 | CPOL | CPHA | 说明 |
|---|
| 0 | 0 | 0 | 最常用,空闲低,上升沿采样 |
| 1 | 0 | 1 | 空闲低,下降沿采样 |
| 2 | 1 | 0 | 空闲高,下降沿采样 |
| 3 | 1 | 1 | 空闲高,上升沿采样 |
{
"id": "spi_sd",
"name": "SD卡SPI",
"type": 3,
"enabled": true,
"pins": [18, 23, 19, 5],
"params": {
"frequency": 4000000,
"mode": 0
}
}
| 设备 | 推荐频率 | 原因 |
|---|
| SD卡 | 4~25 MHz | 标准SD卡支持 |
| TFT屏 | 10~40 MHz | 刷新速度要求 |
| FLASH | 10~50 MHz | 高速读写 |
| ADC单元 | 可用引脚 | 注意 |
|---|
| ADC1 | 32,33,34,35,36,39 | 推荐使用 |
| ADC2 | 0,2,4,12,13,14,15,25,26,27 | WiFi启用时不可用 |
| 参数 | 类型 | 默认值 | 可选值 | 说明 |
|---|
| resolution | 整数 | 12 | 9/10/11/12 | 分辨率(位) |
| attenuation | 整数 | 3 | 0/1/2/3 | 衰减系数 |
| 分辨率 | 最大值 | 精度 | 适用场景 |
|---|
| 9位 | 511 | ±6.4mV | 快速采样 |
| 10位 | 1023 | ±3.2mV | 一般精度 |
| 11位 | 2047 | ±1.6mV | 较高精度 |
| 12位 | 4095 | ±0.8mV | 最常用 |
| 衰减 | 电压范围 | 适用场景 |
|---|
| 0dB | 0~1.1V | 高精度小信号 |
| 2.5dB | 0~1.5V | 传感器输出 |
| 6dB | 0~2.2V | 电池检测 |
| 11dB | 0~3.3V | 最常用,全量程 |
{
"id": "adc_pot",
"name": "电位器ADC",
"type": 26,
"enabled": true,
"pins": [34],
"params": {
"resolution": 12,
"attenuation": 3
}
}
实际电压 = (ADC值 / 4095.0) * 3.3V
- 分压电路:测量>3.3V电压必须使用电阻分压
- 滤波电容:并联100nF电容减少噪声
- 阻抗匹配:信号源阻抗<10kΩ
单引脚:25 或 26
ESP32仅GPIO25和GPIO26支持DAC
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|
| defaultValue | 整数 | 0 | 0~255 | 默认输出值(8位) |
输出电压 = (DAC值 / 255.0) * 3.3V
| DAC值 | 输出电压 | 百分比 |
|---|
| 0 | 0V | 0% |
| 128 | 1.65V | 50% |
| 255 | 3.3V | 100% |
{
"id": "dac_audio",
"name": "音频DAC",
"type": 27,
"enabled": true,
"pins": [25],
"params": {
"defaultValue": 128
}
}
- 负载阻抗:建议>10kΩ,低阻抗需加运放缓冲
- 滤波:输出端加低通滤波器平滑波形
- ESP32-S3:❌ 不支持DAC功能
双引脚:21,22
顺序:引脚1=CLK(时钟), 引脚2=DIO(数据)
| 参数 | 类型 | 默认值 | 取值范围 | 说明 |
|---|
| brightness | 整数 | 3 | 0~7 | 显示亮度 |
| 亮度值 | 相对亮度 | 适用场景 |
|---|
| 0 | 最暗(1/16) | 夜间低光环境 |
| 3 | 中等(4/16) | 默认,室内使用 |
| 7 | 最亮(16/16) | 强光环境 |
{
"id": "display_clock",
"name": "时钟数码管",
"type": 47,
"enabled": true,
"pins": [21, 22],
"params": {
"brightness": 3
}
}
- 5V供电:TM1637支持3.3V和5V,5V更亮
- 电平兼容:ESP32 3.3V信号可直接驱动
- 线长:建议<30cm,长距离需加电容
| 驱动芯片 | 分辨率 | 接口 | 说明 |
|---|
| SSD1306 | 128x64 | I2C | 最常用 |
| SH1106 | 128x64 | I2C | 兼容SSD1306 |
| SSD1306 | 128x32 | I2C | 小屏 |
双引脚:21, 22
顺序:SDA(数据), SCL(时钟)
| 参数 | 类型 | 默认值 | 说明 |
|---|
| i2cAddress | 整数 | 0x3C | I2C地址 |
| contrast | 整数 | 255 | 对比度(0~255) |
{
"id": "oled_display",
"name": "OLED屏",
"type": 36,
"enabled": true,
"pins": [21, 22],
"params": {
"i2cAddress": 60,
"contrast": 255
}
}
通过外设执行规则使用OLED显示动作(actionType=27):
{
"type": 27,
"actionType": 27,
"targetPeriphId": "oled_display",
"actionValue": "温度: ${temperature}℃\n湿度: ${humidity}%"
}
| 引脚 | 原因 |
|---|
| GPIO6~11 | 连接Flash芯片 |
| GPIO34~39 | 仅输入,无内部上拉 |
| 引脚 | 注意事项 |
|---|
| GPIO0 | 启动时为输入,拉低进入下载模式 |
| GPIO15 | 启动时日志输出,可能短暂高电平 |
| GPIO34~39 | 只能做输入,不能输出 |
| 用途 | 推荐引脚 |
|---|
| 数字输出 | 2, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33 |
| 数字输入 | 所有GPIO(除6~11) |
| PWM输出 | 与数字输出相同 |
| ADC输入 | 32, 33, 34, 35, 36, 39 |
| I2C | 21(SDA), 22(SCL) |
| SPI | 18(SCK), 19(MISO), 23(MOSI), 5(CS) |
| 触摸 | 0, 2, 4, 12, 13, 14, 15, 27, 32, 33 |
| 场景 | 问题 | 解决方案 |
|---|
| 两个外设使用同一引脚 | 后初始化的覆盖先前的 | 修改其中一个的引脚 |
| 引脚被系统占用 | 初始化失败 | 查阅引脚分配表 |
| I2C/SPI共享引脚 | 通信冲突 | 使用不同引脚组 |
- 在外设列表中查看所有引脚配置
- 导出
peripherals.json 搜索重复引脚 - 使用引脚分配表格记录
┌─────────────────────────────────────────┐
│ 外设ID │ 引脚 │ 用途 │
├─────────────────────────────────────────┤
│ led_main │ 15 │ 主LED │
│ led_status │ 2 │ 状态指示灯 │
│ btn_power │ 0 │ 电源按键 │
│ btn_mode │ 4 │ 模式切换 │
│ buzzer │ 5 │ 蜂鸣器 │
│ relay_pump │ 23 │ 水泵继电器 │
│ dht_temp │ 21 │ 温湿度传感器 │
│ uart_dbg │ 39,40 │ 调试串口 │
│ oled_disp │ 21,22 │ OLED屏(I2C) │ ← ⚠️ 与dht_temp冲突!
└─────────────────────────────────────────┘
修正方案:将OLED改为其他I2C引脚或软件I2C
- DHT22检测温度
- 温度>30℃时启动风扇(继电器)
- 温度<25℃时关闭风扇
- OLED显示当前温度
1. 点击"新增外设"
2. 填写:
- 外设ID: dht_room
- 名称: 房间温湿度
- 类型: 传感器(38)
- 引脚: 21
- 参数: sensorType=dht, dataField=temperature
3. 保存
1. 点击"新增外设"
2. 填写:
- 外设ID: relay_fan
- 名称: 风扇继电器
- 类型: 数字输出(12)
- 引脚: 23
- 参数: initialState=0
3. 保存
1. 点击"新增外设"
2. 填写:
- 外设ID: oled_ctrl
- 名称: 控制屏
- 类型: LCD/OLED(36)
- 引脚: 18,19 ← 使用不同引脚避免冲突
- 参数: i2cAddress=60
3. 保存
导出的 peripherals.json 应包含:
{
"peripherals": [
{
"id": "dht_room",
"name": "房间温湿度",
"type": 38,
"enabled": true,
"pins": [21],
"params": {
"sensorType": "dht",
"dataField": "temperature"
}
},
{
"id": "relay_fan",
"name": "风扇继电器",
"type": 12,
"enabled": true,
"pins": [23],
"params": {
"initialState": 0
}
},
{
"id": "oled_ctrl",
"name": "控制屏",
"type": 36,
"enabled": true,
"pins": [18, 19],
"params": {
"i2cAddress": 60
}
}
]
}
| 错误 | 原因 | 解决方案 |
|---|
| 外设不工作 | enabled=false | 启用外设 |
| 引脚初始化失败 | 引脚冲突 | 检查并修改引脚分配 |
| 传感器读数异常 | 引脚接错或类型错误 | 确认接线和sensorType |
| JSON格式错误 | 手动编辑语法错误 | 使用Web界面或JSON验证工具 |
| I2C设备不响应 | 引脚错误或地址不对 | 使用I2C扫描器确认地址 |
| 舵机抖动 | 供电不足 | 使用外部5V电源 |
| LED亮度不够 | 未串联电阻或电阻过大 | 计算合适阻值 |
- 检查启用状态:确认
enabled: true - 查看状态值:状态=4表示错误
- 查看日志:Web界面或串口日志
- 验证接线:使用万用表测量
- 简化测试:先测试单个外设
- 检查冲突:导出配置搜索重复引脚
如果页面保存成功但规则或上报仍然异常,优先对照前文“外设配置数据模型”检查引用链:peripherals.json 中的 id、外设执行规则的 targetPeriphId、传感器缓存事件 ds:<id>_<field> 必须完全一致。
- 进入 文件管理
- 下载
/config/peripherals.json - 备份到本地
- 修改JSON文件
- 通过 配置导入/导出 功能上传
- 刷新外设列表
创建常用配置模板:
{
"_templates": {
"led": {
"type": 12,
"params": { "initialState": 0 }
},
"button": {
"type": 13,
"params": { "debounceMs": 50 }
},
"dht": {
"type": 38,
"params": { "sensorType": "dht" }
}
}
}
| 优化项 | 方法 | 效果 |
|---|
| 禁用未使用外设 | enabled: false | 节省内存和GPIO |
| 降低轮询频率 | 增加传感器读取间隔 | 减少CPU占用 |
| 合并同类外设 | 使用NeoPixel代替多个LED | 简化配置 |
| 使用中断代替轮询 | 按键使用GPIO_INTERRUPT | 实时响应 |
系统采用多层内存保护机制确保长期稳定运行:
| 机制 | 阈值 | 行为 |
|---|
| PooledAllocator | 冷启动 8KB 预分配 | 消除 std::map 堆碎片 |
| WorkerPool 常驻栈 | 2×6144B = 12KB | 运行期零碎片异步执行 |
| MemGuard 动态降频 | NORMAL→WARN→SEVERE | 检查周期 1s→2s→4s |
| Web预留保护 | freeHeap<18432 | largestBlock<6144 | 暂停后台轮询 |
| 传感器LRU缓存 | 最大 entries + 120s TTL | 避免重复采集 |
建议:
- 活跃定时/轮询任务建议不超过 8 个(告警阈值),绝对上限 12 个
- 轮询间隔绝对下限 5 秒,推荐 30 秒以上
- 高负载场景(任务 > 8)轮询间隔会被自动修正为 30 秒
推荐配置组合(ESP32-S3, 320KB SRAM):
┌─────────────────────────────────────────────┐
│ 定时规则数: ≤ 6 个 │
│ 轮询间隔: ≥ 10s(少量任务时可 5s) │
│ 动作数/规则: ≤ 4 个 │
│ 脚本动作: ≤ 2 个/规则(内存开销较大) │
│ 总规则数: ≤ 20 个 │
│ 配置文件: ≤ 96KB │
└─────────────────────────────────────────────┘
- UART 外设仅在关联了轮询规则时才被轮询(按需注册)
- 帧完整性通过换行符
\n 或空闲超时 500ms 判定 - 单帧最大 160 字节,超长帧自动截断并分发
- 串口检查间隔 250ms,仅消耗微量 CPU
| 现象 | 可能原因 | 解决方案 |
|---|
| 规则不触发 | 规则未启用 / 外设 disabled | 检查 enabled 状态 |
| 定时触发延迟 | MemGuard 降频中 | 查看日志 MemGuard level changed |
| 轮询任务被暂停 | 内存不足触发 Web 预留保护 | 减少活跃任务数或增大轮询间隔 |
| 执行失败退避 | 连续失败触发 _failureBackoff | 检查目标外设硬件连接 |
| 前端编辑器加载超时 | 网络延迟 / 模块加载失败 | 刷新页面重试,检查 JS 资源加载 |
| PWM 输出无效 | 引脚不支持 PWM / 频率超限 | 验证引脚 PWM 能力和频率范围 |
| Modbus 读取超时 | 波特率不匹配 / 设备离线 | 检查串口参数和设备供电 |
调试时关注以下日志标签:
[PeriphExec] Background timer/poll suspended — 内存保护触发暂停
[PeriphExec] Background timer/poll resumed — 内存恢复后继续
[PeriphExec] MemGuard level changed — 降频级别变化
[PeriphExec] Config auto-corrected — 轮询间隔被自动修正
[PeriphExec] Worker pool started — 异步执行池启动成功
[PeriphExec] Async dispatch failed — 异步投递失败(队列满)
[PeripheralMgr] Pin conflict — 引脚冲突检测
通过 Web API 获取实时内存状态:
# 获取健康状态
GET /api/system/health
# 响应示例
{
"freeHeap": 65536,
"largestBlock": 32768,
"fragmentation": 50,
"memGuardLevel": "NORMAL"
}
当 memGuardLevel 持续为 WARN 或 SEVERE 时,建议:
- 减少同时启用的规则数量
- 增大轮询间隔到 30s 以上
- 禁用不必要的外设释放内存
- 重启设备清除碎片化
{
"id": "rule_temp_alarm",
"name": "温度超限报警",
"enabled": true,
"triggers": [{
"triggerType": 5,
"triggerPeriphId": "ds18b20_1",
"operator": 3,
"compareValue": "40",
"intervalSec": 10
}],
"actions": [{
"actionType": 1,
"targetPeriphId": "buzzer_1",
"actionValue": "1"
}]
}
说明:每 10 秒轮询 DS18B20 传感器,当温度 > 40°C 时激活蜂鸣器。
{
"id": "rule_btn_dblclick",
"name": "按键双击切换",
"enabled": true,
"triggers": [{
"triggerType": 4,
"triggerPeriphId": "btn_main",
"eventId": "evt_double_click"
}],
"actions": [{
"actionType": 4,
"targetPeriphId": "led_status",
"actionValue": ""
}]
}
说明:主按键双击时翻转状态 LED,actionType=4 为 TOGGLE 动作。
{
"id": "rule_periodic_report",
"name": "定时数据上报",
"enabled": true,
"triggers": [{
"triggerType": 3,
"intervalSec": 60
}],
"actions": [{
"actionType": 10,
"targetPeriphId": "",
"actionValue": "report_all"
}]
}
说明:每 60 秒触发一次全量数据上报,actionType=10 为脚本执行动作。
{
"id": "rule_mqtt_pwm",
"name": "MQTT控制PWM",
"enabled": true,
"triggers": [{
"triggerType": 1,
"triggerPeriphId": "pwm_fan",
"operator": 0
}],
"actions": [{
"actionType": 2,
"targetPeriphId": "pwm_fan",
"actionValue": "",
"useReceivedValue": true
}]
}
说明:收到 MQTT 数据命令时,将接收到的值直接写入 PWM 外设(useReceivedValue=true)。
提示:外设配置是FastBee系统的基石,正确的配置能避免80%的运行问题。建议先用Web界面配置,熟练后再手动编辑JSON文件。