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 rsyslogd服务学习

    本篇笔记来自该博客: http://c.biancheng.net/view/1097.html 服务简介 在CentOS 6.x 中日志服务已经由 rsyslogd 取代了原先的 syslogd.r ...

  2. Python-psycopg2的简单使用

    一.简介 psycopg2 库是 python 用来操作 postgreSQL 数据库的第三方库. 二.安装 1.执行如下命令安装 pip3 install psycopg2 2.使用Pycharm安 ...

  3. sqlilabs第一关

    首先打开网页,进行注入点的测试 输入?id=1 and 1=1发现1=2的时候没有进行报错,有两种可能,一种是不能注入,第二种是字符型可以通过对字符型里面的''进行闭合,输入'and 1=1--+发现 ...

  4. 如何在 🤗 Space 上托管 Unity 游戏

    你知道吗?Hugging Face Space 可以托管自己开发的 Unity 游戏!惊不惊喜,意不意外?来了解一下吧! Hugging Face Space 是一个能够以简单的方式来构建.托管和分享 ...

  5. Yolov5 根据自己的需要更改 预测框box和蒙版mask的颜色

    1.首先找到项目中 utils/plots.py 文件,打开该代码 将原来的 Colors类注释掉(或删掉),改成如下Colors类 class Colors: def __init__(self): ...

  6. 2023-04-06:拥抱Golang,优化FFmpeg音频编码器,探究encode_audio.c的内部结构。

    2023-04-06:拥抱Golang,优化FFmpeg音频编码器,探究encode_audio.c的内部结构. 答案2023-04-06: 见moonfdd/ffmpeg-go库. 这段代码是一个示 ...

  7. 2022-03-09:我们正在玩一个猜数游戏,游戏规则如下: 我从 1 到 n 之间选择一个数字。 你来猜我选了哪个数字。 如果你猜到正确的数字,就会 赢得游戏 。 如果你猜错了,那么我会告诉你,我选

    2022-03-09:我们正在玩一个猜数游戏,游戏规则如下: 我从 1 到 n 之间选择一个数字. 你来猜我选了哪个数字. 如果你猜到正确的数字,就会 赢得游戏 . 如果你猜错了,那么我会告诉你,我选 ...

  8. sql server 系统表详细说明

    sql server 系统表详细说明 sysaltfiles 主数据库 保存数据库的文件syscharsets 主数据库字符集与排序顺序sysconfigures 主数据库 配置选项 syscurco ...

  9. 【工作随手记】deaklock排查

    生产环境当中还没真正遇到过死锁的问题.有些疑似死锁的问题,后来经过排查也只是其它问题导致的.所以通过jstack到底怎样排查死锁问题有点疏忽了.这里作个记录. 模拟一个死锁 顺便复习一下. 死锁的产生 ...

  10. jq如何将获取到的css属性值变为int类型

    情况 小王:诶诶诶?我用js中css方法获取到的属性值怎么判断错误了呀?怎么办怎么办? Allen:害,小王,你是不是没有注意左右两边的类型,会不会是数据类型不一致导致的? 事故现场: if($(&q ...