65.9K
CodeProject 正在变化。 阅读更多。
Home

探索使用 Intel® Edison 进行空气质量监测

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2015年5月14日

CPOL

9分钟阅读

viewsIcon

21809

本文展示了一种通过使用 Arduino* 生态系统测量二氧化碳、挥发性有机化合物 (VOC) 和灰尘水平,并将数据发送到云服务提供商来探索空气质量监测的方法。

获取新的 Intel® IoT Developer Kit,这是一个完整的软硬件解决方案,使开发人员能够使用 Intel® Galileo 和 Intel® Edison 板创建令人兴奋的新解决方案。请访问 Intel® 物联网开发者中心

随着污染、过敏敏感性、健康与健身意识以及技术创新的兴起,空气质量监测是一个有趣的研究课题。消费品市场已推出创新产品,提高了人们对家庭空气质量监测的认识。其中一种产品是智能秤。这些智能秤可监测各种与健康相关的参数以及空气质量。空气质量数据会发送到云端,应用程序可以向您发出空气质量变化的警报,以便您知道何时需要通风。了解空气质量可以提高生活质量。本文展示了一种通过使用 Arduino* 生态系统测量二氧化碳、挥发性有机化合物 (VOC) 和灰尘水平,并将数据发送到云服务提供商来探索空气质量监测的方法。

Intel® Edison 平台凭借其快速的处理器、大内存容量以及集成的 WiFi 和蓝牙连接功能,非常适合启动新原型或迁移现有原型。Arduino 生态系统提供了一套功能强大的硬件和固件库,可用于使用 Intel® Edison 计算模块和 Intel® Edison Arduino 扩展板进行实验。

如需了解有关 Intel Edison 平台的更多信息,请参阅以下链接

http://www.intel.com/content/www/us/en/do-it-yourself/edison.html

硬件组件

该项目使用以下硬件组件构建空气质量监测系统

  • Intel® Edison 计算模块
  • Intel® Edison Arduino 扩展板
  • 共阴极 RGB LED + 3 个 1kΩ 电阻
  • GP2Y1010AU0F 光学灰尘传感器 + 150Ω 电阻 + 220 µF 电解电容
  • MQ-135 气体传感器
  • K-30 CO2 传感器
  • PIR 运动传感器

图 1 - 硬件图

工作原理

图 1 显示了硬件组件与 Intel® Edison Arduino 扩展板的连接。该系统使用 RGB LED 作为简单的视觉指示系统来显示空气质量。

为了确定一个区域的总空气质量,使用了三个传感器

  1. 使用光学灰尘传感器测量该区域的灰尘。
  2. 使用气体传感器测量挥发性有机化合物 (VOC),例如烟雾。
  3. 使用带 I2C 接口的 CO2 传感器测量二氧化碳水平。

此外,还使用运动传感器来帮助系统更好地代表区域内的总空气质量,方法是过滤掉由运动引起的灰尘浓度暂时增加,以及由靠近传感器呼吸的人引起的 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 时钟频率

需要注意的是,在撰写本文时,Intel® Edison 的默认 I2C 时钟频率高于 100kHz,这超出了 K-30 CO2 传感器的规格。K-30 CO2 传感器支持的最大 I2C 时钟频率 (SCL) 为 100kHz。可以通过以下几个步骤将 Intel® Edison 的 I2C 时钟频率更改为 100kHz

-确保安装了最新的 Intel® Edison Yocto 固件映像

http://www.intel.com/support/edison/sb/CS-035180.htm

-打开 Edison Linux 终端并以 root 用户登录

https://software.intel.com/en-us/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

如需了解有关 Intel® Edison 计算模块和 I2C 外设的更多信息,请参阅以下链接

http://www.intel.com/support/edison/sb/CS-035274.htm?wapkw=intel+edison+compute+module+hardware+guide

固件

以下代码显示了空气质量系统的包含文件、宏和函数。将讨论初始化、主循环、读取运动传感器、读取空气质量传感器、分析总空气质量、更新视觉指示 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();
}

读取气体传感器:气体传感器可以检测氨气、氮氧化物、酒精、苯和烟雾等气体。气体传感器有一个模拟电压输出,与空气中的气体水平成正比。执行 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 传感器返回百万分率 (ppm) 的 CO2 浓度水平。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);
  }
}

将数据发送到云服务提供商

如需将 Intel® 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);
  }
}

摘要

希望您喜欢使用 Intel Edison 平台探索空气质量监测。挑战自己添加额外的指示来显示每个传感器的状态,为云服务体验添加警报触发器以应对空气质量变化,并寻找将空气质量监测与其他系统集成的机会。

关于作者

Mike Rylee 是 Intel 公司的软件工程师,在嵌入式系统以及 Android*、Windows*、iOS* 和 Mac* 应用程序开发方面拥有丰富的经验。他目前致力于 Android 和物联网的开发。

++本示例源代码根据 Intel Sample Source License 发布

声明本文档不授予任何知识产权的许可(明示或暗示,通过禁止反悔或其他方式)。

Intel 否认所有明示和暗示的保证,包括但不限于适销性、特定用途的适用性以及非侵权性的暗示保证,以及因履约过程、交易过程或贸易用途而产生的任何保证。

本文档包含关于正在开发的产品、服务和/或流程的信息。此处提供所有信息如有更改,恕不另行通知。请联系您的 Intel 代表以获取最新的预测、计划、规格和路线图。

所描述的产品和服务可能包含称为勘误的缺陷或错误,这可能导致与公布的规格不符。当前的已特性化勘误可应要求提供。

可以通过致电 1-800-548-4725 或访问 www.intel.com/design/literature.htm 获取包含订单号且本文档中引用的文件的副本。

Intel 和 Intel 标志是 Intel Corporation 在美国和/或其他国家/地区的商标。

*其他名称和品牌可能被声明为他方财产

© 2015 Intel Corporation。

Intel® 物联网开发者中心

立即开始创新!Intel® 物联网开发者计划提供知识、工具、套件以及专家社区,助您快速轻松地将您的创新想法转化为物联网解决方案。

通过 Intel® IoT Developer Kit for Intel® Edison 和 Intel® Galileo 平台,尽情畅想,动手创造。这些套件是多功能、性能优化且完全集成的端到端物联网解决方案,支持各种编程环境、工具、安全、云连接和硬件。

如需更多资源并了解新的 Intel® 物联网开发者套件 v1.0 如何帮助您简化物联网项目

© . All rights reserved.