shuichan_new/AI项目上下文.md

151 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 项目上下文AI 协作速查,新会话开场贴给 AI 阅读)
> 本文件汇总多项目的结构、约定和踩坑记录。新会话开始时提供给 AI可跳过漫长的项目探索。
## 1. 仓库与工程
| 项目 | 本地路径 | git 仓库 | 说明 |
| --- | --- | --- | --- |
| 控制终端(投料机/四路继电器) | `控制终端/STM32F103_App1` + `STM32F103_BootLoader` | `ssh://nky@58.17.14.95:90/helei/shuichan_new.git` | 当前 V1.7.0 (FreeRTOS**新板引脚重排,不兼容老板**;老仓库 shuichan.git 定格 V1.6.5) |
| 采集终端(农业传感器采集) | `采集终端/V1.0/STM32F103_App1` + `STM32F103_BootLoader` | `http://58.17.14.95:8001/helei/nongye.git` | 当前 V1.0.1 |
| 自制土壤传感器 | `土壤传感器/代码/Soil_HR_TP_V0.2`APP+BL+ `soil_calib.py`/`soil_calib_gui.py` + `dist/土壤标定工具.exe` | 无 git | STM32F030FreeModbus |
| 自制叶面传感器 | `传感器/叶面传感器/代码/Leaf_HR_TP_V1.0`APP+BL | 无 git | STM32F030FreeModbus |
| 百叶箱环境采集 | `传感器/百叶窗环境采集/代码/环境采集终端代码-无气压传感器/terminal-appV2兼容精讯` | 无 git | STM32F030FreeModbus |
| LoRa 参考工程 | `LoRA/GW`、`LoRA/SUB`、`LoRA/参考` | 无 git | 网关/从机 V1.7 参考 |
- 云平台:私有 MQTT broker `58.17.14.95:1880`topic `/iot/data/up|down/<ClientID>`
- 编译Keil `C:\Keil_v5\ARM\ARMCC`,命令行 `UV4.exe -b <proj>.uvprojx -j0 -o Log/build.log`bin 产物在 `OutputBin/`
- 烧录J-Link`JLink_V796e`BL 不能 OTA 只能线刷
- 提交 git 前先跑 `keilkill.bat` 清编译产物
## 2. 源码约定(极重要,反复踩坑)
- **版本号 `FIRMWARE_VERSION_STR` 不要主动加**:功能更新时用户没明确说升版本就不动(小改动也涨版本会失控)
- **所有 APP 源文件(.c/.h是 GBK 编码**Read/Edit 工具无法直接处理,一律用 python 脚本(读 gbk、改、encode 验证后写)
- **heredoc 转义陷阱**python 脚本写 C 代码时高发):
- `\22` 在 python 字符串里会变成八进制 0x12——构造 AT 命令 JSON 转义时必须用 `chr(92)` 拼反斜杠
- `'\\r'`/`'\\n'` 会被写成字面 CR/LF 导致编译错——用 `chr(13)``chr(92)+'r'` 构造
- `\a` 会变 BEL(0x07) 曾把 uvprojx 搞坏
- 写中文字符串后必须 `s.encode('gbk')` 验证再落盘
- Keil 工程必须带编译选项 `--no_multibyte_chars`(中文字符串字节原样输出)
- 串口日志是 GBK 中文,上位机/蓝牙 APP 字符集必须选 GBK否则乱码+吞换行)
- 修改文件路径含中文时,先 `cd` 进目录再用相对路径(绝对路径在 bash/python 里偶发编码错乱)
## 3. 硬件资源分配两个终端共用板型GD32F103RCT6 256K
> **注意**:下表为老板型(采集终端仍用)。**控制终端 V1.7.0 起换新板**,引脚重排见本节末尾附表。
| 用途 | 接口 | 引脚/说明 |
| --- | --- | --- |
| 日志+蓝牙 HLK-B40 | USART1 | PA9/PA10115200BT_MODE=PB0(开漏)BT_RST=PA7 |
| 485 传感器 | USART2 | PA2/PA39600DMA+IDLE 定帧 |
| 4G Air780E/EG | USART3 | PB10/PB11921600CAT_PWR=PC4(开漏拉低=开机,置高=断电) |
| WiFi ESP-01S | UART4 | PC10/PC11921600ESP_RST=PA5ESP_EN=PA6(高有效) |
| HLW8032 计量 | UART5 | PD2 只收(仅控制终端) |
| 继电器×4 | 输出 | PB7/PB8/PC0/PC2高吸合反馈 PB6/PB9/PC1/PC3 |
| 电量/断电检测 | ADC1 | PA0分压比 11 |
| OLED(带字库IC) | 软件SPI | CLK=PC12 MOSI=PC9 DC=PC8 CS1=PC7 FSO=PC6 CS2=PB15 RST=PB14 |
| W25Q64 | 软件SPI | CS=PB4 CLK=PB3 DO=PB5 DI=PA15 |
| EEPROM AT24C02 | 软件I2C | 存 MQTT 配置等 |
| LED | | LED2=PC13(喂 TPL5010 外狗)NET_LED=PA1 |
| 看门狗 | IWDG + TPL5010 | idle 钩子喂 IWDGLED2 翻转喂外狗,**BL 等待循环也必须喂外狗** |
### 控制终端新板引脚表V1.7.0 起,仅控制终端)
| 用途 | 引脚 |
| --- | --- |
| 串口USART1 蓝牙日志 / USART2 485 / USART3 4G / UART4 WiFi / UART5 计量) | 不变PA9/PA10、PA2/PA3、PB10/PB11、PC10/PC11、PD2 |
| CAT_PWRDCDC EN4G 供电) | **PC1 开漏,释放=工作、拉低=掉电(与老板反相!)** |
| CAT_RST直连 Air780E 复位脚) | PA4 开漏,拉低=复位、释放=工作(复位脉冲后必须释放) |
| BT_MODE / BT_RST | **PC4** / PA7 |
| RELAY1~4 / 反馈 | **PC2/PA1/PB12/PB1**;反馈 **PC0/PC3/PC5/PB0** |
| NET_LED | **PB13**LED2 仍 PC13 |
| EEPROM I2CSCL/SDA | **PB5/PB4** |
| W25Q64CS/DO/CLK/DI | **PB8/PB9/PB6/PB7** |
| OLEDCS2/FSO/CS1/DC/MOSI/CLK/RES | **PC12/PA12/PC8/PC9/PA15/PB3/PA11** |
| HR_IN 缺料检测 | **PA8 下拉输入,高=缺料→停投料关继电器1只记日志不接传感器不影响投料** |
| KEY1~4 | **PC6/PC7/PB14/PB15 上拉输入,功能预留** |
| 取消 | PA8 手动模式开关MANUAL_MODE 已删) |
| 开机二维码 | 已配置身份时开机 OLED 显示 10s内容=ClientIDqrcodegen 生成),右侧附 ID 文本 |
**485 总线多从机V1.7.1 起)**:称重秤 0x01Modbus 读重量)+ 扩展继电器板 0x10FC05 控制/FC03 读状态,协议见 `Docs/RS485扩展继电器协议.md`);收帧统一在 feedScaleProcess 按站号分发,发送共用 uart.c 的 rs485_bus 时间戳做 50ms 静默保护;平台标识符 sw5~sw8蓝牙 R5ON~R8OFF扩展板状态断电记忆Relay_State[5] 位掩码),离线→上线自动比对恢复
## 4. 云平台协议
- 上报:`{"header":"iot.prop.post","body":{...}}`4G 通道 AT 报文里引号用**字面三字符 `\22`**C 源码写 `\\22`),不能丢反斜杠(踩过两次)
- **平台只认 UTF-8**发往平台的中文文案不能直接写汉字GBK 源码→GBK 字节→平台乱码,实测),必须用 UTF-8 字节的 `\x` 转义写法(如 `"负载断开或继电器损坏"` = `"\xE8\xB4\x9F\xE8\xBD\xBD\xE6\x96\xAD\xE5\xBC\x80\xE6\x88\x96\xE7\xBB\xA7\xE7\x94\xB5\xE5\x99\xA8\xE6\x8D\x9F\xE5\x9D\x8F"`);串口日志则相反必须 GBK上位机字符集是 GBK
- 下行:`iot.prop.set`(控制终端继电器)、`iot.ota.upgrade.post`OTA
- 标识符sw1~sw4/feeding板载继电器、**sw5~sw8485 扩展继电器板V1.7.1 起,在线才上报)**、weight/zero/onceWt、energy/pow、power="220V,0.21A,46.2W"字符串、GPS"经度,纬度"高德格式、iccid、fwver"1.6.5:3"版本串+序号、ver数字版本序号、BAT_VAL采集终端电量
- 传感器标识符采集终端PH/EC/BS_T/BS_RH/BS_DO/DS_T/DO/BY_TP/BY_RH/BY_HV/BY_CO2/YSMD_TP/YSMD_RH/SOIL_TP/RH/NV/PV/KV/PH/RV/WIND
- 协议解析助手在 `m_app/proto.c`(不用完整 JSON 库)
## 5. EEPROM 布局AT24C02两个终端共用
- 0~110`MqttInfo_Str`ClientID/Username/Password/ServerIP/Topic/Port/Relay_State[7]/Magic=0xDEADBEEF/Ver
- 102继电器状态Relay_State[1~4]=板载 sw1~sw4**[5]=485 扩展板 sw5~sw8 位掩码0xFF 空白视为全断**120~124秤去皮/单次投料/初始化标志
- 132~157BLE 名缓存158BLE 功率160日志等级
- 164~171电能脉冲控制终端172产品模式173GPS 开关175~194OTA 任务 id
- **200~244WiFi 热点配置magic=0xA6@200SSID 22B@201PASS 22B@223**
- 250EEPROM 探测字节
- **身份配置**:固件不含 MQTT 身份,`SETMQTT` 蓝牙灌入 EEPROMMagic+ClientID 非空=已配置否则进待配置模式跳过网络OLED 提示)
- `FACTORY`:整片 EEPROM 写 0xFF 恢复出厂(清 WiFi 配置但不清 ESP 模块里 SmartConfig 的热点,那个用 WIFIRESET
## 6. 蓝牙命令(当前全集,不区分大小写,空格分隔参数)
RESET / INFO / MQTTINFO / STATUS / HELP(逐条中文)
SETMQTT id user pass保存后自动重启/ SETIP ip port / FACTORY / SETWIFI ssid pass / WIFIINFO / WIFICLEAR / WIFIRESET
R1ON~R4OFF/ALLON/ALLOFF控制终端板载/ **R5ON~R8OFF485 扩展继电器板V1.7.1 起)** / FEEDSTART kg / FEEDSTOP / FEED控制终端投喂
SCALE/SCALE0/SCALE1控制终端/ GPS/GPS0/GPS1 / ENCLR控制终端电能清零/ HISTORY控制终端重启记录/ BLESET / LOGTRACE~LOGFATAL / OTA
## 7. OTA 架构(两终端相同)
- 流程MQTT 下发 iot.ota.upgrade.post → HTTP Range 3072B/块下载 → W25Q64 暂存 → CRC16+固件头校验 → 复位进 BL → BL 备份 APP1/搬运/试运行计数3 次失败回退)→ APP 联网后确认MQTT ready + 首次发布 + 延迟9s
- 版本防重复:`new_ver > MqttInfoStr.Ver` 才下载健康检查MQTT ready 后 1 分钟无首次 MPUB 复位并消耗一次试错
- OLED 进度页:`NET_UI_OTA` 阶段 + `g_ota_pct`0~100入口 `air780e_trigger_ota`/`net_wifi_ota` 置位
- **OTA 期间业务全停**`g_ota_active` 标志sensor_process/relayCmdProcess 跳过WiFi 中止自动恢复4G 失败路径本就复位
## 8. 网络层network.c 抽象)
- 4G模组内置 MQTTAir780 AT 指令)与 WiFiESP-01S TCP 透传+MCU 软件 MQTT 3.1.1)统一 NET_* 接口,共享 U2_CopyBuff 接收缓冲net_at_mutex 互斥
- 通道选择V1.7.1 起改为**开机按键手动选择**,仅控制终端新板):欢迎页后 10s 倒计时KEY1=4G/KEY2=WiFi固定/KEY3=配网,超时=EEPROM(130)记忆的上次选择首次默认4G选定后锁定通道原地重试**不再自动回退**;老版本(含采集终端)仍是 EEPROM 记忆优先+4G/WiFi 自动回退循环
- **心跳阶梯**防误复位30s PINGREQ无应答立即 3s 快探测,连续 5 次约42s判死 → 先原 TCP 重发 CONNECT失败再完整重建链路**不整机复位**
- ESP_EN 断电重启esp_reset 先断电 500ms 再上电治模块半死CWJAP 冷启动失败自动重试一次;连上后 AT+CWJAP? 打印信号强度%(含 busy 重试)
- WiFi 就绪后 4G 断电省电(老板 CAT_PWR 置高;**控制终端新板 PC1 反相为拉低=掉电**
## 9. 485 传感器总线(采集终端)
| 地址 | 传感器 | 寄存器 | 上报标识符 |
| --- | --- | --- | --- |
| 0x01 | 水体PH-EC | 0x0000/2 | PH, EC |
| 0x02 | 大气压温湿度 | 0x0000/12 | BS_T, BS_RH, BS_DO |
| 0x03 | 溶解氧DO59 | 0x2500启动/0x2600读4 | DS_T, DO |
| 0x06 | 百叶箱 | 0x0000/9 | BY_TP, BY_RH, BY_HV, BY_CO2 |
| 0x07 | 叶面温湿度(自制) | 0x0020/2 | YSMD_TP, YSMD_RH |
| 0x08 | 土壤温湿度(自制) | 0x0012/2 | SOIL_TP, SOIL_RH |
| 0x09 | 氮磷钾 | 0x001E/3 | SOIL_NV/PV/KV |
| 0x0A | 土壤PH | 0x0006/1 | SOIL_PH |
| 0x0B | 土壤EC | 0x0015/1 | SOIL_RV |
| 0x0C | 风速(聚碳) | 0x0000/1 值×10 | WIND |
- **传感器间必须 ≥50ms 间隔**(从机 485 释放/回声沉降,否则下一个查询撞帧读不到——实测踩坑)
- **DO59 必须用真实地址 0x03 查询,禁用 0xFF 通配**(聚碳风速也认 0xFF 会抢答导致误上线)
- 各传感器实际地址可能和表不符(不同批次),接不上先查地址;精讯 JXBS 改地址寄存器 0x0100聚碳风速 0x07D0+波特率 0x07D1
## 10. 自制传感器固件(土壤/叶面STM32F030
- 寄存器0x12湿度/0x13温度0.1单位0xB5 实时 ADC0xA0 标定标志(0x8000+点数)0xA1~RH点0xAB~ADC点0x0100 地址0x0101 波特率(0/1/2=2400/4800/9600)
- 标定写入顺序:先清标志→写点→最后写标志(标志变化才落 Flash**先写点后写标志**否则不保存
- 土壤 ADC湿度越大 ADC 越大;**叶面相反(湿度越大 ADC 越小)**——上位机已做方向自动识别
- 标定:两点法(空气=0%/水中=100%)够用;多点法需天平+105℃烘干箱按官方流程
- 上位机:`土壤传感器/soil_calib_gui.py` → PyInstaller 打包 `dist/土壤标定工具.exe`(单文件免环境);打包环境在 `packenv/`+`python/`(独立 Python3.13,本机 Python3.14 太新不支持 PyInstallerGitHub 下载需开系统代理127.0.0.1:7897
- **编译老工程2023 年 SPL 工程)三件套**IncludePath 补 `Library\CMSIS\Device\ST\STM32F0xx\Include` + `Library\CMSIS\Include`DFP 版本冲突、fromelf 路径改本机、pArmCC/pCCUsed 编译器锁定字段清空Flash 算法 `$$Device` 宏失效要改绝对路径 `C:\Keil_v5\ARM\PACK\Keil\STM32F0xx_DFP\2.1.0\CMSIS\Flash\STM32F0xx_64.FLM`
## 11. 已知历史问题(已修,勿再引入)
- FreeModbus portserial.cTC 中断重复驱动发送状态机查询快传感器重启——TC 只清标志
- SHT20 测量就绪 do-while 无超时——已加 200 次上限约1.2s)返回上次值
- BL 门禁等待循环只喂 IWDG 没喂 TPL5010 外狗——已补 EXT_WDOG_FEED
- 低电压两级滞回APP <10% 主动复位BL <20% 不放行阈值按各自 BAT 公式算 ADC 原始值
- 心跳超时复位后发现热点 CWJAP:3路由器没活)→ 冷启动重试已加