news 2026/4/23 16:24:16

Raspberry Pi 4 与传感器通信:串口应用实例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Raspberry Pi 4 与传感器通信:串口应用实例

树莓派4串口通信实战:从零搭建温湿度传感器数据采集系统

你有没有遇到过这样的场景?手头有一个支持UART输出的工业级温湿度传感器,想把它接到树莓派上做实时监测,结果发现串口要么打不开,要么收到一堆乱码。别急——这几乎是每个嵌入式新手都会踩的坑。

问题的关键往往不在代码,而在于树莓派默认把串口拿去当系统调试用了。更复杂的是,从Raspberry Pi 3B+开始,蓝牙模块占用了主UART资源,导致GPIO14/15引脚默认绑定的是性能不稳定的mini-UART。如果不加处理直接使用,轻则丢包重试,重则通信完全失败。

今天我们就以一个典型的Modbus RTU温湿度变送器为例,带你一步步打通树莓派4与串口传感器之间的“任督二脉”,实现稳定可靠的数据采集。


先搞清楚:你的树莓派用的是哪个UART?

在动手之前,必须弄明白一件事:树莓派4有两个UART控制器——一个是PL011(也叫uart0),另一个是mini-UART(uart1)。它们的区别可大了:

特性PL011 UARTmini-UART
时钟源独立晶振,频率稳定依赖CPU主频,随功耗调节波动
通信稳定性高,适合工业环境中低,易受系统负载影响
默认映射引脚GPIO14/15(需配置)GPIO14/15(出厂默认)

听起来是不是有点反直觉?明明硬件引脚一样,为什么还会分两种?这是因为为了给板载蓝牙腾地方,官方把原本属于PL011的GPIO14/15让给了mini-UART。

所以,如果你不做任何配置就直接打开/dev/ttyS0,大概率连的是那个“靠CPU吃饭”的mini-UART,一旦系统进入节能模式,波特率一偏移,数据全乱套。

那怎么办?答案就是:强制切换回PL011主串口


第一步:释放被“征用”的串口资源

我们要做的第一件事,就是告诉操作系统:“别再用串口打印启动信息了,我要拿来接传感器。”

1. 关闭串口控制台输出

编辑启动参数文件:

sudo nano /boot/cmdline.txt

找到这一段:

console=serial0,115200 console=tty1 root=PARTUUID=... ro rootwait

删掉console=serial0,115200这部分,保存退出。否则系统会一直往串口发日志,不仅干扰通信,还可能烧坏某些敏感传感器。

2. 启用UART硬件并锁定主控制器

接下来修改设备树配置:

sudo nano /boot/config.txt

在文件末尾添加两行:

enable_uart=1 dtoverlay=uart0
  • enable_uart=1:启用串行接口
  • dtoverlay=uart0:将GPIO14/15重新映射到PL011控制器(即uart0

⚠️ 注意:不同资料中可能会看到pi3-disable-btminiuart-bt等写法,那是旧版系统的做法。在较新的Raspberry Pi OS(Bullseye及以上)中,推荐统一使用dtoverlay=uart0来明确指定主UART。

改完之后重启:

sudo reboot

重启完成后,你可以通过以下命令验证当前串口状态:

ls -l /dev/tty*

正常情况下你会看到:
-/dev/ttyAMA0→ 指向PL011(但现在通常被蓝牙占用)
-/dev/ttyS0→ 现在应该已经指向我们想要的PL011 UART

可以通过内核消息进一步确认:

dmesg | grep tty

如果看到类似这样的输出,说明成功了:

[ 0.000000] Devicetree: Raspberry Pi 4 UART0 overlay [ 1.234567] serial_core: PL011 port mapped at 0xfe201000

第二步:连接传感器,别接反了!

物理连接看似简单,但90%的问题出在这里。

假设你用的是一个支持Modbus RTU协议的温湿度传感器(比如DFRobot SEN0394、维克多WD-33等),典型接线如下:

传感器引脚树莓派GPIO
VCC (3.3V)Pin 1 (3.3V电源)
GNDPin 6 (GND)
TXPin 10 (GPIO15/RX)← 注意交叉
RXPin 8 (GPIO14/TX)

关键点来了:传感器的TX要接树莓派的RX,反之亦然!

很多初学者误以为“TX对TX”,结果两边都在拼命发数据却谁也收不到,白白浪费半天时间排查软件问题。

另外提醒一句:绝对不要给树莓派接5V逻辑电平的设备!GPIO耐压只有3.3V,一旦接入5V TTL信号,轻则IO损坏,重则整块板报废。如果传感器是5V供电的,请务必加上电平转换芯片(如TXB0108或MAX3232)。


第三步:Python代码实战 —— 读取Modbus传感器数据

现在轮到写代码了。我们使用pyserial库来操作串口,先安装依赖:

pip install pyserial

下面是一个完整的数据读取脚本,包含初始化、命令发送、响应解析和CRC校验:

import serial import time from functools import reduce # CRC16校验函数(Modbus标准) def crc16(data): crc = 0xFFFF for byte in data: crc ^= byte for _ in range(8): if crc & 0x0001: crc = (crc >> 1) ^ 0xA001 else: crc >>= 1 return ((crc & 0xFF) << 8) | (crc >> 8) # 初始化串口 def init_serial(port='/dev/ttyS0', baudrate=9600, timeout=1): try: ser = serial.Serial( port=port, baudrate=baudrate, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=timeout ) if ser.is_open: print(f"✅ 串口 {port} 打开成功,波特率: {baudrate}") return ser except Exception as e: print(f"❌ 无法打开串口: {e}") return None # 读取温湿度传感器数据(功能码0x03) def read_modbus_sensor(ser, slave_addr=1, reg_start=0x0000, reg_count=2): # 构造请求帧: [设备地址][功能码][起始寄存器高][低][数量高][低][CRC16_L][H] command = [ slave_addr, 0x03, (reg_start >> 8) & 0xFF, reg_start & 0xFF, (reg_count >> 8) & 0xFF, reg_count & 0xFF ] crc = crc16(command) command.append(crc & 0xFF) # CRC低字节 command.append((crc >> 8) & 0xFF) # CRC高字节 # 发送请求 ser.write(bytes(command)) # 等待响应(根据传感器手册调整延迟) time.sleep(0.15) # 读取可用数据 if ser.in_waiting < 5: return None, None # 帧头都不够,直接放弃 # 先读前5字节判断是否合法响应 header = ser.read(5) if len(header) != 5 or header[0] != slave_addr or header[1] != 0x03: ser.reset_input_buffer() return None, None # 读取剩余数据(数据长度在第5字节) data_len = header[2] remaining = ser.read(data_len + 2) # 数据 + CRC full_response = header + remaining if len(full_response) != 5 + data_len + 2: return None, None # CRC校验 recv_crc = (full_response[-1] << 8) | full_response[-2] calc_crc = crc16(full_response[:-2]) if recv_crc != calc_crc: print("⚠️ CRC校验失败") return None, None # 解析温湿度(假设为连续两个16位寄存器) temp_raw = (full_response[3] << 8) | full_response[4] humi_raw = (full_response[5] << 8) | full_response[6] temperature = -45 + 175 * temp_raw / 65535.0 humidity = 100 * humi_raw / 65535.0 return round(temperature, 2), round(humidity, 2) # 主循环 if __name__ == "__main__": uart = init_serial('/dev/ttyS0', 9600) if not uart: exit(1) print("📡 开始采集温湿度数据...") try: while True: temp, humi = None, None for i in range(3): # 最多重试3次 temp, humi = read_modbus_sensor(uart) if temp is not None: break time.sleep(0.3) if temp is not None and humi is not None: print(f"[+] 温度: {temp:.2f}°C, 湿度: {humi:.2f}%") else: print("[-] 未获取有效数据,请检查接线或配置") time.sleep(2) except KeyboardInterrupt: print("\n⏹️ 用户中断,程序退出") finally: uart.close()

关键设计说明:

  • CRC校验独立实现:避免因第三方库兼容性问题导致校验失败
  • 分步读取机制:先读头部判断合法性,再读后续数据,防止缓冲区错位
  • 自动重试逻辑:工业环境中偶尔丢包很正常,三次重试能显著提升鲁棒性
  • 合理延时控制:Modbus规定从机响应时间一般为20~200ms,太短会读不到数据,太长影响效率

常见问题怎么破?

❓ 串口打不开,提示权限不足?

运行:

sudo usermod -aG dialout pi

然后重启生效。这个组专门用来管理串口设备访问权限。

❓ 收到的数据总是错位或乱码?

优先检查三点:
1. 波特率是否匹配(常见有9600、19200、38400、115200)
2. 是否启用了dtoverlay=uart0
3. 接线是否TX-RX交叉、GND共地

可以用示波器或逻辑分析仪抓一下波形,看看实际波特率有没有漂移。

❓ 多个串口设备怎么接?

树莓派原生只提供一组UART。如果需要挂多个Modbus设备,有两种方案:

  1. 使用RS-485总线:所有设备并联在同一对差分线上,靠地址区分,适合远距离部署;
  2. I²C转多路UART扩展芯片:如SC16IS752,通过I²C控制即可扩展出两个额外串口,适用于紧凑型设计。

工程级建议:不只是“能用”

当你准备把这个方案用于实际项目时,以下几个优化点值得考虑:

✅ 使用非阻塞或异步方式

不要让主线程卡在read()上。可以结合threading.Thread或将串口读取放入单独协程中处理。

✅ 添加日志记录

import logging logging.basicConfig(filename='sensor.log', level=logging.INFO)

便于后期追溯异常情况。

✅ 实现看门狗机制

长时间运行下可能出现串口“假死”。定期检测最后通信时间,超时则自动重启串口实例。

✅ 电源管理

传感器尽量单独供电,尤其是电流较大的型号(如PMS5003激光粉尘仪),避免拉低树莓派电压导致重启。


写在最后

看到这里,你应该已经掌握了如何让Raspberry Pi 4真正发挥其作为嵌入式网关的能力——不再是简单的USB外设堆叠,而是深入到底层硬件层面,精准掌控每一个字节的传输。

这套方法不仅适用于温湿度传感器,同样可用于pH计、CO₂模块、风速仪等各种支持UART/Modbus协议的工业设备。只要理解了“关闭console → 切换主UART → 正确接线 → 协议解析”这条主线,绝大多数串口通信问题都能迎刃而解。

下一步你可以尝试:
- 把采集到的数据通过MQTT上传到Home Assistant
- 结合SQLite做本地存储,构建离线可用的小型监控站
- 加入Web界面,做成一个简易的环境监测仪表盘

技术的魅力就在于此:几个引脚、几行代码,就能把物理世界的信息带进数字空间。

如果你在实践中遇到了其他挑战,欢迎留言交流。我们一起把这块小卡片,变成真正的智能感知中枢。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:32:13

飞书文档批量导出的高效解决方案

飞书文档批量导出的高效解决方案 【免费下载链接】feishu-doc-export 项目地址: https://gitcode.com/gh_mirrors/fe/feishu-doc-export 在数字化办公日益普及的今天&#xff0c;团队知识库的迁移和备份已成为许多企业面临的现实挑战。当需要将飞书文档批量导出到本地时…

作者头像 李华
网站建设 2026/4/23 11:23:00

SpringBoot+Vue 可信捐赠系统管理平台源码【适合毕设/课设/学习】Java+MySQL

摘要 随着互联网技术的快速发展&#xff0c;公益慈善事业逐渐走向数字化和透明化。传统的捐赠方式由于缺乏有效的监管和透明度&#xff0c;导致公众对慈善机构的信任度下降。为了解决这一问题&#xff0c;基于现代技术的可信捐赠系统管理平台应运而生。该系统通过区块链技术的去…

作者头像 李华
网站建设 2026/4/23 11:29:33

SpringBoot+Vue 美发管理系统平台完整项目源码+SQL脚本+接口文档【Java Web毕设】

摘要 随着信息技术的快速发展和美发行业的不断壮大&#xff0c;传统的美发管理模式已难以满足现代业务需求。美发店在客户管理、预约服务、员工调度等方面面临着效率低下、信息不透明等问题。为了解决这些问题&#xff0c;开发一套高效、智能的美发管理系统显得尤为重要。该系统…

作者头像 李华
网站建设 2026/4/23 16:12:10

PaddlePaddle镜像能否用于文档布局分析?LayoutLM尝试

PaddlePaddle镜像能否用于文档布局分析&#xff1f;LayoutLM尝试 在金融、政务和医疗等行业&#xff0c;每天都有成千上万的非结构化文档——发票、合同、病历表单——等待处理。这些文件往往格式不一、排版复杂&#xff0c;传统OCR只能“看见”文字&#xff0c;却无法理解“哪…

作者头像 李华
网站建设 2026/4/23 13:01:44

洛雪音乐六音音源故障修复实战指南:手把手教你恢复音乐播放

洛雪音乐六音音源故障修复实战指南&#xff1a;手把手教你恢复音乐播放 【免费下载链接】New_lxmusic_source 六音音源修复版 项目地址: https://gitcode.com/gh_mirrors/ne/New_lxmusic_source 还在为洛雪音乐升级后无法播放歌曲而烦恼吗&#xff1f;&#x1f914; 六音…

作者头像 李华
网站建设 2026/4/23 16:15:33

PotPlayer字幕翻译插件:百度翻译API的完整配置指南

想在观看外语视频时享受流畅的字幕翻译体验&#xff1f;PotPlayer字幕翻译插件结合百度翻译API&#xff0c;为你的观影体验带来革命性改变。这款实用工具能够实时将外文字幕转换为中文&#xff0c;让你轻松理解视频内容&#xff0c;无需再为语言障碍烦恼。 【免费下载链接】Pot…

作者头像 李华