mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-06-26 16:21:33 +02:00
Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
ee40b60aad | |||
b9a968ef7a | |||
4bb434562f | |||
ab1f6c1ae7 | |||
63c7e9ca00 | |||
0b8408ef13 | |||
ff34d2c143 | |||
73498894e4 | |||
ed3b0ff53f | |||
07e1b5e97a | |||
348ddba048 | |||
a3c8054839 | |||
555693cda8 | |||
0a9f184946 | |||
7c02564ed4 | |||
c270cda600 | |||
0abc5629fc | |||
a40399d082 | |||
0753a4c9dd | |||
1a5ac64aa1 | |||
f170404c03 | |||
16a29b4646 | |||
bb3c57297e |
@ -11,7 +11,7 @@
|
||||
#include <SoftwareSerial.h>
|
||||
#include "Arduino.h"
|
||||
#include <Wire.h>
|
||||
#include <Math.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
// Constructor /////////////////////////////////////////////////////////////////
|
||||
@ -303,7 +303,7 @@ TMP_RH AirGradient::periodicFetchData() //
|
||||
return result;
|
||||
}
|
||||
else
|
||||
returnError(error);
|
||||
return returnError(error);
|
||||
}
|
||||
|
||||
TMP_RH_ErrorCode AirGradient::periodicStop() {
|
||||
@ -607,47 +607,27 @@ const char* AirGradient::getCO2(int retryLimit) {
|
||||
return Char_CO2;
|
||||
}
|
||||
int AirGradient::getCO2_Raw(){
|
||||
int retry = 0;
|
||||
CO2_READ_RESULT result;
|
||||
const byte CO2Command[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};
|
||||
byte CO2Response[] = {0,0,0,0,0,0,0};
|
||||
const byte CO2Command[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};
|
||||
byte CO2Response[] = {0,0,0,0,0,0,0};
|
||||
|
||||
while(!(_SoftSerial_CO2->available())) {
|
||||
retry++;
|
||||
// keep sending request until we start to get a response
|
||||
_SoftSerial_CO2->write(CO2Command, 7);
|
||||
delay(50);
|
||||
if (retry > 10) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int timeout = 0;
|
||||
|
||||
while (_SoftSerial_CO2->available() < 7) {
|
||||
timeout++;
|
||||
if (timeout > 10) {
|
||||
while(_SoftSerial_CO2->available())
|
||||
_SoftSerial_CO2->read();
|
||||
break;
|
||||
}
|
||||
delay(50);
|
||||
}
|
||||
_SoftSerial_CO2->write(CO2Command, 7);
|
||||
delay(100); //give the sensor a bit of time to respond
|
||||
|
||||
if (_SoftSerial_CO2->available()){
|
||||
for (int i=0; i < 7; i++) {
|
||||
int byte = _SoftSerial_CO2->read();
|
||||
if (byte == -1) {
|
||||
result.success = false;
|
||||
return -1;
|
||||
}
|
||||
CO2Response[i] = byte;
|
||||
}
|
||||
int valMultiplier = 1;
|
||||
int high = CO2Response[3];
|
||||
int low = CO2Response[4];
|
||||
unsigned long val = high*256 + low;
|
||||
|
||||
int byte = _SoftSerial_CO2->read();
|
||||
CO2Response[i] = byte;
|
||||
if (CO2Response[0] != 254) {
|
||||
return -1; //error code for debugging
|
||||
}
|
||||
}
|
||||
unsigned long val = CO2Response[3]*256 + CO2Response[4];
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -2; //error code for debugging
|
||||
}
|
||||
}
|
||||
|
||||
//END CO2 FUNCTIONS //
|
||||
|
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 AirGradient
|
||||
Copyright (c) 2022 AirGradient
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -3,6 +3,6 @@ AirGradient Arduino Library for ESP8266 (Wemos D1 MINI)
|
||||
|
||||
Build your own low cost air quality sensor with optional display measuring PM2.5, CO2, Temperature and Humidity.
|
||||
|
||||
This library makes it easy to read the sensor data from the Plantower PMS5003 PM2.5 sensor, the Senseair S8 and the SHT30/31 Temperature and Humidity sensor. Visit our blog for detailed build instructions and PCB layout.
|
||||
This library makes it easy to read the sensor data from the Plantower PMS5003 PM2.5 sensor, the Senseair S8 and the SHT30/31 Temperature and Humidity sensor. Visit our DIY section for detailed build instructions and PCB layout.
|
||||
|
||||
https://www.airgradient.com/blog/
|
||||
https://www.airgradient.com/open-airgradient/instructions/
|
||||
|
BIN
examples/C02_PM_SHT/.DS_Store
vendored
BIN
examples/C02_PM_SHT/.DS_Store
vendored
Binary file not shown.
@ -1,26 +0,0 @@
|
||||
#include <AirGradient.h>
|
||||
AirGradient ag = AirGradient();
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
ag.PMS_Init();
|
||||
ag.CO2_Init();
|
||||
ag.TMP_RH_Init(0x44); //check for SHT sensor with address 0x44
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
Serial.print("PM2: ");
|
||||
Serial.println(ag.getPM2());
|
||||
|
||||
|
||||
Serial.print("CO2: ");
|
||||
Serial.println(ag.getCO2());
|
||||
|
||||
TMP_RH result = ag.periodicFetchData();
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(result.rh);
|
||||
Serial.print(" Temperature: ");
|
||||
Serial.println(result.t);
|
||||
delay(5000);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
#include <AirGradient.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_SSD1306.h>
|
||||
|
||||
AirGradient ag = AirGradient();
|
||||
#define OLED_RESET 0
|
||||
Adafruit_SSD1306 display(OLED_RESET);
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
|
||||
ag.PMS_Init();
|
||||
ag.CO2_Init();
|
||||
ag.TMP_RH_Init(0x44); //check for SHT sensor with address 0x44
|
||||
showTextRectangle("Init", String(ESP.getChipId(),HEX),"AirGradient");
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
int PM2 = ag.getPM2_Raw();
|
||||
int CO2 = ag.getCO2_Raw();
|
||||
TMP_RH result = ag.periodicFetchData();
|
||||
showTextRectangle(String(result.t)+"c "+String(result.rh)+"%", "PM2: "+ String(ag.getPM2()), "CO2: "+String(ag.getCO2())+"");
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
// DISPLAY
|
||||
void showTextRectangle(String ln1, String ln2, String ln3) {
|
||||
display.clearDisplay();
|
||||
display.setTextColor(WHITE);
|
||||
display.setTextSize(1);
|
||||
display.setCursor(32,8);
|
||||
display.println(ln1);
|
||||
display.setTextSize(1);
|
||||
display.setCursor(32,16);
|
||||
display.println(ln2);
|
||||
display.setTextSize(1);
|
||||
display.setCursor(32,24);
|
||||
display.println(ln3);
|
||||
display.display();
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
#include <AirGradient.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
AirGradient ag = AirGradient();
|
||||
#define OLED_RESET 0
|
||||
Adafruit_SSD1306 display(OLED_RESET);
|
||||
|
||||
String APIROOT = "http://hw.airgradient.com/";
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
|
||||
ag.PMS_Init();
|
||||
ag.CO2_Init();
|
||||
ag.TMP_RH_Init(0x44); //check for SHT sensor with address 0x44
|
||||
showTextRectangle("Init", String(ESP.getChipId(),HEX),"AirGradient");
|
||||
connectToWifi();
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
int PM2 = ag.getPM2_Raw();
|
||||
int CO2 = ag.getCO2_Raw();
|
||||
TMP_RH result = ag.periodicFetchData();
|
||||
showTextRectangle(String(result.t)+"c "+String(result.rh)+"%", "PM2: "+ String(PM2), "CO2: "+String(CO2)+"");
|
||||
|
||||
// send payload
|
||||
String payload = "{\"pm02\":" + String(ag.getPM2()) + ",\"wifi\":" + String(WiFi.RSSI()) + ",\"rco2\":" + String(ag.getCO2()) + ",\"atmp\":" + String(result.t) + ",\"rhum\":" + String(result.rh) + "}";
|
||||
Serial.println(payload);
|
||||
String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(),HEX) + "/measures";
|
||||
Serial.println(POSTURL);
|
||||
HTTPClient http;
|
||||
http.begin(POSTURL);
|
||||
http.addHeader("content-type", "application/json");
|
||||
int httpCode = http.POST(payload);
|
||||
String response = http.getString();
|
||||
Serial.println(httpCode);
|
||||
Serial.println(response);
|
||||
http.end();
|
||||
|
||||
delay(15000);
|
||||
}
|
||||
|
||||
// DISPLAY
|
||||
void showTextRectangle(String ln1, String ln2, String ln3) {
|
||||
display.clearDisplay();
|
||||
display.setTextColor(WHITE);
|
||||
display.setTextSize(1);
|
||||
display.setCursor(32,8);
|
||||
display.println(ln1);
|
||||
display.setTextSize(1);
|
||||
display.setCursor(32,16);
|
||||
display.println(ln2);
|
||||
display.setTextSize(1);
|
||||
display.setCursor(32,24);
|
||||
display.println(ln3);
|
||||
display.display();
|
||||
}
|
||||
|
||||
// Wifi Manager
|
||||
void connectToWifi(){
|
||||
WiFiManager wifiManager;
|
||||
//chWiFi.disconnect(); //to delete previous saved hotspot
|
||||
String HOTSPOT = "AIRGRADIENT-"+String(ESP.getChipId(),HEX);
|
||||
wifiManager.setTimeout(120);
|
||||
if(!wifiManager.autoConnect((const char*)HOTSPOT.c_str())) {
|
||||
//Serial.println("failed to connect and hit timeout");
|
||||
delay(3000);
|
||||
ESP.restart();
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,25 @@
|
||||
/*
|
||||
This is the code for the AirGradient DIY Air Quality Sensor with an ESP8266 Microcontroller.
|
||||
|
||||
It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi.
|
||||
|
||||
For build instructions please visit https://www.airgradient.com/open-airgradient/instructions/
|
||||
|
||||
Compatible with the following sensors:
|
||||
SenseAir S8 (CO2 Sensor)
|
||||
|
||||
Please install ESP8266 board manager (tested with version 3.0.0)
|
||||
|
||||
If you have any questions please visit our forum at https://forum.airgradient.com/
|
||||
|
||||
If you are a school or university contact us for a free trial on the AirGradient platform.
|
||||
https://www.airgradient.com/
|
||||
|
||||
Kits with all required components are available at https://www.airgradient.com/open-airgradient/shop/
|
||||
|
||||
MIT License
|
||||
*/
|
||||
|
||||
#include <AirGradient.h>
|
||||
AirGradient ag = AirGradient();
|
||||
|
||||
|
131
examples/CO2_TRAFFIC_LIGHT/CO2_TRAFFIC_LIGHT_SIMPLE.ino
Normal file
131
examples/CO2_TRAFFIC_LIGHT/CO2_TRAFFIC_LIGHT_SIMPLE.ino
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
This is the code for the AirGradient DIY CO2 Traffic light with an ESP8266 Microcontroller.
|
||||
|
||||
For build instructions please visit:
|
||||
https://www.airgradient.com/open-airgradient/instructions/diy-co2-traffic-light/
|
||||
|
||||
Kits (including a pre-soldered version) are available:
|
||||
https://www.airgradient.com/open-airgradient/kits/
|
||||
|
||||
Compatible with the following sensors:
|
||||
SenseAir S8 (CO2 Sensor)
|
||||
|
||||
Please install ESP8266 board manager (tested with version 3.0.0)
|
||||
|
||||
Please install the following libraries:
|
||||
"Adafruit NeoMatrix" Library (tested with 1.2.0)
|
||||
"WifiManager by tzapu, tablatronix" tested with Version 2.0.3-alpha
|
||||
|
||||
If you have any questions please visit our forum at https://forum.airgradient.com/
|
||||
|
||||
If you are a school or university contact us for a free trial on the AirGradient platform.
|
||||
https://www.airgradient.com/
|
||||
|
||||
MIT License
|
||||
*/
|
||||
|
||||
#include <AirGradient.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_NeoMatrix.h>
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#ifndef PSTR
|
||||
#define PSTR // Make Arduino Due happy
|
||||
#endif
|
||||
|
||||
AirGradient ag = AirGradient();
|
||||
#define PIN D8
|
||||
|
||||
int co2 = 0;
|
||||
String text = "AirGradient CO2";
|
||||
// set to true if you want to connect to wifi. The display will show values only when the sensor has wifi connection
|
||||
boolean connectWIFI=true;
|
||||
int greenToOrange = 800;
|
||||
int orangeToRed = 1200;
|
||||
|
||||
// change if you want to send the data to another server
|
||||
String APIROOT = "http://hw.airgradient.com/";
|
||||
|
||||
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(8, 8, PIN,
|
||||
NEO_MATRIX_TOP + NEO_MATRIX_RIGHT +
|
||||
NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
|
||||
NEO_GRB + NEO_KHZ800);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
ag.CO2_Init();
|
||||
matrix.begin();
|
||||
matrix.setRotation(1); // change rotation
|
||||
matrix.setTextWrap(false);
|
||||
matrix.setBrightness(40);
|
||||
matrix.setTextColor(matrix.Color(70,130,180));
|
||||
|
||||
Serial.println("Chip ID: "+String(ESP.getChipId(),HEX));
|
||||
if (connectWIFI) connectToWifi();
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
showText();
|
||||
}
|
||||
|
||||
int x = matrix.width();
|
||||
|
||||
void showText() {
|
||||
Serial.println("in loop");
|
||||
matrix.fillScreen(0);
|
||||
matrix.setCursor(x, 0);
|
||||
matrix.print(String(text));
|
||||
if(--x < -100) {
|
||||
x = matrix.width();
|
||||
Serial.println("end text");
|
||||
co2 = ag.getCO2_Raw();
|
||||
text = String(co2)+"ppm";
|
||||
if (co2>350) matrix.setTextColor(matrix.Color(0, 255, 0));
|
||||
if (co2>greenToOrange) matrix.setTextColor(matrix.Color(255, 90, 0));
|
||||
if (co2>orangeToRed) matrix.setTextColor(matrix.Color(255,0, 0));
|
||||
|
||||
// send payload
|
||||
String payload = "{\"wifi\":" + String(WiFi.RSSI()) + ",";
|
||||
payload = payload + "\"rco2\":" + String(co2);
|
||||
payload = payload + "}";
|
||||
|
||||
if (connectWIFI) {
|
||||
Serial.println(payload);
|
||||
String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(), HEX) + "/measures";
|
||||
Serial.println(POSTURL);
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
http.begin(client, POSTURL);
|
||||
http.addHeader("content-type", "application/json");
|
||||
int httpCode = http.POST(payload);
|
||||
String response = http.getString();
|
||||
Serial.println(httpCode);
|
||||
Serial.println(response);
|
||||
http.end();
|
||||
delay(20000);
|
||||
}
|
||||
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
matrix.show();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// Wifi Manager
|
||||
void connectToWifi(){
|
||||
WiFiManager wifiManager;
|
||||
//WiFi.disconnect(); //to delete previous saved hotspot
|
||||
String HOTSPOT = "AIRGRADIENT-"+String(ESP.getChipId(),HEX);
|
||||
wifiManager.setTimeout(120);
|
||||
if(!wifiManager.autoConnect((const char*)HOTSPOT.c_str())) {
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(3000);
|
||||
ESP.restart();
|
||||
delay(5000);
|
||||
}
|
||||
}
|
235
examples/DIY_BASIC/DIY_BASIC.ino
Normal file
235
examples/DIY_BASIC/DIY_BASIC.ino
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
This is the code for the AirGradient DIY BASIC Air Quality Sensor with an ESP8266 Microcontroller.
|
||||
|
||||
It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi.
|
||||
|
||||
Build Instructions: https://www.airgradient.com/open-airgradient/instructions/diy/
|
||||
|
||||
Kits (including a pre-soldered version) are available: https://www.airgradient.com/open-airgradient/kits/
|
||||
|
||||
The codes needs the following libraries installed:
|
||||
“WifiManager by tzapu, tablatronix” tested with version 2.0.11-beta
|
||||
“U8g2” by oliver tested with version 2.32.15
|
||||
|
||||
Configuration:
|
||||
Please set in the code below the configuration parameters.
|
||||
|
||||
If you have any questions please visit our forum at https://forum.airgradient.com/
|
||||
|
||||
If you are a school or university contact us for a free trial on the AirGradient platform.
|
||||
https://www.airgradient.com/
|
||||
|
||||
MIT License
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <AirGradient.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <Wire.h>
|
||||
#include "SSD1306Wire.h"
|
||||
|
||||
AirGradient ag = AirGradient();
|
||||
|
||||
SSD1306Wire display(0x3c, SDA, SCL);
|
||||
|
||||
// CONFIGURATION START
|
||||
|
||||
// set to true to switch PM2.5 from ug/m3 to US AQI
|
||||
boolean inUSaqi = true;
|
||||
|
||||
// set to true to switch from Celcius to Fahrenheit
|
||||
boolean inF = false;
|
||||
|
||||
// set to true if you want to connect to wifi. The display will show values only when the sensor has wifi connection
|
||||
boolean connectWIFI=true;
|
||||
|
||||
// CONFIGURATION END
|
||||
|
||||
unsigned long currentMillis = 0;
|
||||
|
||||
const int oledInterval = 5000;
|
||||
unsigned long previousOled = 0;
|
||||
|
||||
const int sendToServerInterval = 10000;
|
||||
unsigned long previoussendToServer = 0;
|
||||
|
||||
const int co2Interval = 5000;
|
||||
unsigned long previousCo2 = 0;
|
||||
int Co2 = 0;
|
||||
|
||||
const int pm25Interval = 5000;
|
||||
unsigned long previousPm25 = 0;
|
||||
int pm25 = 0;
|
||||
|
||||
const int tempHumInterval = 2500;
|
||||
unsigned long previousTempHum = 0;
|
||||
float temp = 0;
|
||||
int hum = 0;
|
||||
int displaypage = 0;
|
||||
|
||||
String APIROOT = "http://hw.airgradient.com/";
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
display.init();
|
||||
display.flipScreenVertically();
|
||||
|
||||
if (connectWIFI) {
|
||||
connectToWifi();
|
||||
}
|
||||
|
||||
showTextRectangle("Init", String(ESP.getChipId(), HEX), true);
|
||||
|
||||
ag.CO2_Init();
|
||||
ag.PMS_Init();
|
||||
ag.TMP_RH_Init(0x44);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
currentMillis = millis();
|
||||
updateOLED();
|
||||
updateCo2();
|
||||
updatePm25();
|
||||
updateTempHum();
|
||||
sendToServer();
|
||||
}
|
||||
|
||||
void updateCo2()
|
||||
{
|
||||
if (currentMillis - previousCo2 >= co2Interval) {
|
||||
previousCo2 += co2Interval;
|
||||
Co2 = ag.getCO2_Raw();
|
||||
Serial.println(String(Co2));
|
||||
}
|
||||
}
|
||||
|
||||
void updatePm25()
|
||||
{
|
||||
if (currentMillis - previousPm25 >= pm25Interval) {
|
||||
previousPm25 += pm25Interval;
|
||||
pm25 = ag.getPM2_Raw();
|
||||
Serial.println(String(pm25));
|
||||
}
|
||||
}
|
||||
|
||||
void updateTempHum()
|
||||
{
|
||||
if (currentMillis - previousTempHum >= tempHumInterval) {
|
||||
previousTempHum += tempHumInterval;
|
||||
TMP_RH result = ag.periodicFetchData();
|
||||
temp = result.t;
|
||||
hum = result.rh;
|
||||
Serial.println(String(temp));
|
||||
}
|
||||
}
|
||||
|
||||
void updateOLED() {
|
||||
if (currentMillis - previousOled >= oledInterval) {
|
||||
previousOled += oledInterval;
|
||||
|
||||
switch (displaypage) {
|
||||
case 0:
|
||||
if (inUSaqi) {
|
||||
showTextRectangle("AQI", String(PM_TO_AQI_US(pm25)), false);
|
||||
} else {
|
||||
showTextRectangle("PM2", String(pm25), false);
|
||||
}
|
||||
displaypage = 1;
|
||||
break;
|
||||
case 1:
|
||||
showTextRectangle("CO2", String(Co2), false);
|
||||
displaypage = 2;
|
||||
break;
|
||||
case 2:
|
||||
if (inF) {
|
||||
showTextRectangle("F", String((temp * 9 / 5) + 32), false);
|
||||
} else {
|
||||
showTextRectangle("C", String(temp), false);
|
||||
}
|
||||
displaypage = 3;
|
||||
break;
|
||||
case 3:
|
||||
showTextRectangle("Hum", String(hum)+"%", false);
|
||||
displaypage = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void showTextRectangle(String ln1, String ln2, boolean small) {
|
||||
display.clear();
|
||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
if (small) {
|
||||
display.setFont(ArialMT_Plain_16);
|
||||
} else {
|
||||
display.setFont(ArialMT_Plain_24);
|
||||
}
|
||||
display.drawString(32, 16, ln1);
|
||||
display.drawString(32, 38, ln2);
|
||||
display.display();
|
||||
}
|
||||
|
||||
void sendToServer() {
|
||||
if (currentMillis - previoussendToServer >= sendToServerInterval) {
|
||||
previoussendToServer += sendToServerInterval;
|
||||
String payload = "{\"wifi\":" + String(WiFi.RSSI())
|
||||
+ ", \"rco2\":" + String(Co2)
|
||||
+ ", \"pm02\":" + String(pm25)
|
||||
+ ", \"atmp\":" + String(temp)
|
||||
+ ", \"rhum\":" + String(hum)
|
||||
+ "}";
|
||||
|
||||
if(WiFi.status()== WL_CONNECTED){
|
||||
Serial.println(payload);
|
||||
String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(), HEX) + "/measures";
|
||||
Serial.println(POSTURL);
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
http.begin(client, POSTURL);
|
||||
http.addHeader("content-type", "application/json");
|
||||
int httpCode = http.POST(payload);
|
||||
String response = http.getString();
|
||||
Serial.println(httpCode);
|
||||
Serial.println(response);
|
||||
http.end();
|
||||
}
|
||||
else {
|
||||
Serial.println("WiFi Disconnected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wifi Manager
|
||||
void connectToWifi() {
|
||||
WiFiManager wifiManager;
|
||||
//WiFi.disconnect(); //to delete previous saved hotspot
|
||||
String HOTSPOT = "AIRGRADIENT-" + String(ESP.getChipId(), HEX);
|
||||
wifiManager.setTimeout(60);
|
||||
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
|
||||
showTextRectangle("offline", "mode", true);
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(6000);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate PM2.5 US AQI
|
||||
int PM_TO_AQI_US(int pm02) {
|
||||
if (pm02 <= 12.0) return ((50 - 0) / (12.0 - .0) * (pm02 - .0) + 0);
|
||||
else if (pm02 <= 35.4) return ((100 - 50) / (35.4 - 12.0) * (pm02 - 12.0) + 50);
|
||||
else if (pm02 <= 55.4) return ((150 - 100) / (55.4 - 35.4) * (pm02 - 35.4) + 100);
|
||||
else if (pm02 <= 150.4) return ((200 - 150) / (150.4 - 55.4) * (pm02 - 55.4) + 150);
|
||||
else if (pm02 <= 250.4) return ((300 - 200) / (250.4 - 150.4) * (pm02 - 150.4) + 200);
|
||||
else if (pm02 <= 350.4) return ((400 - 300) / (350.4 - 250.4) * (pm02 - 250.4) + 300);
|
||||
else if (pm02 <= 500.4) return ((500 - 400) / (500.4 - 350.4) * (pm02 - 350.4) + 400);
|
||||
else return 500;
|
||||
};
|
242
examples/DIY_PRO/DIY_PRO.ino
Normal file
242
examples/DIY_PRO/DIY_PRO.ino
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
This is the code for the AirGradient DIY PRO Air Quality Sensor with an ESP8266 Microcontroller.
|
||||
|
||||
It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi.
|
||||
|
||||
Build Instructions: https://www.airgradient.com/open-airgradient/instructions/diy-pro/
|
||||
|
||||
Kits (including a pre-soldered version) are available: https://www.airgradient.com/open-airgradient/kits/
|
||||
|
||||
The codes needs the following libraries installed:
|
||||
“WifiManager by tzapu, tablatronix” tested with version 2.0.11-beta
|
||||
“U8g2” by oliver tested with version 2.32.15
|
||||
“SGP30” by Rob Tilaart tested with Version 0.1.5
|
||||
|
||||
Configuration:
|
||||
Please set in the code below the configuration parameters.
|
||||
|
||||
If you have any questions please visit our forum at https://forum.airgradient.com/
|
||||
|
||||
If you are a school or university contact us for a free trial on the AirGradient platform.
|
||||
https://www.airgradient.com/
|
||||
|
||||
MIT License
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <AirGradient.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <WiFiClient.h>
|
||||
|
||||
#include "SGP30.h"
|
||||
#include <U8g2lib.h>
|
||||
|
||||
AirGradient ag = AirGradient();
|
||||
SGP30 SGP;
|
||||
|
||||
// Display bottom right
|
||||
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
|
||||
|
||||
// Replace above if you have display on top left
|
||||
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R3, /* reset=*/ U8X8_PIN_NONE);
|
||||
|
||||
|
||||
// CONFIGURATION START
|
||||
|
||||
//set to the endpoint you would like to use
|
||||
String APIROOT = "http://hw.airgradient.com/";
|
||||
|
||||
// set to true to switch from Celcius to Fahrenheit
|
||||
boolean inF = false;
|
||||
|
||||
// set to true if you want to connect to wifi. You have 60 seconds to connect. Then it will go into an offline mode.
|
||||
boolean connectWIFI=true;
|
||||
|
||||
// CONFIGURATION END
|
||||
|
||||
|
||||
unsigned long currentMillis = 0;
|
||||
|
||||
const int oledInterval = 5000;
|
||||
unsigned long previousOled = 0;
|
||||
|
||||
const int sendToServerInterval = 10000;
|
||||
unsigned long previoussendToServer = 0;
|
||||
|
||||
const int tvocInterval = 1000;
|
||||
unsigned long previousTVOC = 0;
|
||||
int TVOC = 0;
|
||||
|
||||
const int co2Interval = 5000;
|
||||
unsigned long previousCo2 = 0;
|
||||
int Co2 = 0;
|
||||
|
||||
const int pm25Interval = 5000;
|
||||
unsigned long previousPm25 = 0;
|
||||
int pm25 = 0;
|
||||
|
||||
const int tempHumInterval = 2500;
|
||||
unsigned long previousTempHum = 0;
|
||||
float temp = 0;
|
||||
int hum = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
u8g2.begin();
|
||||
updateOLED();
|
||||
|
||||
if (connectWIFI) {
|
||||
connectToWifi();
|
||||
}
|
||||
|
||||
updateOLED2("Warming up the", "sensors.", "");
|
||||
|
||||
Serial.println(SGP.begin());
|
||||
SGP.GenericReset();
|
||||
|
||||
ag.CO2_Init();
|
||||
ag.PMS_Init();
|
||||
ag.TMP_RH_Init(0x44);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
currentMillis = millis();
|
||||
updateTVOC();
|
||||
updateOLED();
|
||||
updateCo2();
|
||||
updatePm25();
|
||||
updateTempHum();
|
||||
sendToServer();
|
||||
}
|
||||
|
||||
void updateTVOC()
|
||||
{
|
||||
if (currentMillis - previousTVOC >= tvocInterval) {
|
||||
previousTVOC += tvocInterval;
|
||||
SGP.measure(true);
|
||||
TVOC = SGP.getTVOC();
|
||||
Serial.println(String(TVOC));
|
||||
}
|
||||
}
|
||||
|
||||
void updateCo2()
|
||||
{
|
||||
if (currentMillis - previousCo2 >= co2Interval) {
|
||||
previousCo2 += co2Interval;
|
||||
Co2 = ag.getCO2_Raw();
|
||||
Serial.println(String(Co2));
|
||||
}
|
||||
}
|
||||
|
||||
void updatePm25()
|
||||
{
|
||||
if (currentMillis - previousPm25 >= pm25Interval) {
|
||||
previousPm25 += pm25Interval;
|
||||
pm25 = ag.getPM2_Raw();
|
||||
Serial.println(String(pm25));
|
||||
}
|
||||
}
|
||||
|
||||
void updateTempHum()
|
||||
{
|
||||
if (currentMillis - previousTempHum >= tempHumInterval) {
|
||||
previousTempHum += tempHumInterval;
|
||||
TMP_RH result = ag.periodicFetchData();
|
||||
temp = result.t;
|
||||
hum = result.rh;
|
||||
Serial.println(String(temp));
|
||||
}
|
||||
}
|
||||
|
||||
void updateOLED() {
|
||||
if (currentMillis - previousOled >= oledInterval) {
|
||||
previousOled += oledInterval;
|
||||
|
||||
String ln3;
|
||||
String ln1 = "PM:" + String(pm25) + " CO2:" + String(Co2);
|
||||
String ln2 = "AQI:" + String(PM_TO_AQI_US(pm25)) + " TVOC:" + String(TVOC);
|
||||
|
||||
if (inF) {
|
||||
ln3 = "F:" + String((temp* 9 / 5) + 32) + " H:" + String(hum)+"%";
|
||||
} else {
|
||||
ln3 = "C:" + String(temp) + " H:" + String(hum)+"%";
|
||||
}
|
||||
updateOLED2(ln1, ln2, ln3);
|
||||
}
|
||||
}
|
||||
|
||||
void updateOLED2(String ln1, String ln2, String ln3) {
|
||||
char buf[9];
|
||||
u8g2.firstPage();
|
||||
u8g2.firstPage();
|
||||
do {
|
||||
u8g2.setFont(u8g2_font_t0_16_tf);
|
||||
u8g2.drawStr(1, 10, String(ln1).c_str());
|
||||
u8g2.drawStr(1, 30, String(ln2).c_str());
|
||||
u8g2.drawStr(1, 50, String(ln3).c_str());
|
||||
} while ( u8g2.nextPage() );
|
||||
}
|
||||
|
||||
void sendToServer() {
|
||||
if (currentMillis - previoussendToServer >= sendToServerInterval) {
|
||||
previoussendToServer += sendToServerInterval;
|
||||
String payload = "{\"wifi\":" + String(WiFi.RSSI())
|
||||
+ ", \"rco2\":" + String(Co2)
|
||||
+ ", \"pm02\":" + String(pm25)
|
||||
+ ", \"tvoc\":" + String(TVOC)
|
||||
+ ", \"atmp\":" + String(temp)
|
||||
+ ", \"rhum\":" + String(hum)
|
||||
+ "}";
|
||||
|
||||
if(WiFi.status()== WL_CONNECTED){
|
||||
Serial.println(payload);
|
||||
String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(), HEX) + "/measures";
|
||||
Serial.println(POSTURL);
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
http.begin(client, POSTURL);
|
||||
http.addHeader("content-type", "application/json");
|
||||
int httpCode = http.POST(payload);
|
||||
String response = http.getString();
|
||||
Serial.println(httpCode);
|
||||
Serial.println(response);
|
||||
http.end();
|
||||
}
|
||||
else {
|
||||
Serial.println("WiFi Disconnected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wifi Manager
|
||||
void connectToWifi() {
|
||||
WiFiManager wifiManager;
|
||||
//WiFi.disconnect(); //to delete previous saved hotspot
|
||||
String HOTSPOT = "AG-" + String(ESP.getChipId(), HEX);
|
||||
updateOLED2("60s to connect", "to Wifi Hotspot", HOTSPOT);
|
||||
wifiManager.setTimeout(60);
|
||||
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
|
||||
updateOLED2("booting into", "offline mode", "");
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(6000);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate PM2.5 US AQI
|
||||
int PM_TO_AQI_US(int pm02) {
|
||||
if (pm02 <= 12.0) return ((50 - 0) / (12.0 - .0) * (pm02 - .0) + 0);
|
||||
else if (pm02 <= 35.4) return ((100 - 50) / (35.4 - 12.0) * (pm02 - 12.0) + 50);
|
||||
else if (pm02 <= 55.4) return ((150 - 100) / (55.4 - 35.4) * (pm02 - 35.4) + 100);
|
||||
else if (pm02 <= 150.4) return ((200 - 150) / (150.4 - 55.4) * (pm02 - 55.4) + 150);
|
||||
else if (pm02 <= 250.4) return ((300 - 200) / (250.4 - 150.4) * (pm02 - 150.4) + 200);
|
||||
else if (pm02 <= 350.4) return ((400 - 300) / (350.4 - 250.4) * (pm02 - 250.4) + 300);
|
||||
else if (pm02 <= 500.4) return ((500 - 400) / (500.4 - 350.4) * (pm02 - 350.4) + 400);
|
||||
else return 500;
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
#include <AirGradient.h>
|
||||
AirGradient ag = AirGradient();
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
ag.MHZ19_Init(MHZ19B);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
int MHZ19_C02 = ag.readMHZ19();
|
||||
Serial.print("C02: ");
|
||||
Serial.println(MHZ19_C02);
|
||||
|
||||
delay(5000);
|
||||
}
|
380
examples/MINI_DISPLAY/MINI_DISPLAY.ino
Normal file
380
examples/MINI_DISPLAY/MINI_DISPLAY.ino
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
This is the code for the AirGradient DIY Mini Display with an ESP8266 Microcontroller.
|
||||
It can be configures to show the outside air quality as well as one indoor location from the AirGradient platform.
|
||||
|
||||
For build instructions please visit
|
||||
|
||||
https://www.airgradient.com/open-airgradient/blog/airgradient-diy-display/
|
||||
|
||||
The codes needs the following libraries installed:
|
||||
"WifiManager by tzapu, tablatronix" tested with Version 2.0.5-alpha
|
||||
"Adafruit_ILI9341" tested with Version 1.5.10
|
||||
"Adafruit GFX library" tested with Version 1.10.12 (often automatically installed with above ILI9341 library)
|
||||
"ArduinoJSON" by Benoit Blanchon tested with Version 6.18.5
|
||||
|
||||
Configuration:
|
||||
Please set in the code below (line 90-) if you want to display the PM2.5 values in US AQI and temperature in F.
|
||||
|
||||
If you have any questions please visit our forum at https://forum.airgradient.com/
|
||||
|
||||
|
||||
If you are a school or university contact us for a free trial on the AirGradient platform.
|
||||
https://www.airgradient.com/
|
||||
|
||||
MIT License
|
||||
*/
|
||||
|
||||
#include <WiFiManager.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
#include <Adafruit_GFX.h>
|
||||
|
||||
#include <Adafruit_ILI9341.h>
|
||||
|
||||
#include <Fonts/FreeSans9pt7b.h>
|
||||
|
||||
#include <Fonts/FreeSans12pt7b.h>
|
||||
|
||||
#include <Fonts/FreeSans18pt7b.h>
|
||||
|
||||
#define TFT_CS D0
|
||||
#define TFT_DC D8
|
||||
#define TFT_RST - 1
|
||||
#define TS_CS D3
|
||||
|
||||
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
|
||||
|
||||
const char * locNameInside;
|
||||
const char * locNameOutside;
|
||||
|
||||
const char * place_timezone;
|
||||
const char * location;
|
||||
bool outdoor_offline;
|
||||
bool indoor_offline;
|
||||
const char * outdoor_policy;
|
||||
const char * outdoor_date;
|
||||
const char * indoor_date;
|
||||
boolean prodMode = true;
|
||||
|
||||
String deviceID;
|
||||
const char * timex;
|
||||
int pm02;
|
||||
int pi02;
|
||||
int pi02_outside;
|
||||
int rco2;
|
||||
float atmp;
|
||||
float atmp_outside;
|
||||
int rhum_outside;
|
||||
int rhum;
|
||||
int heat;
|
||||
|
||||
const char * pi02_color;
|
||||
const char * pi02_color_outside;
|
||||
const char * pi02_category;
|
||||
const char * pm02_color;
|
||||
const char * pm02_category;
|
||||
const char * rco2_color;
|
||||
const char * rco2_category;
|
||||
const char * heat_color;
|
||||
const char * heat_color_outside;
|
||||
const char * heat_category;
|
||||
|
||||
// Configuration
|
||||
#define API_ROOT "http://hw.airgradient.com/displays/"
|
||||
boolean inUSaqi = false;
|
||||
boolean inF = false;
|
||||
|
||||
String getDeviceId() {
|
||||
return String(ESP.getChipId(), HEX);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Chip ID");
|
||||
Serial.println(String(ESP.getChipId(), HEX));
|
||||
|
||||
tft.begin();
|
||||
tft.setRotation(2);
|
||||
while (!Serial && (millis() <= 1000));
|
||||
welcomeMessage();
|
||||
connectToWifi();
|
||||
|
||||
Serial.print("Connecting");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
tft.fillScreen(ILI9341_BLACK);
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
http.begin(client, API_ROOT + getDeviceId());
|
||||
|
||||
int httpCode = http.GET();
|
||||
if (httpCode == 200) {
|
||||
String airData = http.getString();
|
||||
payloadToDataInside(airData);
|
||||
Serial.print("airData1 : ");
|
||||
Serial.println(airData);
|
||||
} else {
|
||||
Serial.println("error");
|
||||
Serial.println(httpCode);
|
||||
}
|
||||
http.end();
|
||||
|
||||
delay(1000);
|
||||
updateDisplay();
|
||||
|
||||
delay(120000);
|
||||
tft.fillScreen(ILI9341_BLACK);
|
||||
tft.setTextColor(ILI9341_WHITE);
|
||||
tft.setFont( & FreeSans12pt7b);
|
||||
tft.setCursor(5, 20);
|
||||
tft.println("requesting data...");
|
||||
}
|
||||
|
||||
void payloadToDataInside(String payload) {
|
||||
const size_t capacity = JSON_ARRAY_SIZE(1) + 2 * JSON_OBJECT_SIZE(2) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(10) + JSON_OBJECT_SIZE(13) + 530;
|
||||
DynamicJsonBuffer jsonBuffer(capacity);
|
||||
JsonObject & root = jsonBuffer.parseObject(payload);
|
||||
location = root["place"]["name"];
|
||||
place_timezone = root["place"]["timezone"];
|
||||
JsonObject & outdoor = root["outdoor"];
|
||||
locNameOutside = outdoor["name"];
|
||||
outdoor_offline = outdoor["offline"];
|
||||
outdoor_policy = outdoor["guidelines"][0]["title"];
|
||||
JsonObject & outdoor_current = outdoor["current"];
|
||||
|
||||
atmp_outside = outdoor_current["atmp"];
|
||||
rhum_outside = outdoor_current["rhum"];
|
||||
outdoor_date = outdoor_current["date"];
|
||||
JsonObject & indoor = root["indoor"];
|
||||
locNameInside = indoor["name"];
|
||||
indoor_offline = indoor["offline"];
|
||||
JsonObject & indoor_current = indoor["current"];
|
||||
|
||||
atmp = indoor_current["atmp"];
|
||||
rhum = indoor_current["rhum"];
|
||||
rco2 = indoor_current["rco2"];
|
||||
indoor_date = indoor_current["date"];
|
||||
rco2_color = indoor_current["rco2_clr"];
|
||||
rco2_category = indoor_current["rco2_lbl"];
|
||||
|
||||
if (inUSaqi) {
|
||||
pi02_outside = outdoor_current["pi02"];
|
||||
pi02_color_outside = outdoor_current["pi02_clr"];
|
||||
pi02_category = outdoor_current["pi02_lbl"];
|
||||
pi02 = indoor_current["pi02"];
|
||||
pi02_color = indoor_current["pi02_clr"];
|
||||
pi02_category = indoor_current["pi02_lbl"];
|
||||
} else {
|
||||
pi02_outside = outdoor_current["pm02"];
|
||||
pi02_color_outside = outdoor_current["pm02_clr"];
|
||||
pi02_category = outdoor_current["pm02_lbl"];
|
||||
pi02 = indoor_current["pm02"];
|
||||
pi02_color = indoor_current["pm02_clr"];
|
||||
pi02_category = indoor_current["pm02_lbl"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void updateDisplay() {
|
||||
int y = 25;
|
||||
int boxHeight = 75;
|
||||
int boxWidth = 110;
|
||||
int radius = 8;
|
||||
tft.fillScreen(ILI9341_BLACK);
|
||||
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
|
||||
tft.setCursor(5, y);
|
||||
tft.println(location);
|
||||
|
||||
tft.drawLine(0, 35, 250, 35, ILI9341_WHITE);
|
||||
|
||||
y = y + 50;
|
||||
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
|
||||
tft.setCursor(5, y);
|
||||
tft.println(locNameOutside);
|
||||
tft.setFont( & FreeSans12pt7b);
|
||||
|
||||
y = y + 12;
|
||||
|
||||
if (String(pi02_color_outside) == "green") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_GREEN);
|
||||
} else if (String(pi02_color_outside) == "yellow") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_YELLOW);
|
||||
} else if (String(pi02_color_outside) == "orange") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_ORANGE);
|
||||
} else if (String(pi02_color_outside) == "red") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_RED);
|
||||
} else if (String(pi02_color_outside) == "purple") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_PURPLE);
|
||||
} else if (String(pi02_color_outside) == "brown") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_MAROON);
|
||||
}
|
||||
|
||||
if (String(heat_color_outside) == "green") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_GREEN);
|
||||
} else if (String(heat_color_outside) == "yellow") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_YELLOW);
|
||||
} else if (String(heat_color_outside) == "orange") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_ORANGE);
|
||||
} else if (String(heat_color_outside) == "red") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_RED);
|
||||
} else if (String(heat_color_outside) == "purple") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_PURPLE);
|
||||
} else if (String(heat_color_outside) == "brown") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_MAROON);
|
||||
}
|
||||
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
tft.setTextColor(ILI9341_BLACK, ILI9341_BLACK);
|
||||
tft.setCursor(20, y + boxHeight - 10);
|
||||
|
||||
if (inUSaqi) {
|
||||
tft.println("US AQI");
|
||||
} else {
|
||||
tft.println("ug/m3");
|
||||
}
|
||||
|
||||
tft.setFont( & FreeSans18pt7b);
|
||||
tft.setTextColor(ILI9341_BLACK, ILI9341_BLACK);
|
||||
tft.setCursor(20, y + 40);
|
||||
tft.println(String(pi02_outside));
|
||||
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
|
||||
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
|
||||
|
||||
tft.setCursor(20 + boxWidth + 10, y + 20);
|
||||
|
||||
if (inF) {
|
||||
tft.println(String((atmp_outside * 9 / 5) + 32) + "F");
|
||||
} else {
|
||||
tft.println(String(atmp_outside) + "C");
|
||||
}
|
||||
|
||||
tft.setCursor(20 + boxWidth + 10, y + 40);
|
||||
tft.println(String(rhum_outside) + "%");
|
||||
|
||||
tft.setTextColor(ILI9341_DARKGREY, ILI9341_BLACK);
|
||||
tft.setCursor(20 + boxWidth + 10, y + 60);
|
||||
tft.println(String(outdoor_date));
|
||||
|
||||
//inside
|
||||
|
||||
y = y + 110;
|
||||
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
|
||||
tft.setCursor(5, y);
|
||||
tft.println(locNameInside);
|
||||
tft.setFont( & FreeSans12pt7b);
|
||||
|
||||
y = y + 12;
|
||||
|
||||
if (String(pi02_color) == "green") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_GREEN);
|
||||
} else if (String(pi02_color) == "yellow") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_YELLOW);
|
||||
} else if (String(pi02_color) == "orange") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_ORANGE);
|
||||
} else if (String(pi02_color) == "red") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_RED);
|
||||
} else if (String(pi02_color) == "purple") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_PURPLE);
|
||||
} else if (String(pi02_color) == "brown") {
|
||||
tft.fillRoundRect(5, y, boxWidth, boxHeight, radius, ILI9341_MAROON);
|
||||
}
|
||||
|
||||
if (String(rco2_color) == "green") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_GREEN);
|
||||
} else if (String(rco2_color) == "yellow") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_YELLOW);
|
||||
} else if (String(rco2_color) == "orange") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_ORANGE);
|
||||
} else if (String(rco2_color) == "red") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_RED);
|
||||
} else if (String(rco2_color) == "purple") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_PURPLE);
|
||||
} else if (String(rco2_color) == "brown") {
|
||||
tft.fillRoundRect(5 + boxWidth + 10, y, boxWidth, boxHeight, radius, ILI9341_MAROON);
|
||||
}
|
||||
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
tft.setTextColor(ILI9341_BLACK, ILI9341_BLACK);
|
||||
tft.setCursor(20, y + boxHeight - 10);
|
||||
|
||||
if (inUSaqi) {
|
||||
tft.println("US AQI");
|
||||
} else {
|
||||
tft.println("ug/m3");
|
||||
}
|
||||
|
||||
tft.setCursor(20 + boxWidth + 10, y + boxHeight - 10);
|
||||
tft.println("CO2 ppm");
|
||||
|
||||
tft.setFont( & FreeSans18pt7b);
|
||||
tft.setTextColor(ILI9341_BLACK, ILI9341_BLACK);
|
||||
tft.setCursor(20, y + 40);
|
||||
tft.println(String(pi02));
|
||||
tft.setCursor(20 + boxWidth + 10, y + 40);
|
||||
tft.println(String(rco2));
|
||||
|
||||
y = y + 100;
|
||||
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
tft.setTextColor(ILI9341_DARKGREY, ILI9341_BLACK);
|
||||
tft.setCursor(boxWidth - 30, y);
|
||||
tft.println(String(indoor_date));
|
||||
}
|
||||
|
||||
void welcomeMessage() {
|
||||
Serial.println("Welcome Message 2");
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
tft.fillScreen(ILI9341_BLACK);
|
||||
tft.setTextColor(ILI9341_WHITE);
|
||||
|
||||
tft.setCursor(40, 24);
|
||||
tft.setFont( & FreeSans12pt7b);
|
||||
tft.setCursor(5, 20);
|
||||
tft.println("AirGradient");
|
||||
|
||||
tft.setFont( & FreeSans9pt7b);
|
||||
tft.setCursor(5, 100);
|
||||
tft.println("id: " + String(ESP.getChipId(), HEX));
|
||||
|
||||
tft.setCursor(5, 140);
|
||||
tft.println("connecting ...");
|
||||
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void connectToWifi() {
|
||||
delay(2000);
|
||||
|
||||
WiFiManager wifiManager;
|
||||
//chWiFi.disconnect(); //to delete previous saved hotspot
|
||||
String HOTSPOT = "AIRGRADIENT-DISPLAY-" + String(ESP.getChipId(), HEX);
|
||||
wifiManager.setTimeout(120);
|
||||
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(3000);
|
||||
ESP.restart();
|
||||
delay(5000);
|
||||
}
|
||||
}
|
@ -1,16 +1,54 @@
|
||||
/*
|
||||
This is the code for the AirGradient DIY Air Quality Sensor with an ESP8266 Microcontroller.
|
||||
|
||||
It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi.
|
||||
|
||||
For build instructions please visit https://www.airgradient.com/open-airgradient/instructions/
|
||||
|
||||
Compatible with the following sensors:
|
||||
Plantower PMS5003 (Fine Particle Sensor)
|
||||
|
||||
Please install ESP8266 board manager (tested with version 3.0.0)
|
||||
|
||||
If you have any questions please visit our forum at https://forum.airgradient.com/
|
||||
|
||||
If you are a school or university contact us for a free trial on the AirGradient platform.
|
||||
https://www.airgradient.com/
|
||||
|
||||
Kits with all required components are available at https://www.airgradient.com/open-airgradient/shop/
|
||||
|
||||
MIT License
|
||||
*/
|
||||
|
||||
#include <AirGradient.h>
|
||||
|
||||
AirGradient ag = AirGradient();
|
||||
|
||||
void setup(){
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
ag.PMS_Init();
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
int PM2 = ag.getPM2_Raw();
|
||||
Serial.print("PM2: ");
|
||||
Serial.println(ag.getPM2());
|
||||
void loop() {
|
||||
|
||||
delay(5000);
|
||||
int PM2 = ag.getPM2_Raw();
|
||||
|
||||
Serial.print("PM2.5 in ug/m3: ");
|
||||
Serial.println(String(PM2));
|
||||
|
||||
Serial.print("PM2.5 in US AQI: ");
|
||||
Serial.println(String(PM_TO_AQI_US(PM2)));
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
int PM_TO_AQI_US(int pm02) {
|
||||
if (pm02 <= 12.0) return ((50 - 0) / (12.0 - .0) * (pm02 - .0) + 0);
|
||||
else if (pm02 <= 35.4) return ((100 - 50) / (35.4 - 12.0) * (pm02 - 12.0) + 50);
|
||||
else if (pm02 <= 55.4) return ((150 - 100) / (55.4 - 35.4) * (pm02 - 35.4) + 100);
|
||||
else if (pm02 <= 150.4) return ((200 - 150) / (150.4 - 55.4) * (pm02 - 55.4) + 150);
|
||||
else if (pm02 <= 250.4) return ((300 - 200) / (250.4 - 150.4) * (pm02 - 150.4) + 200);
|
||||
else if (pm02 <= 350.4) return ((400 - 300) / (350.4 - 250.4) * (pm02 - 250.4) + 300);
|
||||
else if (pm02 <= 500.4) return ((500 - 400) / (500.4 - 350.4) * (pm02 - 350.4) + 400);
|
||||
else return 500;
|
||||
};
|
||||
|
@ -1,3 +1,25 @@
|
||||
/*
|
||||
This is the code for the AirGradient DIY Air Quality Sensor with an ESP8266 Microcontroller.
|
||||
|
||||
It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi.
|
||||
|
||||
For build instructions please visit https://www.airgradient.com/open-airgradient/instructions/
|
||||
|
||||
Compatible with the following sensors:
|
||||
SHT30/31 (Temperature/Humidity Sensor)
|
||||
|
||||
Please install ESP8266 board manager (tested with version 3.0.0)
|
||||
|
||||
If you are a school or university contact us for a free trial on the AirGradient platform.
|
||||
https://www.airgradient.com/
|
||||
|
||||
Kits with all required components are available at https://www.airgradient.com/open-airgradient/shop/
|
||||
|
||||
If you have any questions please visit our forum at https://forum.airgradient.com/
|
||||
|
||||
MIT License
|
||||
*/
|
||||
|
||||
#include <AirGradient.h>
|
||||
AirGradient ag = AirGradient();
|
||||
|
||||
@ -7,10 +29,17 @@ void setup(){
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
TMP_RH result = ag.periodicFetchData();
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(result.rh_char);
|
||||
Serial.print(" Temperature: ");
|
||||
Serial.println(result.t_char);
|
||||
|
||||
Serial.print("Relative Humidity in %: ");
|
||||
Serial.println(result.rh);
|
||||
|
||||
Serial.print(" Temperature in Celcius: ");
|
||||
Serial.println(result.t);
|
||||
|
||||
Serial.print(" Temperature in Fahrenheit: ");
|
||||
Serial.println((result.t * 9 / 5) + 32);
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
158
examples/TVOC/TVOC.ino
Normal file
158
examples/TVOC/TVOC.ino
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
This is the code for the AirGradient DIY Air Quality Sensor with an ESP8266 Microcontroller.
|
||||
|
||||
It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi.
|
||||
|
||||
For build instructions please visit https://www.airgradient.com/open-airgradient/instructions/
|
||||
|
||||
Instructions on using the TVOC sensor (SGP30) instead of the Temperature / Humidity sensor (SHT3x).
|
||||
|
||||
https://www.airgradient.com/open-airgradient/instructions/tvoc-on-airgradient-diy-sensor/
|
||||
|
||||
The codes needs the following libraries installed:
|
||||
"WifiManager by tzapu, tablatronix" tested with Version 2.0.3-alpha
|
||||
"ESP8266 and ESP32 OLED driver for SSD1306 displays by ThingPulse, Fabrice Weinberg" tested with Version 4.1.0
|
||||
"SGP30" by Rob Tillaart tested with Version 0.1.4
|
||||
|
||||
Configuration:
|
||||
Set in the code below which sensor you are using and if you want to connect it to WiFi.
|
||||
|
||||
If you have any questions please visit our forum at https://forum.airgradient.com/
|
||||
|
||||
If you are a school or university contact us for a free trial on the AirGradient platform.
|
||||
https://www.airgradient.com/
|
||||
|
||||
MIT License
|
||||
*/
|
||||
|
||||
#include "SGP30.h"
|
||||
SGP30 SGP;
|
||||
|
||||
#include <AirGradient.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
#include <Wire.h>
|
||||
#include "SSD1306Wire.h"
|
||||
|
||||
AirGradient ag = AirGradient();
|
||||
|
||||
SSD1306Wire display(0x3c, SDA, SCL);
|
||||
|
||||
WiFiClient client;
|
||||
|
||||
// set sensors that you do not use to false
|
||||
boolean hasPM=true;
|
||||
boolean hasCO2=true;
|
||||
boolean hasSHT=false;
|
||||
boolean hasTVOC=true;
|
||||
|
||||
// set to true if you want to connect to wifi. The display will show values only when the sensor has wifi connection
|
||||
boolean connectWIFI=true;
|
||||
|
||||
// change if you want to send the data to another server
|
||||
String APIROOT = "http://hw.airgradient.com/";
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
||||
display.init();
|
||||
display.flipScreenVertically();
|
||||
showTextRectangle("Init", String(ESP.getChipId(),HEX),true);
|
||||
|
||||
if (hasTVOC) SGP.begin();
|
||||
if (hasPM) ag.PMS_Init();
|
||||
if (hasCO2) ag.CO2_Init();
|
||||
if (hasSHT) ag.TMP_RH_Init(0x44);
|
||||
|
||||
if (connectWIFI) connectToWifi();
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
if (hasTVOC) SGP.measure(false);
|
||||
|
||||
// create payload
|
||||
|
||||
String payload = "{\"wifi\":" + String(WiFi.RSSI()) + ",";
|
||||
|
||||
if (hasPM) {
|
||||
int PM2 = ag.getPM2_Raw();
|
||||
payload=payload+"\"pm02\":" + String(PM2);
|
||||
showTextRectangle("PM2",String(PM2),false);
|
||||
delay(3000);
|
||||
}
|
||||
|
||||
if (hasTVOC) {
|
||||
if (hasPM) payload=payload+",";
|
||||
int TVOC = SGP.getTVOC();
|
||||
payload=payload+"\"tvoc\":" + String(TVOC);
|
||||
showTextRectangle("TVOC",String(TVOC),false);
|
||||
delay(3000);
|
||||
}
|
||||
|
||||
if (hasCO2) {
|
||||
if (hasTVOC) payload=payload+",";
|
||||
int CO2 = ag.getCO2_Raw();
|
||||
payload=payload+"\"rco2\":" + String(CO2);
|
||||
showTextRectangle("CO2",String(CO2),false);
|
||||
delay(3000);
|
||||
}
|
||||
|
||||
if (hasSHT) {
|
||||
if (hasCO2 || hasPM) payload=payload+",";
|
||||
TMP_RH result = ag.periodicFetchData();
|
||||
payload=payload+"\"atmp\":" + String(result.t) + ",\"rhum\":" + String(result.rh);
|
||||
showTextRectangle(String(result.t),String(result.rh)+"%",false);
|
||||
delay(3000);
|
||||
}
|
||||
|
||||
payload=payload+"}";
|
||||
|
||||
// send payload
|
||||
if (connectWIFI){
|
||||
Serial.println(payload);
|
||||
String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(),HEX) + "/measures";
|
||||
Serial.println(POSTURL);
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
http.begin(client, POSTURL);
|
||||
http.addHeader("content-type", "application/json");
|
||||
int httpCode = http.POST(payload);
|
||||
String response = http.getString();
|
||||
Serial.println(httpCode);
|
||||
Serial.println(response);
|
||||
http.end();
|
||||
}
|
||||
}
|
||||
|
||||
// DISPLAY
|
||||
void showTextRectangle(String ln1, String ln2, boolean small) {
|
||||
display.clear();
|
||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
if (small) {
|
||||
display.setFont(ArialMT_Plain_16);
|
||||
} else {
|
||||
display.setFont(ArialMT_Plain_24);
|
||||
}
|
||||
display.drawString(32, 16, ln1);
|
||||
display.drawString(32, 36, ln2);
|
||||
display.display();
|
||||
}
|
||||
|
||||
// Wifi Manager
|
||||
void connectToWifi(){
|
||||
WiFiManager wifiManager;
|
||||
//WiFi.disconnect(); //to delete previous saved hotspot
|
||||
String HOTSPOT = "AIRGRADIENT-"+String(ESP.getChipId(),HEX);
|
||||
wifiManager.setTimeout(120);
|
||||
if(!wifiManager.autoConnect((const char*)HOTSPOT.c_str())) {
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(3000);
|
||||
ESP.restart();
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
name=AirGradient Air Quality Sensor
|
||||
version=1.3.1
|
||||
version=2.0.0
|
||||
author=AirGradient <support@airgradient.com>
|
||||
maintainer=AirGradient <support@airgradient.com>
|
||||
sentence=ESP8266 library for an air quality sensor featuring PM2.5, CO2, Temperature and Humidity with OLED display.
|
||||
paragraph=The library is very robust and works with the Plantower PMS5003 particle sensor, the Senseair S8 CO2 sensor and the SHT30/31 sensor for humidity and temperature. You can also connect an OLED display or send the air quality data to the AirGradient platform or any other backend.
|
||||
paragraph=The library is very robust and works with the Plantower PMS5003 particle sensor, the Senseair S8 CO2 sensor and the SHT30/31 sensor for humidity and temperature. You can also connect an OLED display or send the air quality data to the AirGradient platform or any other backend. Kits with all components including a nice enclosure are available in our online shop.
|
||||
category=Sensors
|
||||
url=https://github.com/airgradienthq/arduino
|
||||
url=https://www.airgradient.com/open-airgradient/instructions/
|
||||
architectures=*
|
||||
|
41
readme.txt
41
readme.txt
@ -1,39 +1,8 @@
|
||||
This is an example C++ library for Arduino 0004+, based on one created by
|
||||
Nicholas Zambetti for Wiring 0006+
|
||||
AirGradient Arduino Library for ESP8266 (Wemos D1 MINI)
|
||||
=====================================================================================================
|
||||
|
||||
Installation
|
||||
--------------------------------------------------------------------------------
|
||||
Build your own low cost air quality sensor with optional display measuring PM2.5, CO2, Temperature and Humidity.
|
||||
|
||||
To install this library, just place this entire folder as a subfolder in your
|
||||
Arduino/lib/targets/libraries folder.
|
||||
|
||||
When installed, this library should look like:
|
||||
|
||||
Arduino/lib/targets/libraries/Test (this library's folder)
|
||||
Arduino/lib/targets/libraries/Test/Test.cpp (the library implementation file)
|
||||
Arduino/lib/targets/libraries/Test/Test.h (the library description file)
|
||||
Arduino/lib/targets/libraries/Test/keywords.txt (the syntax coloring file)
|
||||
Arduino/lib/targets/libraries/Test/examples (the examples in the "open" menu)
|
||||
Arduino/lib/targets/libraries/Test/readme.txt (this file)
|
||||
|
||||
Building
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
After this library is installed, you just have to start the Arduino application.
|
||||
You may see a few warning messages as it's built.
|
||||
|
||||
To use this library in a sketch, go to the Sketch | Import Library menu and
|
||||
select Test. This will add a corresponding line to the top of your sketch:
|
||||
#include <Test.h>
|
||||
|
||||
To stop using this library, delete that line from your sketch.
|
||||
|
||||
Geeky information:
|
||||
After a successful build of this library, a new file named "Test.o" will appear
|
||||
in "Arduino/lib/targets/libraries/Test". This file is the built/compiled library
|
||||
code.
|
||||
|
||||
If you choose to modify the code for this library (i.e. "Test.cpp" or "Test.h"),
|
||||
then you must first 'unbuild' this library by deleting the "Test.o" file. The
|
||||
new "Test.o" with your code will appear after the next press of "verify"
|
||||
This library makes it easy to read the sensor data from the Plantower PMS5003 PM2.5 sensor, the Senseair S8 and the SHT30/31 Temperature and Humidity sensor. Visit our DIY section for detailed build instructions and PCB layout.
|
||||
|
||||
https://www.airgradient.com/open-airgradient/instructions/
|
||||
|
Reference in New Issue
Block a user