news 2026/4/16 18:24:40

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/15 13:28:30

【2025最新】基于SpringBoot+Vue的客户管理系统管理系统源码+MyBatis+MySQL

摘要 随着信息技术的飞速发展&#xff0c;企业对客户管理的需求日益增长&#xff0c;传统的客户管理方式已无法满足现代企业高效、精准的管理需求。客户管理系统通过数字化手段整合客户信息&#xff0c;优化业务流程&#xff0c;提升客户满意度和企业竞争力。当前&#xff0c;客…

作者头像 李华
网站建设 2026/4/16 11:08:02

深度解析Ooder架构:A2UI时代全栈设计的四大核心思考

深度解析Ooder架构&#xff1a;A2UI时代全栈设计的四大核心思考 在大模型席卷企业级开发的当下&#xff0c;AI to UI&#xff08;A2UI&#xff09;已从概念落地为实际生产力&#xff0c;成为前端开发演进的核心方向之一。而专为大模型流式处理设计的Ooder全栈架构&#xff0c;…

作者头像 李华
网站建设 2026/4/15 13:13:43

PaddlePaddle镜像中的Batch Normalization移动平均参数调整

PaddlePaddle镜像中的Batch Normalization移动平均参数调整 在实际的深度学习项目中&#xff0c;我们常常会遇到这样一个问题&#xff1a;模型在训练时表现良好&#xff0c;但一旦进入推理阶段&#xff0c;输出却变得不稳定甚至严重偏离预期。尤其在使用PaddlePaddle部署OCR、目…

作者头像 李华
网站建设 2026/4/15 13:10:37

ViGEmBus虚拟手柄驱动:彻底解决Windows游戏控制器兼容性问题

ViGEmBus虚拟手柄驱动&#xff1a;彻底解决Windows游戏控制器兼容性问题 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 你是否曾经遇到过这样的情况&#x…

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

树莓派4b安装系统并部署Apache服务器的操作指南

手把手教你用树莓派4B搭建本地Web服务器&#xff1a;从刷系统到Apache部署 你有没有想过&#xff0c;花几百块钱买一块小卡片电脑&#xff0c;就能把它变成一个随时可访问的网站服务器&#xff1f;这听起来像科幻&#xff0c;但在今天&#xff0c;它已经是每个创客、学生甚至工…

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

IDEA插件开发实践:Thief-Book阅读器技术解析与实现

IDEA插件开发实践&#xff1a;Thief-Book阅读器技术解析与实现 【免费下载链接】thief-book-idea IDEA插件版上班摸鱼看书神器 项目地址: https://gitcode.com/gh_mirrors/th/thief-book-idea 在当今快节奏的软件开发环境中&#xff0c;如何有效利用碎片化时间进行知识积…

作者头像 李华