Compare commits

...

9 Commits
1.3.5 ... 1.4.1

Author SHA1 Message Date
ed3b0ff53f corrected library version number 2021-12-08 10:11:45 +07:00
07e1b5e97a improved examples code 2021-12-08 09:59:32 +07:00
348ddba048 Merge pull request #4 from AlanBell/patch-1
Update AirGradient.cpp
2021-12-08 08:32:12 +07:00
a3c8054839 Merge pull request #8 from markasoftware/markasoftware/math-and-wificlient
correct math.h header and specify wificlient as per new http library requirement.
2021-12-08 08:31:26 +07:00
555693cda8 Merge pull request #12 from StrongholdIII/master
Added return to compile with platformIO
2021-12-08 08:30:14 +07:00
0a9f184946 added comment 2021-12-08 08:20:22 +07:00
7c02564ed4 Added return to compile with platformIO 2021-10-15 22:01:57 +02:00
0abc5629fc correct math.h header and specify wificlient as per new http library requirement 2021-05-29 00:04:15 -07:00
a40399d082 Update AirGradient.cpp
math.h should be lower case - otherwise won't compile on case sensitive platforms.
2021-01-02 16:18:36 +00:00
8 changed files with 663 additions and 49 deletions

View File

@ -303,7 +303,7 @@ TMP_RH AirGradient::periodicFetchData() //
return result; return result;
} }
else else
returnError(error); return returnError(error);
} }
TMP_RH_ErrorCode AirGradient::periodicStop() { TMP_RH_ErrorCode AirGradient::periodicStop() {

View File

@ -16,21 +16,30 @@ The codes needs the following libraries installed:
"WifiManager by tzapu, tablatronix" tested with Version 2.0.3-alpha "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 "ESP8266 and ESP32 OLED driver for SSD1306 displays by ThingPulse, Fabrice Weinberg" tested with Version 4.1.0
If you have any questions please visit our forum at https://forum.airgradient.com/
Configuration: Configuration:
Please set in the code below which sensor you are using and if you want to connect it to WiFi. Please set in the code below which sensor you are using and if you want to connect it to WiFi.
You can also switch PM2.5 from ug/m3 to US AQI and Celcius to Fahrenheit
If you are a school or university contact us for a free trial on the AirGradient platform. If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/schools/ https://www.airgradient.com/schools/
Kits with all required components are available at https://www.airgradient.com/diyshop/
MIT License MIT License
*/ */
#include <AirGradient.h> #include <AirGradient.h>
#include <WiFiManager.h> #include <WiFiManager.h>
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h> #include <ESP8266HTTPClient.h>
#include <Wire.h> #include <Wire.h>
#include "SSD1306Wire.h" #include "SSD1306Wire.h"
AirGradient ag = AirGradient(); AirGradient ag = AirGradient();
@ -38,22 +47,28 @@ AirGradient ag = AirGradient();
SSD1306Wire display(0x3c, SDA, SCL); SSD1306Wire display(0x3c, SDA, SCL);
// set sensors that you do not use to false // set sensors that you do not use to false
boolean hasPM=true; boolean hasPM = true;
boolean hasCO2=true; boolean hasCO2 = true;
boolean hasSHT=true; boolean hasSHT = true;
// set to true to switch PM2.5 from ug/m3 to US AQI
boolean inUSaqi = false;
// 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 // set to true if you want to connect to wifi. The display will show values only when the sensor has wifi connection
boolean connectWIFI=false; boolean connectWIFI = false;
// change if you want to send the data to another server // change if you want to send the data to another server
String APIROOT = "http://hw.airgradient.com/"; String APIROOT = "http://hw.airgradient.com/";
void setup(){ void setup() {
Serial.begin(9600); Serial.begin(9600);
display.init(); display.init();
display.flipScreenVertically(); display.flipScreenVertically();
showTextRectangle("Init", String(ESP.getChipId(),HEX),true); showTextRectangle("Init", String(ESP.getChipId(), HEX), true);
if (hasPM) ag.PMS_Init(); if (hasPM) ag.PMS_Init();
if (hasCO2) ag.CO2_Init(); if (hasCO2) ag.CO2_Init();
@ -63,7 +78,7 @@ void setup(){
delay(2000); delay(2000);
} }
void loop(){ void loop() {
// create payload // create payload
@ -71,43 +86,56 @@ void loop(){
if (hasPM) { if (hasPM) {
int PM2 = ag.getPM2_Raw(); int PM2 = ag.getPM2_Raw();
payload=payload+"\"pm02\":" + String(PM2); payload = payload + "\"pm02\":" + String(PM2);
showTextRectangle("PM2",String(PM2),false);
if (inUSaqi) {
showTextRectangle("AQI", String(PM_TO_AQI_US(PM2)), false);
} else {
showTextRectangle("PM2", String(PM2), false);
}
delay(3000); delay(3000);
} }
if (hasCO2) { if (hasCO2) {
if (hasPM) payload=payload+","; if (hasPM) payload = payload + ",";
int CO2 = ag.getCO2_Raw(); int CO2 = ag.getCO2_Raw();
payload=payload+"\"rco2\":" + String(CO2); payload = payload + "\"rco2\":" + String(CO2);
showTextRectangle("CO2",String(CO2),false); showTextRectangle("CO2", String(CO2), false);
delay(3000); delay(3000);
} }
if (hasSHT) { if (hasSHT) {
if (hasCO2 || hasPM) payload=payload+","; if (hasCO2 || hasPM) payload = payload + ",";
TMP_RH result = ag.periodicFetchData(); TMP_RH result = ag.periodicFetchData();
payload=payload+"\"atmp\":" + String(result.t) + ",\"rhum\":" + String(result.rh); payload = payload + "\"atmp\":" + String(result.t) + ",\"rhum\":" + String(result.rh);
showTextRectangle(String(result.t),String(result.rh)+"%",false);
if (inF) {
showTextRectangle(String((result.t * 9 / 5) + 32), String(result.rh) + "%", false);
} else {
showTextRectangle(String(result.t), String(result.rh) + "%", false);
}
delay(3000); delay(3000);
} }
payload=payload+"}"; payload = payload + "}";
// send payload // send payload
if (connectWIFI){ if (connectWIFI) {
Serial.println(payload); Serial.println(payload);
String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(),HEX) + "/measures"; String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(), HEX) + "/measures";
Serial.println(POSTURL); Serial.println(POSTURL);
WiFiClient client; WiFiClient client;
HTTPClient http; HTTPClient http;
http.begin(client, POSTURL); http.begin(client, POSTURL);
http.addHeader("content-type", "application/json"); http.addHeader("content-type", "application/json");
int httpCode = http.POST(payload); int httpCode = http.POST(payload);
String response = http.getString(); String response = http.getString();
Serial.println(httpCode); Serial.println(httpCode);
Serial.println(response); Serial.println(response);
http.end(); http.end();
} }
} }
@ -126,16 +154,28 @@ void showTextRectangle(String ln1, String ln2, boolean small) {
} }
// Wifi Manager // Wifi Manager
void connectToWifi(){ void connectToWifi() {
WiFiManager wifiManager; WiFiManager wifiManager;
//WiFi.disconnect(); //to delete previous saved hotspot //WiFi.disconnect(); //to delete previous saved hotspot
String HOTSPOT = "AIRGRADIENT-"+String(ESP.getChipId(),HEX); String HOTSPOT = "AIRGRADIENT-" + String(ESP.getChipId(), HEX);
wifiManager.setTimeout(120); wifiManager.setTimeout(120);
if(!wifiManager.autoConnect((const char*)HOTSPOT.c_str())) { if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
Serial.println("failed to connect and hit timeout"); Serial.println("failed to connect and hit timeout");
delay(3000); delay(3000);
ESP.restart(); ESP.restart();
delay(5000); delay(5000);
} }
} }
// 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;
};

View File

@ -10,9 +10,13 @@ SenseAir S8 (CO2 Sensor)
Please install ESP8266 board manager (tested with version 3.0.0) 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. If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/schools/ https://www.airgradient.com/schools/
Kits with all required components are available at https://www.airgradient.com/diyshop/
MIT License MIT License
*/ */

View File

@ -0,0 +1,381 @@
/*
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/resources/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/schools/
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);
}
}

View File

@ -10,25 +10,45 @@ Plantower PMS5003 (Fine Particle Sensor)
Please install ESP8266 board manager (tested with version 3.0.0) 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. If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/schools/ https://www.airgradient.com/schools/
Kits with all required components are available at https://www.airgradient.com/diyshop/
MIT License MIT License
*/ */
#include <AirGradient.h> #include <AirGradient.h>
AirGradient ag = AirGradient(); AirGradient ag = AirGradient();
void setup(){ void setup() {
Serial.begin(9600); Serial.begin(9600);
ag.PMS_Init(); ag.PMS_Init();
} }
void loop(){ void loop() {
int PM2 = ag.getPM2_Raw(); int PM2 = ag.getPM2_Raw();
Serial.print("PM2: ");
Serial.println(ag.getPM2());
delay(5000); 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;
};

View File

@ -13,6 +13,10 @@ 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. If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/schools/ https://www.airgradient.com/schools/
Kits with all required components are available at https://www.airgradient.com/diyshop/
If you have any questions please visit our forum at https://forum.airgradient.com/
MIT License MIT License
*/ */
@ -25,10 +29,17 @@ void setup(){
} }
void loop(){ void loop(){
TMP_RH result = ag.periodicFetchData(); TMP_RH result = ag.periodicFetchData();
Serial.print("Humidity: ");
Serial.print(result.rh_char); Serial.print("Relative Humidity in %: ");
Serial.print(" Temperature: "); Serial.println(result.rh);
Serial.println(result.t_char);
Serial.print(" Temperature in Celcius: ");
Serial.println(result.t);
Serial.print(" Temperature in Fahrenheit: ");
Serial.println((result.t * 9 / 5) + 32);
delay(5000); delay(5000);
} }

158
examples/TVOC/TVOC.ino Normal file
View 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/diy/
Instructions on using the TVOC sensor (SGP30) instead of the Temperature / Humidity sensor (SHT3x).
https://www.airgradient.com/resources/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:
Please 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/schools/
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);
}
}

View File

@ -1,5 +1,5 @@
name=AirGradient Air Quality Sensor name=AirGradient Air Quality Sensor
version=1.3.5 version=1.4.1
author=AirGradient <support@airgradient.com> author=AirGradient <support@airgradient.com>
maintainer=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. sentence=ESP8266 library for an air quality sensor featuring PM2.5, CO2, Temperature and Humidity with OLED display.