news 2026/4/18 10:04:17

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/18 9:41:18

Arduino创意作品结合DHT11的数据采集系统构建

从零构建温湿度监测系统&#xff1a;Arduino与DHT11的实战指南你有没有试过走进一个房间&#xff0c;感觉闷热潮湿却说不清具体数值&#xff1f;或者担心家里的植物是不是缺水了&#xff1f;其实&#xff0c;这些日常问题都可以通过一个不到30元的小装置来解决——用Arduino D…

作者头像 李华
网站建设 2026/4/17 22:03:36

探索大数据领域数据仓库的多维分析技术

探索大数据领域数据仓库的多维分析技术&#xff1a;从“数据迷宫”到“决策地图” 一、引入与连接&#xff1a;为什么我们需要多维分析&#xff1f; 想象这样一个场景&#xff1a;你是某电商公司的运营经理&#xff0c;早上刚到办公室&#xff0c;就收到老板的灵魂拷问&#xf…

作者头像 李华
网站建设 2026/4/18 9:45:48

基于SpringBoot+Vue的考勤管理系统管理系统设计与实现【Java+MySQL+MyBatis完整源码】

摘要 随着企业信息化建设的不断推进&#xff0c;传统的人工考勤管理方式已难以满足现代企业对高效、精准管理的需求。纸质考勤记录易丢失、统计效率低下且容易出错&#xff0c;而分散的电子表格管理缺乏系统性和安全性&#xff0c;难以实现数据的实时共享与分析。为解决这一问题…

作者头像 李华
网站建设 2026/4/18 6:33:18

Java Web 考务报名平台系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着教育信息化的快速发展&#xff0c;考务管理系统的数字化和智能化需求日益增长。传统考务报名方式依赖人工操作&#xff0c;存在效率低、错误率高、信息孤岛等问题&#xff0c;难以满足大规模考试报名的需求。为解决这一问题&#xff0c;基于现代Web技术的考务报名平台…

作者头像 李华
网站建设 2026/4/18 4:37:42

PaddlePaddle镜像能否用于电商商品标题生成?Seq2Seq实战

PaddlePaddle镜像能否用于电商商品标题生成&#xff1f;Seq2Seq实战 在电商平台日均新增数万商品的今天&#xff0c;如何高效、一致地生成吸引点击又符合SEO规范的商品标题&#xff0c;已经成为运营团队的核心挑战。人工撰写不仅耗时费力&#xff0c;还容易因风格不统一影响品牌…

作者头像 李华