项目介绍
本项目的思路来自于我的工作日常,可能是因为办公室人多,空气中二氧化碳含量非常高,我一坐在工位上就犯困。所以我非常需要一个终端设备帮助我进行环境的温度、湿度、气压、二氧化碳浓度的监测。
本项目基于Wio Terminal实现了室内环境监测终端,采用传感器CCS811、BMP390、AHT20、ICM20948,并将传感器数据实时显示在WIO TERMINAL屏幕上。
传感器介绍
CCS811
CCS811是来自AMS公司的气体传感器,可以监测各种挥发性有机化合物(VOC),可以通过IIC返回eCO2(equivalent CO2等效二氧化碳浓度)和TVOC(Total Volatile Organic Compounds总挥发性有机化合物)浓度 。监测范围为百万分之 400 至 8192 (ppm) 范围内的eCO2(等效计算二氧化碳)浓度和十亿分之 1187 (ppb) 范围内的TVOC(总挥发性有机化合物)浓度。根据说明书,它可以检测醇类、醛类、酮类、有机酸、胺类、脂肪族和芳香族烃。
本次使用的传感器来自Adafruit,开发板体积非常精致,板载两个被Adafruit命名为StemmaQT的IIC端口,规格为SH1.0 4P。这样的接口对于IIC设备有着极好的扩展性。
ICM20948
ICM20948是来自Invensense的九轴传感器,它被认为是已停产的MPU9250的升级款。此传感器的测量精度为:
•±250 dps、±500 dps、±1000 dps 和 ±2000 dps可编程 FSR 的3 轴陀螺仪
•±2g、±4g、±8g 和 ±16g可编程 FSR 的 3 轴加速度计
• 3 轴罗盘,范围宽达±4900 µT
本次使用的ICM20948传感器同样来自Adafruit的设计。
AHT20
AHT20是来自广州奥松的温湿度传感器,这是一颗非常经济的传感器,单科价格仅为2元,精度为 +- 2% 相对湿度,20-80% RH 和 20-60 °C 时为 +-0.3 °C。
BMP390
BMP390是博世的气压传感器,BMP390是 BMP280 和 BMP388 的升级版——低空噪声低至 0.1m,转换时间同样快。该传感器的相对精度为 ±3 帕斯卡,相当于约 ±0.25 米的高度,同时支持以 ±0.5°C 的精度测量温度。
AHT20和BMP390的传感器扩展板是我自己绘制的,同时板上也设计了CCS811的电路,但是因为电路问题CCS811部分未调通。
功能演示
总结
Wio Terminal真的是一块无限接近于消费产品的开发板,精美的做工、放到现在依旧强劲的samd51处理器…… 虽然以当下的视角来看,它依然有很多可以改进的地方:不可触控的屏幕、宽广的黑边。但这些不足并不影响它作为一块优秀的开发板。
当然,这次的作品也会作为我未来项目的准备,希望未来能基于feather板卡的外形实现一个小型的室内监测终端,将尺寸从wioterminal的大小进一步缩小。
代码:
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include <Adafruit_AHTX0.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BMP3XX.h"
#include "Adafruit_CCS811.h"
#include <Adafruit_ICM20X.h>
#include <Adafruit_ICM20948.h>
#define SEALEVELPRESSURE_HPA (1013.25)
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
Adafruit_AHTX0 aht;
Adafruit_BMP3XX bmp;
Adafruit_CCS811 ccs;
Adafruit_ICM20948 icm;
uint16_t measurement_delay_us = 65535;
int mode=1;
void setup(void) {
Serial.begin(115200);
pinMode(WIO_5S_LEFT, INPUT_PULLUP);
pinMode(WIO_5S_RIGHT, INPUT_PULLUP);
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
while (! aht.begin()) {
Serial.println("Could not find AHT? Check wiring");
delay(10);
}
while (! bmp.begin_I2C()) {
Serial.println("Could not find a valid BMP3 sensor, check wiring!");
}
bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp.setOutputDataRate(BMP3_ODR_50_HZ);
while (! ccs.begin()){
Serial.println("Failed to start sensor! Please check your wiring.");
}
while (! icm.begin_I2C()){
Serial.println("Failed to find ICM20948 chip.");
}
}
void loop() {
if (digitalRead(WIO_5S_LEFT) == LOW) {
Serial.println("Left");
tft.fillScreen(TFT_BLACK);
mode--;
}
else if (digitalRead(WIO_5S_RIGHT) == LOW) {
Serial.println("Right");
tft.fillScreen(TFT_BLACK);
mode++;
}
if (mode==0) mode=4;
if (mode==5) mode=1;
if (mode==1)
{
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
// tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0, 4);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println("AHT20");
tft.printf("Temperature: %3.2f C \n",temp.temperature);
tft.printf("Humidity: %3.2f rH \n",humidity.relative_humidity);
}
if (mode==2)
{
bmp.performReading();
// tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0, 4);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println("BMP390");
tft.printf("Temperature: %3.2f C \n",bmp.temperature);
tft.printf("Pressure: %3.2f hPa \n",bmp.pressure / 100.0);
tft.printf("Altitude: %3.2f M \n",bmp.readAltitude(SEALEVELPRESSURE_HPA));
}
if (mode==3)
{
if(ccs.available()){
if(!ccs.readData()){
tft.setCursor(0, 0, 4);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println("CCS811");
tft.printf("CO2: %d \n",ccs.geteCO2());
tft.printf("ppm, TVOC: %d \n",ccs.getTVOC());
}
}
}
if (mode==4)
{
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t mag;
sensors_event_t temp;
icm.getEvent(&accel, &gyro, &temp, &mag);
// tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0, 4);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println("ICM20948");
tft.println("Accel");
tft.printf("X:%3.2f Y:%3.2f Z:%3.2f \n",accel.acceleration.x,accel.acceleration.y,accel.acceleration.z);
tft.println("Mag");
tft.printf("X: %3.2f Y:%3.2f Z:%3.2f \n",accel.acceleration.x,accel.acceleration.y,accel.acceleration.z);
tft.println("Gyro");
tft.printf("X:%3.2f Y:%3.2f Z:%3.2f \n",gyro.gyro.x,gyro.gyro.y,gyro.gyro.z);
}
delay(100);
}