shuichan_new/AI项目上下文.md

13 KiB
Raw Permalink Blame History

项目上下文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.2APP+BL+ soil_calib.py/soil_calib_gui.py + dist/土壤标定工具.exe 无 git STM32F030FreeModbus
自制叶面传感器 传感器/叶面传感器/代码/Leaf_HR_TP_V1.0APP+BL 无 git STM32F030FreeModbus
百叶箱环境采集 传感器/百叶窗环境采集/代码/环境采集终端代码-无气压传感器/terminal-appV2兼容精讯 无 git STM32F030FreeModbus
LoRa 参考工程 LoRA/GWLoRA/SUBLoRA/参考 无 git 网关/从机 V1.7 参考
  • 云平台:私有 MQTT broker 58.17.14.95:1880topic /iot/data/up|down/<ClientID>
  • 编译Keil C:\Keil_v5\ARM\ARMCC,命令行 UV4.exe -b <proj>.uvprojx -j0 -o Log/build.logbin 产物在 OutputBin/
  • 烧录J-LinkJLink_V796eBL 不能 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 PB13LED2 仍 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 报文里引号用字面三字符 \22C 源码写 \\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.postOTA
  • 标识符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~110MqttInfo_StrClientID/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_pct0~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\IncludeDFP 版本冲突、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路由器没活→ 冷启动重试已加