内容介绍
一. 背景
为了测量我家里的空气质量, 我购买了一台二氧化碳监测器,我非常喜欢它,因为它不仅可以显示二氧化碳水平,还可以显示室温。然而,这对我来说还不够。我想测量更多的参数,所以我正在寻找合适的设备。我发现有些贵得离谱,所以我决定自己做。
二. 使用到的芯片和外设
1. 微处理器 MAX32660
2. 电源 ADP151AUJZ-3.3-R7
ADP151 是一款超低噪声、低压差线性稳压器,工作电压范围为 2.2 V 至 5.5 V,并提供高达 200 mA 的输出电流。 200 mA 负载下 140 mV 的低压差提高了效率并允许在较宽的输入电压范围内工作。 ADP151 采用创新的电路拓扑结构,无需旁路电容器即可实现超低噪声性能,非常适合对噪声敏感的模拟和 RF 应用。 ADP151 还实现了超低噪声性能,而不会影响 PSRR 或瞬态线路和负载性能。 200 mA 负载下 265 μA 的低静态电流使 ADP151 适用于电池供电的便携式设备。
3. 屏幕
我希望它有一个最小 10 英寸的大屏幕,但是非常的昂贵,于是我决定还是选用比较常用的3.2寸TFT屏幕
4. 二氧化碳传感器
mh-z19二氧化碳传感器, 这也是这个项目里面最贵的部分, 虽然相比其他的二氧化碳传感器已经便宜很多了. 同时他也提供了可靠的测量和自动校准功能.
5. 室内温湿度传感器
我使用 SI7021 温度和湿度传感器进行室内监控,该传感器使用 I2C 协议并连接到 SDA 和 SCL 引脚。不贵,工业精度高。我喜欢它,因为我根本没有遇到任何麻烦。
6. 室外温湿度传感器
对于室外温度,我使用封装在不锈钢胶囊中的 DS18B20。价格便宜而且相对准确。通信是通过 1-wire 进行的。
7. 时间模块
使用 I2C 的 DS 1307 RTC 模块。
三. 系统框图:
四. 代码示例:
#include <Wire.h>
#include "RTClib.h"
//#include <Arduino.h>
#include <SPI.h>
#include <SoftwareSerial.h>
#include <SparkFunHTU21D.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <UTFT.h>
#define ONE_WIRE_BUS 9
#define GREENLED 5
#define YELLOWLED 7
#define REDLED 8
#define BUTTONLED 11
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
UTFT myGLCD(CTE32HR, 38, 39, 40, 41);
HTU21D myHumidity;
RTC_DS1307 rtc;
extern uint8_t Ubuntu[];
byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
unsigned char response[9];
unsigned int ppm;
unsigned long time;
int photocellReading;
int hourupg;
int minupg;
float humd;
float temp;
int tcolor;
int Z; //LED brightness
boolean Reset = false; // for reseting display;
void lamps(void) {
//CO2
if (ppm<800){
myGLCD.setColor(255,140,255); //green
myGLCD.fillCircle(450, 87, 12);
analogWrite(GREENLED, Z);
analogWrite(YELLOWLED, 0);
analogWrite(REDLED, 0);
}
if (ppm>800 & ppm<1200) {
myGLCD.setColor(70,70,255); //Yellow
myGLCD.fillCircle(450, 87, 12);
analogWrite(GREENLED, 0);
analogWrite(YELLOWLED, Z);
analogWrite(REDLED, 0);
}
if (ppm>1200){
myGLCD.setColor(VGA_AQUA);
myGLCD.fillCircle(450, 87, 12);
analogWrite(GREENLED, 0);
analogWrite(YELLOWLED, 0);
analogWrite(REDLED, Z);
}
//Hum
if (humd>30 & humd<50) {
myGLCD.setColor(255,140,255); //green
myGLCD.fillCircle(450, 149, 12);
}
if (humd>20 & humd<30) {
myGLCD.setColor(70,70,255); //Yellow
myGLCD.fillCircle(450, 149, 12);
}
if (humd<20) {
myGLCD.setColor(70,70,255); //Yellow
myGLCD.fillCircle(450, 149, 12);
}
if (humd>50 & humd<60) {
myGLCD.setColor(70,70,255); //Yellow
myGLCD.fillCircle(450, 149, 12);
}
if (humd>60) {
myGLCD.setColor(VGA_AQUA);
myGLCD.fillCircle(450, 149, 12);
}
//Temp ins
if (temp>20 & temp<27) {
myGLCD.setColor(255,140,255); //green
myGLCD.fillCircle(450, 213, 12);
} else {
myGLCD.setColor(70,70,255); //Yellow
myGLCD.fillCircle(450, 213, 12);
}
//Tempouts
if (sensors.getTempCByIndex(0)<10) {
myGLCD.setColor(70,70,255); //Yellow
myGLCD.fillCircle(450, 278, 12);
} else {
myGLCD.setColor(255,140,255); //green
myGLCD.fillCircle(450, 278, 12);
}}
void drawmain(void) {
myGLCD.setFont(Ubuntu);
if (tcolor==0) myGLCD.setColor(VGA_BLACK);
if (tcolor==1) myGLCD.setColor(VGA_SILVER);
if (tcolor==2) myGLCD.setColor(250,10,250);
if (tcolor==3) myGLCD.setColor(200,100,200);
if (tcolor==4) myGLCD.setColor(100,200,200);
if (tcolor==5) myGLCD.setColor(10,200,200);
if (tcolor==6) myGLCD.setColor(200,200,100);
if (tcolor==7) myGLCD.setColor(250,250,10);
if (tcolor==8) myGLCD.setColor(10,10,250);
if (tcolor==9) myGLCD.setColor(10,250,10);
if (tcolor==10) myGLCD.setColor(250,10,10);
if (tcolor==11) myGLCD.setColor(VGA_TEAL);
if (tcolor==12) myGLCD.setColor(VGA_AQUA);
DateTime now = rtc.now();
// Time
if (now.hour()<10)
{
myGLCD.print("0", 190, 7);
myGLCD.printNumI(now.hour(), 215, 7);
}
else
{
myGLCD.printNumI(now.hour(), 190, 7);
}
myGLCD.print(":", 240, 5);
if (now.minute()<10)
{
myGLCD.print("0", 265, 7);
myGLCD.printNumI(now.minute(), 290, 7);
}
else
{
myGLCD.printNumI(now.minute(), 265, 7);
}
//myGLCD.setColor(VGA_BLACK);
myGLCD.print("CO2", 18, 74);
if (ppm > 999)
{
myGLCD.printNumI(ppm, 250, 74);
}
else
{
myGLCD.print(" ", 250, 74);
myGLCD.printNumI(ppm, 275, 74);
}
myGLCD.print("ppm", 348, 74);
myGLCD.print("Humidity", 18, 136);
myGLCD.printNumI(humd, 343, 136); //humd
myGLCD.print("%", 398, 136);
myGLCD.print("Temp(in)", 18, 200);
if (temp>=0) {
if (temp<10) {
myGLCD.print(" ", 275, 200);
myGLCD.print("+", 300, 200); //temp
myGLCD.printNumF(temp,1, 325, 200);
}
else
{
myGLCD.print("+", 275, 200); //temp
myGLCD.printNumF(temp,1, 300, 200);
}
}
if (temp<0){
if (temp>-10) {
myGLCD.print(" ", 275, 200);
myGLCD.printNumF(temp,1, 300, 200);
}
else
{
myGLCD.printNumF(temp,1, 275, 200);
}
}
myGLCD.print("C", 398, 200);
myGLCD.print("Temp(out)", 18, 265);
if (sensors.getTempCByIndex(0)<-100) {
myGLCD.print("Empty", 300, 265);
}
else{
if (sensors.getTempCByIndex(0)>=0) {
if (sensors.getTempCByIndex(0)<10) {
myGLCD.print(" ", 275, 200);
myGLCD.print("+", 300, 265);
myGLCD.printNumF(sensors.getTempCByIndex(0),1, 325, 265);
}
else
{
myGLCD.print("+", 275, 265);
myGLCD.printNumF(sensors.getTempCByIndex(0),1, 300, 265);
}}
if (sensors.getTempCByIndex(0)<0){
if (sensors.getTempCByIndex(0)>-10) {
myGLCD.print(" ", 275, 200);
myGLCD.printNumF(sensors.getTempCByIndex(0),1, 300, 265);
}
else
{
myGLCD.printNumF(sensors.getTempCByIndex(0),1, 275, 265);}}
myGLCD.print("C", 398, 265);
}}
void dateandtime(void) {
DateTime now = rtc.now();
hourupg=now.hour();
minupg=now.minute();
//time adjustment
if (digitalRead(3) == LOW) {
if (minupg==59)
{
minupg=0;
}
else
{
minupg=minupg+1;
}
rtc.adjust(DateTime(0,0,0,hourupg,minupg,0));
}
if (digitalRead(2) == LOW) {
if(hourupg==23)
{
hourupg=0;
}
else
{
hourupg=hourupg+1;
}
rtc.adjust(DateTime(0,0,0,hourupg,minupg,0));
}}
void co2(void) {
Serial3.write(cmd, 9);
memset(response, 0, 9);
Serial3.readBytes(response, 9);
int i;
byte crc = 0;
for (i = 1; i < 8; i++) crc+=response[i];
crc = 255 - crc;
crc++;
if ( !(response[0] == 0xFF && response[1] == 0x86 && response[8] == crc) ) {
} else {
unsigned int responseHigh = (unsigned int) response[2];
unsigned int responseLow = (unsigned int) response[3];
ppm = (256*responseHigh) + responseLow;
}
}
void th(void) {
humd = myHumidity.readHumidity();
temp = myHumidity.readTemperature();
sensors.requestTemperatures(); // Send the command to get temperature readings
}
void photosensor(void) {
photocellReading = analogRead(12);
if (photocellReading < 150) {
// Serial.println(" - Dark");
analogWrite(BUTTONLED, 5);
Z=25;
} else if (photocellReading < 300) {
// Serial.println(" - Dim");
analogWrite(BUTTONLED, 50);
Z=80;
} else if (photocellReading < 700) {
// Serial.println(" - Light");
analogWrite(BUTTONLED, 100);
Z=120;
} else if (photocellReading < 900) {
// Serial.println(" - Bright");
analogWrite(BUTTONLED, 150);
Z=150;
} else {
// Serial.println(" - Very bright");
analogWrite(BUTTONLED, 200);
Z=200;
}
// Serial.print(photocellReading);
}
void screenreset(void) {
if(((hourupg==0 && minupg==0) || (hourupg==12 && minupg==0)) && Reset==false) {
myGLCD.clrScr();
myGLCD.fillScr(VGA_WHITE); //due to inverted colors on my display
myGLCD.setBackColor(VGA_WHITE); //due to inverted colors on my display
Reset=true;}
if((hourupg==0 || hourupg==12)&& minupg>0) {
Reset=false;
}}
void setup(void) {
myGLCD.InitLCD();
myGLCD.clrScr();
myGLCD.fillScr(VGA_WHITE); //due to inverted colors on my display
myGLCD.setBackColor(VGA_WHITE); //due to inverted colors on my display
Serial3.begin(9600);
//Serial.begin(9600);
sensors.begin();
myHumidity.begin();
tcolor=0;
rtc.begin();
pinMode(GREENLED, OUTPUT);
pinMode(YELLOWLED, OUTPUT);
pinMode(REDLED, OUTPUT);
pinMode(BUTTONLED, OUTPUT);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
Z=0;
}
void loop(void) {
co2();
photosensor();
dateandtime();
th();
if (digitalRead(4) == LOW){
tcolor=tcolor+1;
}
if (tcolor>=13) tcolor=0;
drawmain();
lamps();
screenreset();
}