MQ135是一个比较便宜的空气质量传感器,可以用在家庭以及工业场所中。树莓派是一个小巧但很强大的卡片电脑,基于Linux,同时提供了很多硬件接口,方便开发出各种电子产品。Golang是一款简单高效的语言,编译结果为native代码,无需提前安装运行环境和虚拟机。

关于MQ135需要提前说明几点:

1、自身无法确定污染气体种类。最开始想用MQ135获取空气中各种有害气体的浓度,比如甲苯、CO、酒精等,搞了几天发现这个行不通,虽然可以判断空气质量好坏,但是并不能确定是何种气体导致的空气污染。因为MQ135在多种有害气体浓度升高的时候都会增加气敏材料的导电率,并不能区分出是哪种气体导致的。但是如果在某些特殊的环境中,污染物只可能是某种气体时,倒是可以准确的检测。

2、气体浓度检测范围是10-1000ppm。国际标准将室内苯浓度限定为0.087mg/m3,换算成ppm就更小了,不知道在小于10ppm的环境中实际表现如何。对于想检测室内苯系物是不是超标,这个就很难判断,除非超过了10ppm,那就是很严重的污染了。

3、使用前需要先校准。MQ135的数据表中给出了各种气体不同浓度对应的传感器电阻相对Ro的比值,Ro是氨气在100ppm、20°C 、 65%相对湿度下的传感器电阻值,但是说明书中没有给出这个值是多少,不过可以根据指定的气体浓度值及对应的电阻值进行计算,这就得有个标准的实验环境。同时根据说明书预热时间需要48小时,所以使用这个传感器应该是一直开着,偶尔可以短暂关机或重启。

4、测量精度问题。这里说的是带PCB板的MQ135,板子上自带一个负载电阻,但是阻值只有1KΩ或者2KΩ,所以测出的电压会比较小,精度可能不够,对于CO2这种空气中浓度比较高的气体,值会在比较大的范围跳动。这个带板子的MQ135的说明书实际没有明确说明可以检测CO2,但是说明书的图表中有一条曲线实际就是CO2的,而且有些资料中提到是可以检测的,只不过要把负载电阻搞的很大精度才够。


下边就开始介绍实验步骤了。

1、硬件准备

  • 树莓派3B+(需要能提供5V电压;已安装好操作系统,能ssh连接)
  • MQ135(PCB板自带负载电阻,输出电压的模拟信号)
  • MCP3008(将MCP3008的模拟信号转换为数字信号)
  • DHT11(温湿度传感器,MQ135会受到温度和湿度的影响)
  • 面包板(安置DHT11、MCP3008、DHT11)
  • 杜邦线若干(母对母头、公对公头、公对母头都需要)

有些文章中还使用了电平转换器件,将MQ135产生的5V电平信号转换为3.3V电平信号,可能是因为他们的树莓派不能读取5V信号,这个在3B+上经过实测5V信号也没有问题,所以我认为不是必要的,当然加上它也没问题,计算的时候输入电压按照3.3V就可以了。这里不使用它的另一个原因,安装在面包板上时排针与它经常接触不良,可能需要焊接下,比较麻烦,索性就不用了。

2、硬件连线

这里仅表示连线关系,实际走线可以酌情处理,比如Ground有很多阵脚可以提供,5V针脚也有两个。

3、开启SPI

SPI是串行外设接口,因为读取MCP3008的数据需要使用SPI协议,但是树莓派默认并没有开启它,所以需要手动开启SPI。执行命令:

sudo raspi-config

然后选择P4 SPI。

重启树莓派,以使SPI生效。

4、编程读数据

这里专门编写了一个模块,以方便读取MQ135和DHT11的数据,所以先安装这个模块。

go get github.com/bosima/go-pidriver

然后导入这个模块。

import "https://github.com/bosima/go-pidriver"

因为涉及的内容比较多,这里分步介绍:

(1)初始化树莓派针脚映射。

drivers.OpenRPi()

(2)初始化DHT11,以及采集当前温度的方法。

	dht11, err := drivers.NewDHT11(4)
if err != nil {
fmt.Println(err)
return
}
func readTR(dht11 *drivers.DHT11) (float64, float64, error) {
rh, tmp, err := dht11.ReadData() if err != nil {
return 0.0, 0.0, err
} return rh, tmp, nil
}

(3)初始化MCP3008。最后1个参数代表参考电压为5V。MCP3008实际有三个电压的参数:工作电压、参考电压、模拟信号电压,参考电压和模拟信号电压都不能超过工作电压,参考电压是用于模拟信号转换为数字信号的比较值,所以一般参考电压也不应该低于模拟信号电压,工作电压和参考电压一般使用相同的值,这里都使用的5V。

	mcp, err := drivers.NewMCP3008(0, 0, 5.0)
if err != nil {
fmt.Println(err)
return
}

(4)初始化MQ135。

mq135 := drivers.NewMQ135(mcp, 5.0, "CO2", 10, 2.0)
  • vcc是工作电压,这里统一了加热电压和回路电压,按照说明书加热电压为5.0V±0.2V,回路电压为≤24V,这里统一为5V。
  • gas要测量的气体,支持测量二氧化碳、一氧化碳、氨气、酒精、甲苯、丙酮。因为要计算基准参考电阻,必须有一个实验环境,因为大气中二氧化碳的浓度比较容易获取,所以这里用了二氧化碳。
  • ro是基准参考电阻值,表示在含100ppm氨气、20℃/65%RH下的传感器电阻值,这里因为没有标准实验环境,所以先随便写一个10,后边校准的步骤中会计算这个值。
  • rl是负载电阻的阻值。这个要看PCB上焊接的电阻,我这里上边写的是202,代表2KΩ,有的可能写的102,代表1KΩ。下图红框中的电阻即为负载电阻。

(5)校准Ro。每隔2秒钟采集下温湿度,然后再传入CO2的浓度,大气中CO2的浓度可以使用这个常量值,但是由于碳排放问题,基本每年都在增高的,可以通过这个网站获取:https://www.co2.earth/。因为MQ135需要较长时间的预热,所以校准前需要提前预热好,校准时保持稳定的气体环境,校准次数可以根据实际情况调整。

	ro := 0.0
sampleTimes := 60
for i := 0; i < sampleTimes; i++ {
// use realtime temperature and humidity
for {
rh, tmp, err = readTR(dht11)
if err == nil {
break
}
time.Sleep(time.Second * 2)
} // Gas concentration in natural environment:
// CO2 414ppm
// unit transfer: {y}ppm = 24.5 * {x}mg/m^3 /{M}
ro += mq135.MeasureRo(tmp, rh, 414.0)
time.Sleep(time.Second * 2)
}
mq135.Ro = ro / float64(sampleTimes)
fmt.Printf("ro: %f \n", mq135.Ro)

(6)测试气体浓度。这里写了一个死循环,每隔2秒钟测量1次二氧化碳浓度。

for {
rh, tmp, err := readTR(dht11)
if err != nil {
time.Sleep(time.Second * 2)
continue
} concentration, err := mq135.MeasureGasConcentration(tmp, rh)
if err != nil {
fmt.Println(err)
continue
} fmt.Printf("\rtmp: %.2f, rh: %.2f, concentration: %f", tmp, rh, concentration)
os.Stdout.Sync() time.Sleep(time.Millisecond * 2000)
}

看一下实际输出结果:

面对MQ135呼吸,会看到CO2气体浓度值快速上升,从MQ135挪开一会,会看到浓度值又降回原来的水平。

5、几个关键计算

(1)传感器电阻

MQ135输出的是电压信号,那么根据电压信号怎么得到传感器的电阻值。下边是MQ135的简化电路图,VC是输入电压,RS是传感器实际电阻,VRL是输出电压,RL是负载电阻,问题可以这样描述:已知VC、VRL和RL,求RS的值。

根据欧姆定律,可以得出:RS=(VC/VRL-1)*RL

另外需要考虑温湿度对电阻值的影响,下图是100ppm氨气在不同温湿度条件下的Rs/Ro值的曲线。从这个图表中的数据可以拟合温湿度的多项式:z=p00 + p10*x + p01*y + p20*x^2 + p11*x*y,x代表温度,y代表湿度,p00、p10、p01、p20、p11都是一些常数,具体值请查看Github源代码。

因此最终计算RS时还需要做一下校正:RS=RS/z

(2)模拟信号转数字信号

MCP3008采用逐次逼近的算法。首先会取工作电压的1/2,这里就是2.5V,然后通过内置的DAC转换为模拟电压与输入信号进行比较,如果2.5V大于输入电压则最高位为0,否则为1;然后取0*2.5+5*1/4与输入电压进行比较,如果大于则次高位为0,否则为1;然后再取0*2.5+5*1/4+ 5*1/8与输入信号进行比较,如果大于则第三位为0,否则为1;如此依次比较取得最终10位数值,即0-1023之间的数字。

由逐次逼近算法可知,电压被分成了1024份,所以得到的数字信号转化为电压时:V={DAC}*(5/1024)

(3)MQ135 Ro计算

根据MQ135的数据图表可以拟合气体浓度与电阻比值之间的公式为:Rs/Ro=ax^b,这是一个幂函数,对于某种特定的气体,其中a、b为常数,x为气体浓度,Rs前边已经有方法可以计算出来,因此只要得到x就可以得到Ro的值。

R0 = RS * (x/ A)-1/B ,其中A=(1 / a)1/b ,B=1/b。

这里因为没有标准的实验环境,所以取个巧,使用大气中的二氧化碳浓度标准值作为清洁空气中的二氧化碳浓度值,这个虽然和当前测试环境不一定匹配,但是只能凑合用用了。另外因为这里用的MQ135板载负载电阻只有2千欧,所以对CO2实际的测量精度也会有比较大的影响。

(4)气体浓度计算

有了Ro,反过来就可以根据Rs计算气体浓度了:c = A * (RS / R0)B,A=(1 / a)1/b ,B=1/b,a、b气体浓度幂函数之中的常量。


因之前对硬件和传感器的知识了解甚少,仓促之间可能有错误之处,还望指正。

此文所有源代码已经开源到GitHub,欢迎取用:https://github.com/bosima/go-pidriver

此文参考了大量网络资料,特别是这篇文章:https://pslab.io/blog/measuring-co2-with-mq135/

树莓派使用Golang+MQ135检测室内空气质量的更多相关文章

  1. OneNET麒麟座应用开发之十:空气质量数据监测站项目总结

    大气质量数据监测站用于测试空气质量监测及数据采集,实现野外或者室内空气质量的检测. 1.项目概述 本项目是一个定制项目,要求采集大气的压力.温度.湿度.PM25.位置等数据并上传到指定的后台服务器.但 ...

  2. 使用微创联合M5S空气检测仪、树莓派3b+、prometheus、grafana实现空气质量持续监控告警WEB可视化

    1.简介 使用微创联合M5S空气检测仪.树莓派3b+.prometheus.grafana实现空气质量持续监控告警WEB可视化 grafana dashboard效果: 2.背景 2.1 需求: 1. ...

  3. DIY 空气质量检测表

    DIY 空气质量检测表 前几天逛淘宝看到有空气颗粒物浓度测量的传感器,直接是 3.3V TTL 电压串口输出的,也不贵,也就 100 多一点.觉得挺好就买了个,这两天自己捣鼓了个小程序,搞了个软件界面 ...

  4. scrapy结合selenium抓取武汉市环保局空气质量日报

    1.前言 目标网站:武汉市环境保护局(http://hbj.wuhan.gov.cn/viewAirDarlyForestWaterInfo.jspx).scrapy对接selenium模块抓取空气质 ...

  5. 空气质量管理系统+SSM(Spring+SpringMVC+Mybatis)+前后端分离总结

    作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 点我进SSM演示地址 1.目录结构: 2.需要注意的地方 2.1在WEB-INFO下新建 2.1.1 springMVC-servlet.xml & ...

  6. 空气质量管理系统ssm(mybatis+spring+springMVC)框架+前后端分离

    1.目录结构: 2.需要注意的地方 2.1在WEB-INFO下新建 2.1.1 springMVC-servlet.xml <?xml version="1.0" encod ...

  7. 用python+selenium获取北上广深成五地PM2.5数据信息并按空气质量排序

    从http://www.pm25.com/shenzhen.html抓取北京,深圳,上海,广州,成都的pm2.5指数,并按照空气质量从优到差排序,保存在txt文档里 代码如下: #coding=utf ...

  8. 使用 Cloud Insight SDK 监控北京空气质量!

    现在越来越多的 App 都开始有广告了.特别是空气质量监测,和天气类的 App,广告还是蛮多的,眼花缭乱,真是够了. 最近刚好在用一款系统监控工具 Cloud Insight,它提供的 SDK 可以把 ...

  9. 天气类API调用的代码示例合集:全国天气预报、实时空气质量数据查询、PM2.5空气质量指数等

    以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 全国天气预报:数据来自国家气象局,可根据地名.经纬度GPS.IP查 ...

  10. 全国城市空气质量实时数据(PM2.5)实时下载

    国家公布了“http://113.108.142.147:20035/emcpublish/”空气质量实时发布平台,WCF服务地址为“http://113.108.142.147:20035/EnvP ...

随机推荐

  1. Linux:管道命令与文本处理三剑客(grep、sed、awk)

    1 管道命令(pipe)介绍 众所周知,bash命令执行的时候会输出信息,但有时这些信息必须要经过几次处理之后才能得到我们想要的格式,此时应该如何处置?这就牵涉到 管道命令(pipe) 了.管道命令使 ...

  2. 5221. 【GDOI2018模拟7.10】A

    题目大意: 给你一棵有根树,问你在这棵树上总共有多少棵子树的节点构成了一个完整的整数区间. 考试想法: 考试时就想到了正解,正解就是从下到上遍历整一棵树,每一个节点记录一下它的最小值min.最大值ma ...

  3. 【Visual Leak Detector】源码编译 VLD 库

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记.本篇介绍 VLD 源码的编译.同系列文章目录可见 <内存泄漏检测工具>目录 目录 说明 1. VLD 库的依赖文件 2. 源码 ...

  4. JS 实现关键字文本搜索 高亮显示

    示例:  利用字符串的 split 方法,通过搜索的关键字分割成数组  在利用数组的 join 方法拼接成字符串 我是利用mock的省份 1 <template> 2 <div cl ...

  5. java线程的创建

    文章目录 前言 进程 线程 使用线程 继承Thread 线程随机性 .start()的顺序不代表.run()的顺序 实现Runnable 实例共享造成的非线程安全问题 线程常用方法: 判断线程是否为停 ...

  6. Prism Sample 24-NavigationJournal

    本例是在上一案例中导航参数的基础上增加了导航的历史记录功能,就是向前向后的功能. 导航本身很简单,以下代码就实现了: public void OnNavigatedTo(NavigationConte ...

  7. Redis数据结构二之SDS和双向链表

    本文首发于公众号:Hunter后端 原文链接:Redis数据结构二之SDS和双向链表 这一篇笔记介绍一下 SDS(simple dynamic string)和双向链表. 以下是本篇笔记目录: SDS ...

  8. Matplotlib.pyplot.plot 绘图

    Matplotlib.pyplot 创建图形.在图形中创建创建一个绘图区域.在绘图区域中你那个绘制一些线.在图形中添加标签之类 画二维平面图 x = np.arange(0, 10, 2) y1 = ...

  9. < Python全景系列-4 > 史上最全文件类型读写库大盘点!什么?还包括音频、视频?

    欢迎来到我们的系列博客<Python全景系列>!在这个系列中,我们将带领你从Python的基础知识开始,一步步深入到高级话题,帮助你掌握这门强大而灵活的编程语言! 本文系列第四篇,介绍史上 ...

  10. ET介绍—— 一切皆实体的设计

    一切皆实体 目前十分流行ECS设计,主要是守望先锋的成功,引爆了这种技术.守望先锋采用了状态帧这种网络技术,客户端会进行预测,预测不准需要进行回滚,由于组件式的设计,回滚可以只回滚某些组件即可.ECS ...