空气质量监测是一个关注度较高的主题,其研究领域主要包括污染增长、过敏、健康与健身意识 ,以及技术创新。 消费市场显示,市场上推出的创新性产品提高了人们监测家庭空气质量的意识。 其中有一类产品为智能表。 这类智能表可监测各种与健康相关的参数,以及空气质量。 空气质量数据发送至云系统,应用为您提示空气质量的变化,以便您了解哪 个区域需要通风。 具备空气质量意识有助于改善生活质量。 本文将探讨如何通过使用 Arduino* 生态系统测量二氧化碳、挥发性有机化合物和灰尘的浓度,并将数据发送至云服务提供商来进行空气质量监测。
英特尔® Edison 平台配备了快速处理器、大容量内存,以及面向 WiFi 和蓝牙的集成连接性,非常适合启动新原型,或迁移现有原型。 Arduino 生态系统可提供一系列硬件和固件库, 支持使用英特尔® Edison 计算模块和英特尔® Edison Arduino Breakout 开发板进行试验。
如欲了解更多有关英特尔 Edison 平台的信息,请访问下列链接:
http://www.intel.com/content/www/us/en/do-it- yourself/edison.html
硬件组件:
该项目的空气质量监测系统主要使用下列硬件组:
- 英特尔® Edison 计算模块
- 英特尔® Edison Arduino Breakout 开发板
- 共阴极 RGB LED + 3 个 1kΩ 电阻器
- GP2Y1010AU0F 光学灰尘传感器 + 150Ω 电阻器 + 220 µF 电解质电容器
- MQ-135 气体传感器
- K-30 CO2 传感器
- PIR 运动传感器
图 1 - 硬件连接图
工作原理:
图 1 所示为硬件组件与英特尔® Edison Arduino Breakout 开发板的连接。 该系统将 RGB LED 用作简单的目测指示系统来显示空气质量。
为确定某区域的整体空气质量,该系统使用三个传感器:
1. 光学灰尘传感器:用于测量某区域的灰尘。
2. 气体传感器:用于测量烟雾等挥发性有机化合物。
3. CO2 传感器:借助 I2C 接口测量二氧化碳浓度。
此外, 该系统还配备运动传感器,通过过滤掉由运动引起的暂时性灰尘浓度上升以及由于人们靠近传感器呼吸所引起的暂时性 CO2 浓度上升,以最大程度地真实反映某区域的整体空气质量。
如果未检测到运动,固件将读取空气质量传感器、分析传感器数据、更新目测指示系统,并将空气质量数据发送至云。 有关该系统的详细内容将会在“固件”部分做进一步介绍。
如欲了解有关传感器的更多内容,请点击下列链接查看数据表:
http://www.kosmodrom.com.ua/pdf/MQ135.pdf
https://www.sparkfun.com/datasheets/Sensors/gp2y1010au_e.pdf
http://www.co2meter.com/collections/co2- sensors/products/k-30-co2-sensor-module
http://www.ladyada.net/media/sensors/PIRSensor- V1.2.pdf
配置 I2C 时钟频率:
需注意 的一点是,在撰写本文时,英特尔® Edison 的默认 I2C 时钟频率高于 100kHZ,超过了 K-30 CO2 传感器的规格。 K-30 CO2 传感器所支持的最高 I2C 时钟频率 (SCL) 为 100kHz。 英特尔® Edison I2C 时钟频率可通过下列几个步骤更改为 100kHZ:
- 确保安装了最新的英特尔® Edison Yocto 固件映像:
http://www.intel.com/support/edison/sb/CS- 035180.htm
- 打开 Edison Linux 终端,并以根用户身份登录:
https://software.intel.com/zh-cn/articles/getting-started-with-the-intel-edison-board-on- windows
-cd /sys/devices/pci0000:00/0000:00:09.1/i2c_dw_sysnode
-echo std > mode
-cat mode
如欲了解有关英特尔® Edison 计算模块和 I2C 外设的更多信息,请访问下列链接:
固件:
下列代码显示了空气质量系统包含的组件、宏和函数。 下面将介绍针对初始化、主循环 、读取运动传感器、读取空气质量传感器、分析整体空气质量、更新目测指示 LED,以及将数据发送至云服务提供商的函数。
包含:
#include <Wire.h>
宏:
//Pin Defines #define gasSensorPin A1 #define dustSensorPin A0 #define dustSensorLEDPin 2 #define redRGBLEDPin 3 #define greenRGBLEDPin 4 #define blueRGBLEDPin 5 #define motionSensorPin 6 //Air Quality Defines #define AIR_QUALITY_OPTIMAL 2 #define AIR_QUALITY_GOOD 1 #define AIR_QUALITY_BAD 0 #define AIR_QUALITY_UNKNOWN -1 #define MAX_SENSOR_READINGS 10 #define SENSOR_READING_DELAY 1000 //Motion Sensor Defines #define MOTION_NOT_DETECTED 0 #define MOTION_DETECTED 1 #define MOTION_DELAY_TIME 1000 //Dust Sensor Timing Parameters (from p.5 of datasheet) #define SAMPLE_DELAY 280 //Sampling #define PULSEWIDTH_DELAY 40 //Pw #define PERIOD_DELAY 9680 //T //Gas Sensor Thresholds #define GAS_SENSOR_OPTIMAL 140 #define GAS_SENSOR_GOOD 200 //Dust Sensor Thresholds #define DUST_SENSOR_OPTIMAL 125 #define DUST_SENSOR_GOOD 250 //CO2 Sensor Thresholds #define CO2_SENSOR_OPTIMAL 800 #define CO2_SENSOR_GOOD 2000
函数:
初始化: 该函数可初始化串行调试接口、I/O 针脚和 I2C 接口。
void setup() { Serial.begin(9600); pinMode(gasSensorPin, INPUT); pinMode(dustSensorPin, INPUT); pinMode(dustSensorLEDPin, OUTPUT); pinMode(redRGBLEDPin, OUTPUT); pinMode(greenRGBLEDPin, OUTPUT); pinMode(blueRGBLEDPin, OUTPUT); pinMode(motionSensorPin, INPUT); Wire.begin(); }
主循环: 主循环可初始化系统、检查运动、读取空气质量传感器、分析整体空气质量、更新指示 LED,并将数据发送至云服务。
void loop() { // -- Init int airQuality = 0; int motion = 0; int sensorAirQuality[3] = {0,0,0}; //0-Gas Sensor, 1-CO2 Sensor, 2- DustSensor Serial.println(""); // -- Check for motion motion = readMotionSensor(); if (motion == MOTION_NOT_DETECTED) { // -- Read Air Quality Sensors readAirQualitySensors(sensorAirQuality); // -- Analyze Total Air Quality airQuality = analyzeTotalAirQuality(sensorAirQuality [0],sensorAirQuality[1],sensorAirQuality[2]); // -- Update Indication LED updateIndicationLED(airQuality); // -- Update Air Quality Value for Cloud Datastream updateCloudDatastreamValue(CHANNEL_AIR_QUALITY_ID, airQuality); // -- Send Data To Cloud Service sendToCloudService(); } }
读取运动传感器: 通过取样传感器的数字输出针脚可读取运动传感器。 如果检测到运动,传感器输出针脚将跳变至“高电平”。 该函数尝试过滤故障,并反馈是否检测到运动。
int readMotionSensor() { // -- Init int motionSensorValue = MOTION_NOT_DETECTED; int motion = MOTION_NOT_DETECTED; Serial.println("-Read Motion Sensor"); // -- Read Sensor motionSensorValue = digitalRead(motionSensorPin); // -- Analyze Value if (motionSensorValue == MOTION_DETECTED) { delay(MOTION_DELAY_TIME); motionSensorValue = digitalRead(motionSensorPin); if (motionSensorValue == MOTION_DETECTED) { motion = MOTION_DETECTED; Serial.println("--Motion Detected"); updateIndicationLED(AIR_QUALITY_UNKNOWN); } } return motion; }
读取空气质量传感器: 该函数调用单独的气体、co2 和灰尘传感器函数。 函数将指针带入整数数组,以保存各传感器的空气质量结果。
void readAirQualitySensors(int* sensorAirQuality) { Serial.println("-Read Air Quality Sensors"); sensorAirQuality[0] = readGasSensor(); sensorAirQuality[1] = readCO2Sensor(); sensorAirQuality[2] = readDustSensor(); }
读取气体传感器: 气体传感器可检测 NH3、NOx、乙醇、 苯,烟雾等气体。 气体传感器包含一个模拟电压输出,该输出与空气中的气体浓度成正比。 执行 A/D 换算可读取该传感器。 该函数可读取传感器、求取读数的平均值、分析传感器数据,并返回该传感器的空气质量。
int readGasSensor() { // -- Init int airQuality = 0; int gasSensorValue = 0; // -- Read Sensor for (int i=0; i < MAX_SENSOR_READINGS; i++) { gasSensorValue += analogRead(gasSensorPin); delay(SENSOR_READING_DELAY); } gasSensorValue /= MAX_SENSOR_READINGS; //Average the sensor readings // -- Update Cloud Datastream Serial.print("--gasSensorValue = "); Serial.println(gasSensorValue); updateCloudDatastreamValue(CHANNEL_GAS_SENSOR_ID, gasSensorValue); // -- Analyze Value if (gasSensorValue < GAS_SENSOR_OPTIMAL) { airQuality = AIR_QUALITY_OPTIMAL; } else if (gasSensorValue < GAS_SENSOR_GOOD) { airQuality = AIR_QUALITY_GOOD; } else { airQuality = AIR_QUALITY_BAD; } return airQuality; }
读取灰尘传感器: 灰尘传感器包含光学传感系统,该系统借助数字输出针脚通电。 通电后执行 A/D 换算可对传感器的模拟电压输出(与空气中的 灰尘成正比)进行取样。 该函数可读取传感器、求取读数的平均值、分析传感器数据, 并返回该传感器的空气质量。
int readDustSensor() { // -- Init int airQuality = 0; int dustSensorValue = 0; // -- Read Sensor for (int i=0; i < MAX_SENSOR_READINGS; i++) { digitalWrite(dustSensorLEDPin,LOW); //Enable LED delayMicroseconds(SAMPLE_DELAY); dustSensorValue += analogRead(dustSensorPin); delayMicroseconds(PULSEWIDTH_DELAY); digitalWrite(dustSensorLEDPin,HIGH); //Disable LED delayMicroseconds(PERIOD_DELAY); delay(SENSOR_READING_DELAY); } dustSensorValue /= MAX_SENSOR_READINGS; //Average the sensor readings // -- Update Cloud Datastream Serial.print("--dustSensorValue = "); Serial.println(dustSensorValue); updateCloudDatastreamValue(CHANNEL_DUST_SENSOR_ID, dustSensorValue); // -- Analyze Value if (dustSensorValue < DUST_SENSOR_OPTIMAL) { airQuality = AIR_QUALITY_OPTIMAL; } else if (dustSensorValue < DUST_SENSOR_GOOD) { airQuality = AIR_QUALITY_GOOD; } else { airQuality = AIR_QUALITY_BAD; } return airQuality; }
读取 CO2 传感器: CO2 传感器返回 CO2 浓度值(单位:ppm)。 CO2 传感器通过 I2C 接口读取。 该函数可读取传感器、求取读数的平均值、分析传感器数据,并返回该传感器的空气质量。
int readCO2Sensor() { // -- Init int airQuality = 0; int co2SensorValue = 0; int tempValue=0; int invalidCount=0; // -- Read Sensor for (int i=0; i < MAX_SENSOR_READINGS; i++) { tempValue = readCO2(); // see http://cdn.shopify.com/s/files/1/0019/5952/files/Senseair-Arduino.pdf? 1264294173 for this function (tempValue == 0) ? invalidCount++ : co2SensorValue += tempValue; delay(SENSOR_READING_DELAY); } if (invalidCount != MAX_SENSOR_READINGS) { co2SensorValue /= (MAX_SENSOR_READINGS - invalidCount); //Average the sensor readings } // -- Update Cloud Datastream Serial.print("--co2SensorValue = "); Serial.println(co2SensorValue); updateCloudDatastreamValue(CHANNEL_CO2_SENSOR_ID, co2SensorValue); // -- Analyze Value if (co2SensorValue < CO2_SENSOR_OPTIMAL) { airQuality = AIR_QUALITY_OPTIMAL; } else if (co2SensorValue < CO2_SENSOR_GOOD) { airQuality = AIR_QUALITY_GOOD; } else { airQuality = AIR_QUALITY_BAD; } return airQuality; }
分析整体空气质量: 该函数可通过分析传来的气体、co2 和灰尘等空气质量值确定该地区的整体空气质量。 该函数可返回该地区的整体空气质量水平。
int analyzeTotalAirQuality(int gasAirQuality, int co2AirQuality, int dustAirQuality) { int airQuality = 0; Serial.println("-Analyze Total Air Quality"); if (gasAirQuality==AIR_QUALITY_BAD \ || dustAirQuality==AIR_QUALITY_BAD \ || co2AirQuality==AIR_QUALITY_BAD) { Serial.println("--Air Quality Is BAD"); airQuality = AIR_QUALITY_BAD; } else if (gasAirQuality == AIR_QUALITY_OPTIMAL \ && dustAirQuality == AIR_QUALITY_OPTIMAL \ && co2AirQuality==AIR_QUALITY_OPTIMAL) { Serial.println("--Air Quality Is OPTIMAL"); airQuality = AIR_QUALITY_OPTIMAL; } else { Serial.println("--Air Quality Is Good"); airQuality = AIR_QUALITY_GOOD; } return airQuality; }
更新目测指示 LED: 该函数可将指示 LED 更新至与传来的空气质量值相对应的颜色。 LED 变成蓝色表示空气质量水平达到最佳、绿色表示空气质量良好、红色表示空气质量差。 如果检测到运动,LED 将变成品红色。
void updateIndicationLED(int airQuality) { Serial.println("-Update Indication LED"); // --Turn off all colors digitalWrite(redRGBLEDPin,LOW); digitalWrite(greenRGBLEDPin,LOW); digitalWrite(blueRGBLEDPin,LOW); // --Update Indication LED if (airQuality == AIR_QUALITY_UNKNOWN) { digitalWrite(redRGBLEDPin,HIGH); digitalWrite(greenRGBLEDPin,HIGH); digitalWrite(blueRGBLEDPin,HIGH); } else if (airQuality == AIR_QUALITY_OPTIMAL) { digitalWrite(blueRGBLEDPin, HIGH); } else if (airQuality == AIR_QUALITY_GOOD) { digitalWrite(greenRGBLEDPin, HIGH); } else { digitalWrite(redRGBLEDPin, HIGH); } }
将数据发送至云服务提供商:
如欲将英特尔® Edison 连接至 WiFi 网络,请参考下列链接:
http://www.intel.com/support/edison/sb/CS- 035342.htm
图 2 - xively.com 馈送
在本示例中, xively.com将用作接收空气质量数据的云服务提供商。 图 2 所示为由四条通道组成的示例馈送。 “函数” 部分将对这些通道做进一步介绍。 集成 xively.com要求将 Http Client 和 Xively 库添加至 Arduino IDE。 请点击以下链接,查看关于 xively.com创建账户、Arduino 教程,以及将库集成于 Arduino IDE 的更多信息。
https://xively.com/dev/tutorials/arduino_wi- fi/
下列代码显示了可添加至空气质量系统的组件、宏和函数示例,可因此添加 xively.com支持。
包含:
#include <WiFi.h> #include <HttpClient.h> #include <Xively.h>
宏:
//Xively.com Defines #define XIVELY_FEED <enter your feed number here> #define XIVELY_KEY <enter your key string here> #define XIVELY_HTTP_SUCCESS 200 #define CHANNEL_AIR_QUALITY"AIR_QUALITY" #define CHANNEL_AIR_QUALITY_ID 0 #define CHANNEL_GAS_SENSOR "GAS_SENSOR" #define CHANNEL_GAS_SENSOR_ID 1 #define CHANNEL_CO2_SENSOR "CO2_SENSOR" #define CHANNEL_CO2_SENSOR_ID 2 #define CHANNEL_DUST_SENSOR "DUST_SENSOR" #define CHANNEL_DUST_SENSOR_ID 3 #define MAX_CHANNELS 4
全局变量:
//Xively Datastream XivelyDatastream datastreams[] = { XivelyDatastream(CHANNEL_AIR_QUALITY, strlen (CHANNEL_AIR_QUALITY), DATASTREAM_FLOAT), XivelyDatastream(CHANNEL_GAS_SENSOR, strlen (CHANNEL_GAS_SENSOR), DATASTREAM_FLOAT), XivelyDatastream(CHANNEL_CO2_SENSOR, strlen (CHANNEL_CO2_SENSOR), DATASTREAM_FLOAT), XivelyDatastream(CHANNEL_DUST_SENSOR, strlen (CHANNEL_DUST_SENSOR), DATASTREAM_FLOAT) }; //Xively Feed XivelyFeed feed(XIVELY_FEED, datastreams, MAX_CHANNELS); //Xively Client WiFiClient client; XivelyClient xivelyclient(client);
函数:
更新数据流: 调用该函数可更新 xively.com通道数据流的值。 通道 ID 和数据流的值可传递至该函数。 如图 2 所示,该系统使用四条数据流。 数据流可更新为气体、co2 和灰尘传感器函数的原始传感器数据。 此外,主循环中的数据流 还可更新为整体空气质量值。
void updateCloudDatastreamValue(int channelID, int value) { // -- Update the Datastream Value datastreams[channelID].setFloat(value); }
将数据流发送至 Xively: 该函数针对 xively.com馈送执行 PUT 操作 。 函数返回成功或失败代码状态。 主循环调用该函数。
void sendToCloudService() { int status=0; Serial.println("-Send To Cloud Service”); // -- Upload the Datastream to Xively status = xivelyclient.put(feed, XIVELY_KEY); // -- Verify Transaction if (status == XIVELY_HTTP_SUCCESS) { Serial.println("--HTTP OK"); } else { Serial.print("--ERROR: "); Serial.println(status); } }
总结:
欢迎大家使用英特尔 Edison 平台研究空气质量监测。 挑战自我,添加其他显示各传感器状态的指示,添加针对空气质量变化的警告触发器增强云服务体验,并寻找机会将空气质量监测与其他系统相集成。
关于作者:
Mike Rylee 是英特尔公司的一名软件工程师,曾致力于开发基于 Android*、 Windows*、iOS* 和 Mac* 运行的嵌入式系统和应用。 他目前的主要工作是为 Android 和物联网相关项目提供支持。
++该示例源代码根据英特尔示例源许可发布
声明 本文档不代表英特尔公司或其它机构向 任何人明确或隐含地授予任何知识产权。
英特尔明确拒绝所有明确或隐含的担保,包括但不限于对于适销性、特定用途适用性和不侵犯任何权利的隐含担保,以及任何对于履约习惯、交易习惯或贸易惯例的担保。
本文包含尚处于开发阶段的产品、服务和/或流程的信息。 此处提供的所有信息可随时更改,恕不另行通知。 联系您的英特尔代表,了解最新的预测、时间表、规格和路线图。
本文所述的产品和服务可能包含与宣称的规格不符的缺陷或 失误。 英特尔提供最新的勘误表备索。
如欲获取本文提及的带订购编号的文档副本,可致电 1- 800-548-4725,或访问 www.intel.com/design/literature.htm。
英特尔和 Intel 标识是英特尔在美国和/或其他国家的商标 。
*其他的名称和品牌可能是其他所有者的资产。
英特尔公司 © 2015 年版权所有。