news 2026/4/16 14:39:04

树莓派4b实现空气质量检测仪超详细版

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
树莓派4b实现空气质量检测仪超详细版

用树莓派4B打造一台真正的空气质量检测仪:从零开始的完整实战


当你的家需要“呼吸健康”的眼睛

你有没有过这样的经历?早上醒来喉咙干痒,打开空气净化器发现PM2.5读数飙到150以上——可市面上那些动辄几百上千的商用检测仪,要么数据不准,要么功能死板,还不知道把隐私传到了哪个云端。

其实,我们完全可以自己动手做一个更聪明、更透明、还能联网可视化的空气监测站。而这一切,只需要一块树莓派4B和几十元的传感器模块。

这不是一个玩具项目,而是一套真正能用在家庭、教室甚至小型办公区的环境监控系统。它不仅能实时告诉你“现在空气质量怎么样”,还能记录趋势、触发报警、生成图表,甚至为未来接入智能家居打下基础。

今天,我就带你一步步实现这个系统,不跳坑、不省略、代码全给透,让你不仅能做出来,更能搞懂每一个环节背后的逻辑。


为什么选SDS011?因为它真的准

说到测PM2.5,很多人第一反应是买个红外传感器比如GP2Y1010AU0F。便宜是便宜(十几块钱),但说实话,它的精度只适合做个“大概看看”级别的演示

真正靠谱的选择是激光散射原理的数字传感器——比如Nova Fitness 出品的 SDS011

这颗传感器虽然外形朴素,但它内部有一束650nm的激光二极管,配合风扇强制抽气采样。当空气中颗粒物穿过光路时,会产生特定角度的散射光,光电探测器捕捉后通过算法反演出PM2.5和PM10的质量浓度(单位:μg/m³)。

它强在哪?

参数指标
测量范围0~9999 μg/m³(连重度雾霾都能扛)
分辨率1 μg/m³(比很多商用设备还细)
输出频率约每秒一次
接口类型UART串口(TTL电平,9600bps)
工作电压5V ±0.1V,电流约100mA

最关键的是:它输出的是标准串行数据包,结构清晰、校验完整,非常适合嵌入式系统对接。

⚠️ 注意:SDS011使用的是5V供电和信号电平,不能直接连树莓派GPIO!必须通过USB-TTL转接模块(如CH340G或CP2102)连接到电脑或树莓派的USB口。


如何读取SDS011的数据?别被协议吓住

网上有些教程说“串口通信很复杂”,其实只要你理解了它的数据帧格式,几行Python就能搞定。

SDS011每次发送10字节的数据包,结构如下:

[0xAA][0xC0][PM2.5低字节][PM2.5高字节][PM10低字节][PM10高字节][保留][校验和][0xAB]

其中:
- PM2.5 = (byte3 + byte4×256) / 10 → 单位 μg/m³
- 校验和 = (byte2~byte7之和) & 0xFF,用于验证传输是否出错

下面是经过实战打磨的稳定读取代码:

import serial import time class SDS011: def __init__(self, port="/dev/ttyUSB0", baudrate=9600): self.ser = serial.Serial(port, baudrate, timeout=2) def read(self): while True: # 寻找数据包头 if self.ser.read() == b'\xaa': if self.ser.read() == b'\xc0': frame = self.ser.read(8) # 读后续8字节 if len(frame) == 8: checksum = sum(frame[:6]) & 0xFF if checksum == frame[6]: # 第7字节是校验和 pm25 = (frame[0] + frame[1] * 256) / 10.0 pm10 = (frame[2] + frame[3] * 256) / 10.0 return pm25, pm10 return None, None def close(self): self.ser.close()

💡经验提示
- 如果程序一直卡住没数据,先检查/dev/ttyUSB0是否存在(插拔传感器试试)
- 可以用ls /dev/tty*查看当前可用串口设备
- 建议加个异常处理和重试机制,避免单次错误导致整个采集崩溃


温湿度怎么测?DHT22虽老但够用

接下来是温湿度部分。虽然现在有SHT30、BME280这些I²C高端传感器,但对于初学者来说,DHT22依然是性价比最高的选择

它长这样:一个白色的小方块,三个引脚(VCC、DATA、GND),单价不到10元。

它的工作方式有点“原始”

DHT22用的是单总线协议,主机要主动拉低GPIO至少1ms来唤醒它,然后它才会吐出40位数据。每一位用脉冲宽度表示“0”或“1”:
- 26~28μs 宽度 → “0”
- 70μs 左右宽度 → “1”

听起来挺麻烦?幸好已经有现成库帮我们封装好了底层时序。

推荐使用官方维护的Adafruit_Python_DHT库:

sudo pip3 install Adafruit_DHT

使用非常简单:

import Adafruit_DHT SENSOR = Adafruit_DHT.DHT22 PIN = 4 # GPIO4(物理引脚7) def get_temp_humi(): humidity, temperature = Adafruit_DHT.read_retry(SENSOR, PIN) if humidity is not None and temperature is not None: print(f"温度: {temperature:.1f}°C, 湿度: {humidity:.1f}%") return temperature, humidity else: print("❌ 读取失败,请检查接线或电源") return None, None

🔧接线要点
- VCC 接 3.3V 或 5V(都可以)
- GND 接地
- DATA 接 GPIO4,并外接一个4.7kΩ 上拉电阻到3.3V(否则信号容易失真)

注意采样间隔:DHT22两次读取之间至少要等2秒,太频繁会自发热影响精度。


树莓派4B怎么整合这两个传感器?

现在硬件都清楚了,关键是:怎么让它们在同一台树莓派上稳定运行?

系统架构其实很清晰:

SDS011 → USB-TTL模块 → 插入树莓派USB口 → /dev/ttyUSB0 DHT22 → 连接到 GPIO4 引脚 ↓ Python主程序 ↓ 数据汇总 + 存储 ↓ Flask服务器提供API ↓ 浏览器查看实时曲线

但实际开发中会有几个经典“坑”,我们必须提前绕开。


第一个大坑:串口被系统占用了!

刚接触树莓派的朋友常遇到这个问题:明明插上了USB转TTL模块,Python却读不到任何数据。

原因很简单:树莓派默认开启了串口登录终端(serial console),把/dev/ttyAMA0/dev/serial0拿去当shell用了,导致你无法正常访问串口设备。

✅ 正确解决方法:

运行:

sudo raspi-config

进入菜单:

Interface Options → Serial Port

然后两个问题依次回答:
1. “Would you like a login shell accessible over serial?” →No
2. “Would you like the serial port hardware to be enabled?” →Yes

重启之后,你的USB-TTL设备就会出现在/dev/ttyUSB0,可以自由读写了。

📌 小技巧:如果你以后还想用其他串口设备(比如GPS模块、LoRa模块),这一步都是必做的。


第二个挑战:多传感器如何协同工作?

SDS011每秒出一次数据,DHT22每2秒才能读一次。如果都在主线程里跑,很容易互相阻塞。

更好的做法是:用多线程解耦采集任务

我们可以创建两个独立线程,分别负责PM2.5和温湿度的采集,再通过一个队列把数据统一交给主程序处理。

import threading import queue import time data_queue = queue.Queue() def collect_pm25(): sensor = SDS011() while True: pm25, pm10 = sensor.read() if pm25 is not None: data_queue.put({ 'type': 'pm', 'pm25': pm25, 'pm10': pm10, 'timestamp': time.time() }) time.sleep(1) def collect_th(): while True: temp, humi = get_temp_humi() if temp is not None: data_queue.put({ 'type': 'th', 'temp': temp, 'humi': humi, 'timestamp': time.time() }) time.sleep(2) # 遵守DHT22最小间隔 # 启动后台采集线程 threading.Thread(target=collect_pm25, daemon=True).start() threading.Thread(target=collect_th, daemon=True).start()

这样一来,两个传感器互不影响,也不会因为某个读取慢而拖累整体性能。


数据存哪?本地文件就够用了

对于这种小规模监测系统,不需要上MySQL或者MongoDB。用CSV或者SQLite就足够轻量又高效。

这里我推荐用SQLite,因为它是文件型数据库,无需额外服务,支持结构化查询,后期导出分析也方便。

建表语句如下:

import sqlite3 conn = sqlite3.connect('air_quality.db', check_same_thread=False) c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS readings ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp REAL, pm25 REAL, pm10 REAL, temperature REAL, humidity REAL )''') conn.commit()

每当从队列拿到新数据,就合并写入数据库:

latest = {'pm25': None, 'pm10': None, 'temp': None, 'humi': None} while True: item = data_queue.get() if item['type'] == 'pm': latest['pm25'] = item['pm25'] latest['pm10'] = item['pm10'] elif item['type'] == 'th': latest['temp'] = item['temp'] latest['humi'] = item['humi'] # 当两项都有有效数据时才写入 if latest['pm25'] is not None and latest['temp'] is not None: c.execute("INSERT INTO readings (timestamp, pm25, pm10, temperature, humidity) VALUES (?, ?, ?, ?, ?)", (item['timestamp'], latest['pm25'], latest['pm10'], latest['temp'], latest['humi'])) conn.commit() print(f"📊 已保存数据: PM2.5={latest['pm25']} μg/m³, T={latest['temp']}°C")

让数据“活”起来:网页可视化

光有数据还不够,我们要让它看得见。

最简单的方案是用Flask + Chart.js搭一个微型Web服务器,在手机或电脑浏览器里实时看曲线。

安装Flask:

pip3 install flask

启动一个HTTP服务:

from flask import Flask, jsonify, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') # 前端页面 @app.route('/data') def get_latest(): c.execute("SELECT * FROM readings ORDER BY id DESC LIMIT 1") row = c.fetchone() if row: return jsonify({ 'time': time.strftime('%H:%M:%S', time.localtime(row[1])), 'pm25': row[2], 'pm10': row[3], 'temp': row[4], 'humi': row[5] }) return jsonify({'error': 'no data'})

前端HTML+JavaScript用Chart.js画动态折线图:

<canvas id="chart"></canvas> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> const ctx = document.getElementById('chart').getContext('2d'); const chart = new Chart(ctx, { type: 'line', data: { labels: [], datasets: [ { label: 'PM2.5 (μg/m³)', borderColor: 'red', tension: 0.1, data: [] }, { label: '温度 (°C)', borderColor: 'blue', tension: 0.1, data: [] } ] }, options: { responsive: true } }); // 每2秒请求一次最新数据 setInterval(() => { fetch('/data').then(r => r.json()).then(data => { chart.data.labels.push(new Date().toLocaleTimeString()); chart.data.datasets[0].data.push(data.pm25); chart.data.datasets[1].data.push(data.temp); // 只保留最近50个点 if (chart.data.labels.length > 50) { chart.data.labels.shift(); chart.data.datasets.forEach(ds => ds.data.shift()); } chart.update(); }); }, 2000); </script>

打开浏览器访问http://树莓派IP地址:5000,你会看到一条不断延伸的曲线,像心跳一样跳动着反映你房间的空气质量变化。


实际应用场景不止于“看看”

你以为这只是个玩具?其实它可以做得更多。

✅ 家庭场景

放在卧室,设定规则:当PM2.5 > 75时自动亮起红色LED灯提醒开净化器

✅ 教室/办公室

部署多台设备,结合WiFi信号强度估算位置,生成室内空气质量热力图。

✅ 教学实验

电子信息类专业的学生可以通过这个项目掌握:
- 传感器原理
- 单总线与UART通信
- 多线程编程
- 数据库操作
- Web前后端交互
一套下来,就是完整的物联网工程实践。

✅ 移动监测

装上电池和GPS模块,绑在自行车上骑行一圈,回来就能绘制出城市不同路段的污染分布图。


经验总结:这些细节决定成败

做完这套系统后,我总结了几条关键经验,帮你少走弯路:

问题解决方案
供电不稳定导致传感器重启使用5V/3A电源适配器,避免用手机充电头
DHT22读数经常失败检查是否有4.7kΩ上拉电阻,GPIO接触是否良好
图表刷新卡顿限制前端显示数据点数量(建议≤50)
树莓派发热严重加装散热片或小风扇,尤其是长时间运行时
时间不准确开启NTP同步:sudo timedatectl set-ntp true
SD卡容易损坏定期备份数据库,避免频繁写入日志

还能怎么升级?给你几个方向

这个项目不是终点,而是起点。你可以继续扩展:

  • 🔹加上OLED屏幕:用SSD1306显示本地数值,断网也能看
  • 🔹集成MQTT协议:把数据发到Home Assistant,联动空调、新风系统
  • 🔹加入声音报警:蜂鸣器在超标时发出提示音
  • 🔹低功耗模式:配合RTC模块定时唤醒,延长电池续航
  • 🔹AI预测模型:用历史数据训练简单回归模型,预测未来半小时趋势

甚至可以把多个节点组成LoRa无线网络,实现几百米范围内的分布式监测。


写在最后:技术的意义在于改变生活

做这样一个空气质量检测仪,成本不过百元,耗时不过几天,但它带来的价值远超金钱。

它让你第一次真正“看见”了空气的质量;
它教会你如何把传感器、代码、网络连成一个完整的系统;
它可能促使你养成开窗通风的习惯,也可能推动家人购买一台更好的净化器。

更重要的是,你不再是一个被动接受信息的用户,而是一个能动手解决问题的创造者

如果你正在寻找一个既能练手又有实际用途的树莓派项目,那么这个空气质量检测仪,绝对值得你花一个周末去完成。

如果你在搭建过程中遇到了问题,欢迎留言交流。我已经把完整的代码整理好放在GitHub上,也可以私信获取。

毕竟,呼吸这件事,不该靠猜。

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

5分钟掌握城市道路可视化:开启城市探索的全新视角

5分钟掌握城市道路可视化&#xff1a;开启城市探索的全新视角 【免费下载链接】city-roads Visualization of all roads within any city 项目地址: https://gitcode.com/gh_mirrors/ci/city-roads 还在为复杂的地图信息而头疼吗&#xff1f;city-roads城市道路可视化工…

作者头像 李华
网站建设 2026/4/16 8:43:05

微pe官网分区工具为IndexTTS2预留专用存储空间

微PE官网分区工具为IndexTTS2预留专用存储空间 在AI语音技术加速落地的今天&#xff0c;越来越多开发者尝试将高拟真语音合成系统部署到本地环境。然而&#xff0c;当面对像 IndexTTS2 这类基于深度学习的大模型时&#xff0c;很多人会遇到一个看似“低级”却极为致命的问题&am…

作者头像 李华
网站建设 2026/4/15 22:47:59

GLM-Edge-V-5B:边缘设备也能玩转AI图文理解吗?

GLM-Edge-V-5B&#xff1a;边缘设备也能玩转AI图文理解吗&#xff1f; 【免费下载链接】glm-edge-v-5b 项目地址: https://ai.gitcode.com/zai-org/glm-edge-v-5b 导语&#xff1a;THUDM推出全新轻量级多模态模型GLM-Edge-V-5B&#xff0c;将50亿参数的图文理解能力带到…

作者头像 李华
网站建设 2026/4/16 8:46:37

Intel平台eSPI中断机制详解:系统学习

深入理解Intel平台eSPI中断机制&#xff1a;从协议到实战的完整指南在现代PC与嵌入式系统设计中&#xff0c;接口的演进往往决定了系统的能效比、集成度和可靠性。随着LPC&#xff08;Low Pin Count&#xff09;总线逐渐退出历史舞台&#xff0c;eSPI&#xff08;Enhanced Seri…

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

ASMR下载终极指南:3步轻松获取海量音频资源

ASMR下载终极指南&#xff1a;3步轻松获取海量音频资源 【免费下载链接】asmr-downloader A tool for download asmr media from asmr.one(Thanks for the asmr.one) 项目地址: https://gitcode.com/gh_mirrors/as/asmr-downloader 还在为寻找高品质ASMR音频而烦恼吗&am…

作者头像 李华
网站建设 2026/4/16 9:04:59

Qwen3-4B新升级:256K上下文+69.6分MMLU-Pro的AI助手

Qwen3-4B新升级&#xff1a;256K上下文69.6分MMLU-Pro的AI助手 【免费下载链接】Qwen3-4B-Instruct-2507-GGUF 项目地址: https://ai.gitcode.com/hf_mirrors/unsloth/Qwen3-4B-Instruct-2507-GGUF 导语&#xff1a;阿里云旗下通义千问团队推出Qwen3-4B-Instruct-2507模…

作者头像 李华