更新 README.md,重构项目概览与硬件连接说明,添加快速开始与常见问题部分

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Wang Beihong
2026-04-24 13:00:11 +08:00
parent 109bdbc848
commit 6018456f0b

483
README.md
View File

@@ -1,141 +1,234 @@
## 引脚分配 # Smart Granary Code
### IIC设备 基于 ESP-IDF 的智能粮仓监测与联动控制固件,运行于 ESP32-S3。项目集成了光照、温湿度、气体、火焰、人体/门磁、重量等多类传感器,支持本地 UI、语音交互SU-03T以及 MQTT 远程上报与控制。
这类设备有BH1750光照传感器、AHT30温湿度传感器 ## 1. 项目概览
| 设备名称 | SCL引脚 | SDA引脚 | ### 1.1 核心能力
| -------- | ------- | ------- |
- 多传感器采集BH1750、AHT30、MQ-2、JW01、火焰传感器、HX711、人体/门磁
- 本地显示LVGL + ST7789
- 两种控制模式:`manual`(手动)/`auto`(自动联动)
- 四路继电器执行:风扇、照明、制冷、加热
- 语音模块SU-03T 查询与告警播报
- 网络能力Wi-Fi AP 配网 + STA 联网 + MQTT 双向通信
### 1.2 默认运行行为
- 上电默认 `manual` 模式
- MQTT 上报周期1 秒
- 门未关告警阈值60 秒
- 粮食“变质”判定阈值:`co2 >= 1500 ppm`
- 火焰危险阈值:`fire_percent >= 35%`
## 2. 硬件连接说明
以下为当前代码中的实际引脚定义。
### 2.1 I2C 设备
BH1750 与 AHT30 共享同一 I2C 总线:
| 设备 | SCL | SDA |
| --- | --- | --- |
| BH1750 | GPIO1 | GPIO2 | | BH1750 | GPIO1 | GPIO2 |
| AHT30 | GPIO1 | GPIO2 | | AHT30 | GPIO1 | GPIO2 |
### 继电器 ### 2.2 继电器4 路)
一共有4个继电器分别控制4个设备的开关从1号到4号依次为风扇、照明灯、制冷片、加热器。 | 继电器编号 | 功能 | GPIO |
| --- | --- | --- |
| 1 | 风扇 | GPIO12 |
| 2 | 照明灯 | GPIO11 |
| 3 | 制冷片 | GPIO10 |
| 4 | 加热器 | GPIO9 |
| 设备名称 | 继电器编号 | GPIO引脚 | ### 2.3 ADC 传感器
| -------- | ---------- | -------- |
| 风扇 | 1 | GPIO12 |
| 照明灯 | 2 | GPIO11 |
| 制冷片 | 3 | GPIO10 |
| 加热器 | 4 | GPIO9 |
### ADC传感器 | 设备 | GPIO | 说明 |
| --- | --- | --- |
| 火焰传感器 | GPIO3 | 百分比采样 + 危险判定 |
| MQ-2 | GPIO8 | 有害气体/烟雾百分比 |
这个用的是ADC输入连接到GPIO3引脚。 ### 2.4 UART 设备
| 设备名称 | GPIO引脚 | | 设备 | UART | TX | RX | 波特率 |
| ---------- | -------- | | --- | --- | --- | --- | --- |
| 火焰传感器 | GPIO3 | | JW01TVOC/HCHO/CO2 | UART0 | GPIO43 | GPIO44 | 9600 |
| MQ-2 | GPIO8 | | SU-03T语音 | UART2 | GPIO42 | GPIO41 | 115200 |
### 2.5 IO 输入
### 串口设备 | 设备 | GPIO | 说明 |
| --- | --- | --- |
| HC-SR312 人体感应 | GPIO16 | 高电平表示检测到人体 |
| 门磁开关 | GPIO17 | 低电平表示门关闭 |
| 设备名称 | TX引脚 | RX引脚 | ### 2.6 称重模块
| -------- | ------ | ------ |
| 气体传感器 | GPIO4 | GPIO5 |
| 语音模块 | GPIO6 | GPIO7 |
### IO设备 | 设备 | SCK | DOUT |
| --- | --- | --- |
| HX711 | GPIO13 | GPIO14 |
| 设备名称 | GPIO引脚 | ## 3. 软件架构
| -------- | -------- |
| HC-SR312 | GPIO16 |
| 微动开关 | GPIO17 |
### 3.1 主要任务
### 称重模块 - `sensor_task`:周期读取多传感器并更新共享环境数据
- `ui_task`:驱动 UI 刷新与界面变量更新
- `status_task`:人体/门磁状态与开门超时告警
- `relay_status_task`:同步继电器状态到 UI 与上报数据
- `hx711_task`:称重采样、滤波、去皮与稳定显示
- `mqtt_publish_task`:每秒打包 JSON 并发布 MQTT
- `su03t_auto_alert_task`:语音告警节流上报(默认 3 分钟)
- `sntp_task`:联网后 SNTP 对时
| 设备名称 | GPIO引脚 | ### 3.2 模式逻辑
| -------- | -------- |
| HX711 | GPIO35 | GPIO36 |
``` - `manual`:接收 MQTT 下发的继电器开关命令,自动联动逻辑不接管
set_var_door_status("关闭"); - `auto`:按阈值自动控制制冷/制热/风扇,照明不参与自动控制
set_var_food_status("良好");
set_var_door_status("关闭"); ## 4. 开发环境要求
set_var_hum_status("有人");
set_var_hot_status("开"); ### 4.1 基础要求
set_var_cool_status("关");
set_var_fan_status("开"); - Linux 开发环境
set_var_light_status("开"); - ESP-IDF建议与当前工程一致版本需包含 `idf.py`
- USB 驱动与串口权限正常
### 4.2 目标芯片与分区
- Target`esp32s3`
- Flash Size16MB工程当前配置
- 分区表:自定义 `partitions.csv`
`partitions.csv` 当前配置:
- `nvs`0x9000, 0x6000
- `phy_init`0xF000, 0x1000
- `factory`0x10000, 4M
## 5. 快速开始
### 5.1 拉起工程
```bash
idf.py set-target esp32s3
idf.py build
``` ```
## MQTT 协议说明(上位机对接) ### 5.2 烧录并查看日志
本项目通过 MQTT 实现数据上报与远程控制。上位机可直接按以下协议开发。 ```bash
idf.py -p /dev/ttyUSB0 flash monitor
```
### 1. 连接参数与默认配置 如果你使用的是 USB Serial/JTAG可根据实际端口替换 `-p` 参数。
参数来自 menuconfig ### 5.3 VS CodeESP-IDF 插件)建议流程
1. 先执行 Build
2. 再执行 Flash
3. 最后打开 Monitor 查看日志
## 6. menuconfig 关键配置
```bash
idf.py menuconfig
```
### 6.1 Wi-Fi 连接参数
菜单位置:`WiFi 连接`
| 配置项 | 说明 | 默认值 | | 配置项 | 说明 | 默认值 |
| ------ | ---- | ------ | | --- | --- | --- |
| WIFI_CONNECT_CONNECT_TIMEOUT_SEC | 连接超时(秒) | 30 |
| WIFI_CONNECT_MAX_SCAN_RESULTS | 扫描结果上限 | 20 |
| WIFI_CONNECT_AP_MAX_CONNECTIONS | 配网 AP 最大连接数 | 4 |
### 6.2 MQTT 参数
菜单位置:`MQTT 配置参数`
| 配置项 | 说明 | 默认值 |
| --- | --- | --- |
| AGRI_ENV_MQTT_BROKER_URI | MQTT 服务器地址 | 空 | | AGRI_ENV_MQTT_BROKER_URI | MQTT 服务器地址 | 空 |
| AGRI_ENV_MQTT_USERNAME | MQTT 用户名 | 空 | | AGRI_ENV_MQTT_USERNAME | MQTT 用户名 | 空 |
| AGRI_ENV_MQTT_PASSWORD | MQTT 密码 | 空 | | AGRI_ENV_MQTT_PASSWORD | MQTT 密码 | 空 |
| AGRI_ENV_MQTT_CLIENT_ID | 客户端 ID | agri-env-monitor | | AGRI_ENV_MQTT_CLIENT_ID | 客户端 ID | agri-env-monitor |
| AGRI_ENV_MQTT_PUBLISH_TOPIC | 设备上报主题 | agri/env/data | | AGRI_ENV_MQTT_PUBLISH_TOPIC | 发布主题 | agri/env/data |
| AGRI_ENV_MQTT_SUBSCRIBE_TOPIC | 设备订阅主题 | agri/env/cmd | | AGRI_ENV_MQTT_SUBSCRIBE_TOPIC | 订阅主题 | agri/env/cmd |
协议与连接行为: ## 7. 配网说明
工程内置 AP 配网 + HTTP 控制台 + DNS 劫持流程:
1. 设备启动 APSTA开启配网热点
2. 手机连接热点后访问 `http://192.168.4.1`
3. 页面扫描附近 Wi-Fi提交 `SSID + 密码`
4. 设备连上路由后,页面可显示分配到的 STA IP
配网页面 API
- `GET /api/scan`:扫描 AP 列表
- `POST /api/connect`:提交联网参数
- `GET /api/status`:查询连接状态
- `POST /api/clear`:清除保存的 Wi-Fi 配置
- `GET /api/sysinfo`:查看运行时信息
## 8. MQTT 协议说明(上位机对接)
### 8.1 协议与连接行为
- MQTT 协议版本MQTT v3.1 - MQTT 协议版本MQTT v3.1
- 如果 Broker URI 未写协议头,会自动补成 mqtt:// 并默认端口 1883 - 连接成功后自动订阅 `AGRI_ENV_MQTT_SUBSCRIBE_TOPIC`
- 连接成功后设备自动订阅 AGRI_ENV_MQTT_SUBSCRIBE_TOPIC - 若 Broker URI 无协议头,内部会补全为 `mqtt://`,默认端口 1883
- 当前发布参数QoS=0Retain=0每秒上报一次
### 2. 主题定义 ### 8.2 主题定义
| 方向 | 主题 | 用途 | | 方向 | 主题 | 用途 |
| ---- | ---- | ---- | | --- | --- | --- |
| 设备 -> 上位机 | agri/env/data | 周期上报环境数据、设备状态、阈值配置 | | 设备 -> 上位机 | `agri/env/data` | 周期上报环境数据、状态、阈值 |
| 上位机 -> 设备 | agri/env/cmd | 下发模式切换、阈值修改、手动控制命令 | | 上位机 -> 设备 | `agri/env/cmd` | 模式切换、阈值更新、手动控制 |
发布参数(当前固件实现): ### 8.3 上报 JSON 字段agri/env/data
- 上报周期1 秒 1 次 | 字段 | 类型 | 说明 |
- QoS0 | --- | --- | --- |
- Retain0 | time | string | 设备本地时间,格式 `YYYY-MM-DD HH:MM:SS` |
| lux | number | 光照lux |
| temp | number | 温度(摄氏度) |
| humidity | number | 湿度(%RH |
| gas_percent | number | MQ-2 百分比(% |
| tvoc | number | JW01 TVOC |
| hcho | number | JW01 HCHO |
| co2 | number | JW01 CO2ppm |
| ice_weight | number | HX711 重量g |
| fire_percent | number | 火焰百分比(% |
| fire_danger | boolean | 火焰危险判定 |
| human_present | boolean | 人体存在 |
| door_closed | boolean | 门是否关闭true=关) |
| door_alarm | boolean | 门未关超时告警 |
| door_open_seconds | number | 连续开门时长(秒) |
| fan_on | boolean | 风扇继电器状态 |
| light_on | boolean | 照明继电器状态 |
| cool_on | boolean | 制冷继电器状态 |
| hot_on | boolean | 制热继电器状态 |
| su03t_last_msgno | number | SU-03T 最近消息号 |
| su03t_rx_count | number | SU-03T 累计收包次数 |
| mode | string | `auto``manual` |
| th_temp_h | number | 制冷阈值 |
| th_temp_l | number | 制热阈值 |
| th_hum_h | number | 湿度阈值 |
| th_gas_h | number | 气体阈值 |
| ip_address | string | 当前 IP |
| food_status | string | `good` / `spoilage` |
| uptime_s | number | 运行时长(秒) |
| free_heap_kb | number | 剩余堆内存KB |
### 3. 上报数据 JSONagri/env/data 上报示例:
#### 3.1 完整字段
| 字段名 | 类型 | 单位/取值 | 说明 |
| ------ | ---- | --------- | ---- |
| time | string | YYYY-MM-DD HH:MM:SS | 设备本地时间 |
| lux | number | lux | 光照强度 |
| temp | number | 摄氏度 | 温度 |
| humidity | number | %RH | 湿度 |
| gas_percent | number | % | MQ-2 气体浓度百分比 |
| tvoc | number | 传感器原始单位 | TVOCJW01 |
| hcho | number | 传感器原始单位 | 甲醛JW01 |
| co2 | number | ppm | 二氧化碳JW01 |
| ice_weight | number | g | HX711 重量值 |
| fire_percent | number | % | 火焰传感器百分比 |
| fire_danger | boolean | true/false | 火焰危险判定 |
| human_present | boolean | true/false | 人体存在状态 |
| door_closed | boolean | true/false | 门磁状态true=关门) |
| door_alarm | boolean | true/false | 门未关超时告警状态 |
| door_open_seconds | number | s | 当前连续开门时长 |
| fan_on | boolean | true/false | 风扇继电器状态 |
| light_on | boolean | true/false | 照明继电器状态 |
| cool_on | boolean | true/false | 制冷继电器状态 |
| hot_on | boolean | true/false | 制热继电器状态 |
| su03t_last_msgno | number | 0-255 | SU-03T 最近消息号 |
| su03t_rx_count | number | >=0 | SU-03T 累计收包次数 |
| mode | string | auto/manual | 当前控制模式 |
| th_temp_h | number | 摄氏度 | 制冷阈值temp >= th_temp_h 触发制冷) |
| th_temp_l | number | 摄氏度 | 制热阈值temp <= th_temp_l 触发制热) |
| th_hum_h | number | %RH | 湿度阈值humidity >= th_hum_h 触发风扇) |
| th_gas_h | number | % | 气体阈值gas_percent >= th_gas_h 触发风扇) |
| ip_address | string | IPv4 字符串 | 当前联网 IP |
| food_status | string | good/spoilage | 粮食状态(依据 co2 判定) |
| uptime_s | number | s | 设备运行时长 |
| free_heap_kb | number | KB | 剩余堆内存 |
#### 3.2 上报示例
```json ```json
{ {
@@ -152,6 +245,8 @@
"fire_danger": false, "fire_danger": false,
"human_present": false, "human_present": false,
"door_closed": false, "door_closed": false,
"door_alarm": false,
"door_open_seconds": 4,
"fan_on": false, "fan_on": false,
"light_on": false, "light_on": false,
"cool_on": false, "cool_on": false,
@@ -170,50 +265,23 @@
} }
``` ```
### 4. 下发命令 JSONagri/env/cmd ### 8.4 下发命令agri/env/cmd
下发命令为 JSON。字段按需携带,未携带字段保持原值。 字段按需携带,未携带字段保持原值。
| 字段 | 类型 | 说明 | | 字段 | 类型 | 说明 |
| ------ | ---- | ---- | | --- | --- | --- |
| mode | string | automanual | | mode | string | `auto` / `manual` |
| th_temp_h | number | 更新制冷阈值 | | th_temp_h | number | 更新制冷阈值 |
| th_temp_l | number | 更新制热阈值 | | th_temp_l | number | 更新制热阈值 |
| th_hum_h | number | 更新湿度阈值 | | th_hum_h | number | 更新湿度阈值 |
| th_gas_h | number | 更新气体阈值 | | th_gas_h | number | 更新气体阈值 |
| fan | boolean | 手动控制风扇继电器1号 | | fan | boolean | 手动控制风扇 |
| light | boolean | 手动控制照明继电器2号 | | light | boolean | 手动控制照明 |
| cool | boolean | 手动控制制冷继电器3号 | | cool | boolean | 手动控制制冷 |
| hot | boolean | 手动控制制热继电器4号 | | hot | boolean | 手动控制制热 |
### 5. 控制逻辑规则 下发示例(自动模式):
#### 5.1 手动模式mode=manual
- 支持 fan/light/cool/hot 四个布尔量直接控制继电器
- 自动联动逻辑不接管继电器
#### 5.2 自动模式mode=auto
- 制冷temp >= th_temp_h 时开启,否则关闭
- 制热temp <= th_temp_l 时开启,否则关闭
- 风扇humidity >= th_hum_h 或 gas_percent >= th_gas_h 时开启,否则关闭
- 照明:当前自动逻辑不控制照明继电器
### 6. 上电默认值
设备上电后的默认模式与阈值:
- mode = manual
- th_temp_h = 35.0
- th_temp_l = 15.0
- th_hum_h = 70.0
- th_gas_h = 20.0
- door_open_alarm_seconds = 60
### 7. 下发示例
#### 7.1 切到自动并设置阈值
```json ```json
{ {
@@ -225,7 +293,7 @@
} }
``` ```
#### 7.2 切到手动并开风扇、开制冷 下发示例(手动模式):
```json ```json
{ {
@@ -237,9 +305,142 @@
} }
``` ```
### 8. 上位机实现建 ### 8.5 SU-03T 语音命令协
- 命令下发后,以上报主题 agri/env/data 的最新数据作为状态确认 说明:
- 建议上位机做字段容错:新增字段应忽略,缺失字段使用默认显示
- 当前固件未提供独立 ACK 主题,建议在上位机侧做超时重发策略 - 串口为 UART2RX=GPIO41TX=GPIO42115200 波特率。
- 门磁告警建议以 door_alarm 与 door_open_seconds 组合显示door_alarm=true 时突出提示用户 - 语音模块上报命令时,固件按 msgno 匹配语义并立即回包。
- 数值类回包使用 8 字节 little-endian double 作为参数区。
- 状态类回包使用“仅 msgno、无参数”格式。
#### 8.5.1 查询命令映射(模块 -> 设备)
| 命令词label | key | 请求 msgno |
| --- | --- | --- |
| 温度是多少 | ask_temp | 0x00 |
| 湿度是多少 | ask_humi | 0x01 |
| 光照强度是多少 | ask_lux | 0x02 |
| 烟雾浓度是多少 | ask_mq2 | 0x03 |
| 二氧化碳浓度是多少 | ask_co2 | 0x04 |
| 粮食重量是多少 | ask_weight | 0x05 |
| 有人在吗 | ask_hum | 0x06 |
| 门磁状态 | ask_door | 0x07 |
| 风扇继电器状态 | ask_fan | 0x08 |
| 照明继电器状态 | ask_light | 0x09 |
| 制冷继电器状态 | ask_cool | 0x0A |
| 制热继电器状态 | ask_hot | 0x0B |
| 当前控制模式 | ask_control | 0x0C |
| 粮食状态 | ask_rice | 0x0D |
#### 8.5.2 回包映射(设备 -> 模块)
| 场景 | 回包 msgno | 参数 |
| --- | --- | --- |
| 温度查询返回 | 0x01 | double温度 |
| 湿度查询返回 | 0x02 | double湿度 |
| 光照查询返回 | 0x03 | doublelux |
| 烟雾查询返回 | 0x04 | doublegas_percent |
| CO2 查询返回 | 0x05 | doubleco2 |
| 重量查询返回 | 0x06 | doubleice_weight |
| 人体状态:有人 | 0x1A | 无参数 |
| 人体状态:无人 | 0x1B | 无参数 |
| 门磁状态:关门 | 0x0D | 无参数 |
| 门磁状态:开门 | 0x0C | 无参数 |
| 风扇:开 | 0x14 | 无参数 |
| 风扇:关 | 0x15 | 无参数 |
| 照明:开 | 0x20 | 无参数 |
| 照明:关 | 0x21 | 无参数 |
| 制冷:开 | 0x16 | 无参数 |
| 制冷:关 | 0x17 | 无参数 |
| 制热:开 | 0x18 | 无参数 |
| 制热:关 | 0x19 | 无参数 |
| 控制模式:自动 | 0x1C | 无参数 |
| 控制模式:手动 | 0x1D | 无参数 |
| 粮食状态:良好 | 0x1E | 无参数 |
| 粮食状态:变质 | 0x1F | 无参数 |
#### 8.5.3 主动告警(设备周期上报)
说明:语音主动告警任务每 1 秒检查一次条件,同一类告警最小间隔为 180 秒。
| 触发条件 | 告警 msgno | 参数 |
| --- | --- | --- |
| temp >= th_temp_h | 0x10 | double当前温度 |
| humidity >= th_hum_h | 0x11 | double当前湿度 |
| fire_danger = true | 0x12 | 无参数 |
| door_closed = false | 0x13 | 无参数 |
## 9. 自动联动规则
仅在 `mode=auto` 时生效:
- 制冷:`temp >= th_temp_h` 时开,否则关
- 制热:`temp <= th_temp_l` 时开,否则关
- 风扇:`humidity >= th_hum_h``gas_percent >= th_gas_h` 时开,否则关
- 照明:当前自动逻辑不控制照明
上电默认值:
- `mode = manual`
- `th_temp_h = 35.0`
- `th_temp_l = 15.0`
- `th_hum_h = 70.0`
- `th_gas_h = 20.0`
- `door_open_alarm_seconds = 60`
## 10. 目录结构(核心)
```text
.
├── main/
│ └── main.cpp # 系统入口与任务编排
├── components/
│ ├── wifi-connect/ # AP 配网、HTTP 控制台、STA 联网
│ ├── agri_env/ # MQTT 封装
│ ├── bh1750/ # 光照传感器
│ ├── MQ-2/ # 气体传感器
│ ├── JW01/ # TVOC/HCHO/CO2 传感器
│ ├── fire_sensor/ # 火焰传感器
│ ├── human_door/ # 人体/门磁检测
│ ├── relay_ctrl/ # 四路继电器控制
│ ├── su-03t/ # 语音模块协议
│ ├── lvgl_st7789_use/ # LCD + LVGL 显示
│ └── ui/ # UI 页面与变量绑定
├── partitions.csv # 分区表
├── sdkconfig # 当前工程配置
└── update_sdkconfig.sh # 常用 sdkconfig 修补脚本
```
## 11. 常见问题与排障
### 11.1 设备始终无法联网
- 检查是否连上设备热点并访问了 `http://192.168.4.1`
- 检查路由器频段ESP32-S3 常用 2.4GHz
- 在串口日志中观察 `wifi_connect` 状态机输出
### 11.2 MQTT 无法上报
- 确认 `AGRI_ENV_MQTT_BROKER_URI` 是否有效
- 确认设备已获取 STA IP且可访问 Broker
- 检查鉴权参数(用户名/密码/Client ID
### 11.3 JW01 与日志冲突
JW01 使用 UART0GPIO43/44建议保持控制台输出为 USB Serial/JTAG避免 UART0 日志与传感器数据冲突。
### 11.4 HX711 波动大
- 检查供电稳定性与接线
- 系统已内置去皮、低通与稳定锁定逻辑,仍异常时优先排查硬件噪声
## 12. 开发建议
- 新增组件时先补齐 `components/<name>/include` 对外接口,再在 `main.cpp` 挂接任务
- MQTT 字段建议保持向后兼容:新增字段不删除旧字段
- 上位机建议以 `agri/env/data` 最新数据作为控制确认(当前无独立 ACK 主题)
## 13. 许可证
当前仓库未提供独立 LICENSE 文件,如需对外发布,请补充开源许可证并在此处声明。