智能硬件 · 2026/5/24
ESP32-C3 读取 RS485 土壤温湿度传感器:接线、共地和 Modbus 排障记录
记录 ESP32-C3 通过 Mini TTL-RS485 模块读取土壤温湿度传感器的完整排障过程:TX/RX 不交叉、TTL-GND 与 485-GND 必须共地、实际地址 0x04、波特率 9600。
这次调试的是一套很常见、也很容易卡住的小系统:ESP32-C3 开发板,通过芯路城 Mini TTL 转 RS485 模块,读取 ZTS-3000-TR-WS-* 土壤温湿度传感器。
一开始看起来只是“ESP32-C3 读不到 RS485 数据”,但最后真正踩到的坑有三个:TTL 侧 TX/RX 接法、传感器实际 Modbus 地址/波特率、以及模块两端 GND 是否共地。
最终可用接线
芯路城这个 Mini TTL 转 RS485 模块的 TTL 侧比较特殊,资料注明 TX/RX 不需要反接。实测确认,最终可用接线是:
ESP32-C3 GPIO0 TX -> RS485 模块 TXD
ESP32-C3 GPIO1 RX -> RS485 模块 RXD
ESP32-C3 3V3/5V -> RS485 模块 VCC
ESP32-C3 GND -> RS485 模块 TTL-GND
RS485 模块 A+ -> 传感器 A
RS485 模块 B- -> 传感器 B
传感器电源 V+ -> 按传感器要求供电,4.5-30V DC
传感器 GND -> 与 ESP32-C3 GND / RS485 模块 485-GND 共地
这里最反直觉的是 TTL 侧:不是常规的 `TX -> RXD`、`RX -> TXD`,而是 `TX -> TXD`、`RX -> RXD`。按常规交叉接法时,程序一直发查询帧,但收不到任何回包。
模块 VCC:3.3V 和 5V 都能读,但长期建议 3.3V
这个 Mini TTL-RS485 模块资料写的工作电压范围是 `3.0V~5.5V`。实测 VCC 接 ESP32-C3 的 3.3V 可以读,接开发板 5V 也可以读。
但长期使用更建议接 3.3V。原因是 ESP32-C3 的 GPIO 不是 5V 容忍输入。如果模块由 5V 供电,TTL 侧 TXD 高电平可能接近 5V,存在把 ESP32-C3 RX 脚打高压的风险。短时间测试可以,长期部署不值得赌。
必须共地:不共地时完全没有回包
这个模块的 TTL-GND 和 485-GND 实测不连通。做了一组对比:
TTL-GND 与 485-GND 不连通:
扫描 4800/9600/2400/19200、地址 0x04 与 0x01-0x0A,全部 RX [0]
TTL-GND 与 485-GND 连通:
扫描命中 9600 / 地址 0x04,稳定返回湿度与温度
所以在这套桌面/短线系统里,建议把这些地连在一起:
ESP32-C3 GND
RS485 模块 TTL-GND
RS485 模块 485-GND
传感器电源 GND
RS485 是差分信号,但收发器仍然需要共模电压落在可接受范围内。两端地完全漂着时,A/B 相对收发器参考点可能跑出范围,于是表现为“主机一直发,传感器像没存在过”。
传感器实际通信参数
PDF 手册写的是:
协议: Modbus-RTU
默认地址: 0x01
波特率: 4800
串口格式: 8N1
读取命令: 读保持寄存器 0x0000 起,长度 2
但这只代表默认值。实测这只传感器当前参数是:
实际地址: 0x04
波特率: 9600
串口格式: 8N1
所以最终查询帧是:
04 03 00 00 00 02 C4 5E
典型返回帧:
04 03 04 01 14 00 00 EE CB
解析方式:
寄存器 0: 土壤湿度,uint16 / 10,单位 %
寄存器 1: 土壤温度,int16 / 10,单位 C
示例:
Raw moisture = 0x0114 = 276 -> 27.6 %
Raw temperature = 0x0000 = 0 -> 0.0 C
实测输出
共地之后,程序启动扫描命中:
Detected baud: 9600
Detected address: 0x04
随后稳定读取:
TX [8]: 04 03 00 00 00 02 C4 5E
RX [9]: 04 03 04 01 14 00 00 EE CB
Raw moisture=276, raw temperature=0
Soil moisture: 27.6 %, soil temperature: 0.0 C
ESP32-C3 引脚选择注意
这次最终使用:
TX = GPIO0
RX = GPIO1
不建议用 GPIO11 做 UART RX。ESP32-C3 的 GPIO11 与 VDD_SPI/Flash 供电相关,很多开发板并不适合拿它当普通串口脚。
另外,如果你的开发板是原生 USB-Serial/JTAG 的 ESP32-C3,Arduino CLI 烧录时建议启用 USB CDC,否则可能只能看到 ROM 启动日志,看不到程序里的 `Serial.println()`:
arduino-cli compile --fqbn 'esp32:esp32:esp32c3:CDCOnBoot=cdc,FlashMode=dio,FlashFreq=40' /path/to/esp32c3_soil_modbus
arduino-cli upload -p /dev/cu.usbmodem212401 --fqbn 'esp32:esp32:esp32c3:CDCOnBoot=cdc,FlashMode=dio,FlashFreq=40' /path/to/esp32c3_soil_modbus
如果是 WCH/CH340 之类 USB 串口开发板,端口名可能是 `/dev/cu.wchusbserial...`,且不一定需要 `CDCOnBoot=cdc`。
程序上的处理
最终 Arduino 程序做了这些事:
- 不依赖第三方库,只使用 `Serial1`
- 自己实现 Modbus CRC16
- 启动时扫描常见波特率和地址,优先尝试地址 `0x04`
- 持续读取寄存器 `0x0000` 起的 2 个保持寄存器
- 打印 TX/RX 原始帧,方便排查
- 对前导杂字节做滑窗容错,避免偶发 `FE` / `FF` 让整帧判坏
排障顺序建议
如果你也遇到 ESP32-C3 读 RS485 土壤温湿度传感器没有数据,可以按这个顺序查:
- 传感器是否按要求单独供电,通常是 4.5-30V DC。
- ESP32-C3 GND、RS485 模块 TTL-GND、RS485 模块 485-GND、传感器电源 GND 是否共地。
- 这个芯路城 Mini 模块 TTL 侧是否按 `TX -> TXD`、`RX -> RXD` 接。
- RS485 A/B 是否需要对调。
- 传感器地址和波特率是否被改过,不要只相信手册默认值。
- ESP32-C3 是否用了不适合的 GPIO,比如 GPIO11。
- 如果只能看到启动日志,看不到程序输出,检查 `CDCOnBoot=cdc`。
最后结论
这次真正让通信恢复的组合是:
GPIO0 TX -> 模块 TXD
GPIO1 RX -> 模块 RXD
TTL-GND 与 485-GND 共地
传感器地址 0x04
波特率 9600
这类问题很容易被误判成“代码错”或“Modbus CRC 错”。但从这次过程看,最关键的仍然是物理层:地参考、模块丝印语义、传感器实际地址/波特率。只要这些对上,ESP32-C3 读取 RS485 土壤温湿度数据就很稳定。