Air Quality Monitoring
Create a real-time air quality monitoring system capable of reading air quality, temperature, and humidity data with the Nicla Sense Env and displaying it on a GIGA Display Shield!
Components and supplies
1
Nicla Sense Env
1
Arduino GIGA Display Bundle
Apps and platforms
1
Arduino IDE
Project description
Code
AirQualitySketch
c
AirQuality.ino
1//Uncomment only one of the following lines to select your display. 2//#define USE_ILI9341 //2.4 inch 320x240 TFT Feather Wing 3//#define USE_HX8357 //3.5 inch 480x320 TFT Feather Wing 4//#define USE_HALLOWING //Adafruit Hallowing M0 Express 5//#define USE_PYGAMER //Adafruit PyGamer M4 Express 6#define USE_GIGA_GFX //Arduino Giga R1 with display 7//#define USE_MCUFRIEND // 2.8 inch 240x320 MCUFRIEND displays 8#include "board_select.h" 9 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13 14// Example program for font collections. Shows mixed font strings, 15// and the use of print() and getTextBound() on them. 16 17#include "FontCollection.h" 18 19// Uses libraries: 20// Any graphics library inheriting from Adafruit 21 22// Text and UI symbol fonts go into a font collection. 23// This one is for 18pt Sans 24#include <fonts/FreeSans18pt7b.h> 25#include <fonts/UISymbolSans18pt7b.h> 26FontCollection fc18(&display, &FreeSans18pt7b, &UISymbolSans18pt7b, 1, 1); 27 28// This one is for 12pt Sans; too small on Giga but useful on the smaller displays 29#include <fonts/FreeSans12pt7b.h> 30#include <fonts/UISymbolSans12pt7b.h> 31FontCollection fc12(&display, &FreeSans12pt7b, &UISymbolSans12pt7b, 1, 1); 32 33// This one is for 24pt Sans 34#include <fonts/FreeSans24pt7b.h> 35#include <fonts/UISymbolSans24pt7b.h> 36FontCollection fc24(&display, &FreeSans24pt7b, &UISymbolSans24pt7b, 1, 1); 37 38// Colours in RGB565. 39#define CYAN (uint16_t)0x07FF 40#define RED (uint16_t)0xf800 41#define BLUE (uint16_t)0x001F 42#define GREEN (uint16_t)0x07E0 43#define MAGENTA (uint16_t)0xF81F 44#define WHITE (uint16_t)0xffff 45#define BLACK (uint16_t)0x0000 46#define YELLOW (uint16_t)0xFFE0 47#define GREY (uint16_t)display.color565(0x7F, 0x7F, 0x7F) 48#define DKGREY (uint16_t)display.color565(0x3F, 0x3F, 0x3F) 49 50// Define color 51#define FONT_COLOR YELLOW 52 53// Define Refresh rate 54#define REFRESH_RATE_S 10 55 56// Define if use or not splash screen (Arduino logo) 57//#define LOGO 58 59// Select font 60#define MEDIUM_FONT 61//#define BIG_FONT 62 63#ifdef MEDIUM_FONT 64 #define X_HOME 20 65 #define Y_HOME 50 66 67 #define X_TAB 480 68 #define Y_TAB 100 69#endif 70 71#ifdef BIG_FONT 72 #define X_HOME 20 73 #define Y_HOME 20 74 75 #define X_TAB 590 76 #define Y_TAB 120 77#endif 78 79// Include the NiclaSenseEnv library 80#include "NiclaSenseEnv.h" 81 82typedef enum 83{ 84 AIR_QUALITY_VIEW, 85 TEMP_HUM_VIEW 86} ViewType; 87 88// Global device object for Nicla Sense Env 89NiclaSenseEnv device; 90 91// Global variables 92int16_t x = 20, y = 20; 93int16_t xr, yr; 94uint16_t wr, hr; 95 96// Air quality variables 97float AirQuality; 98float CO2; 99float TVOC; 100 101// T&H variables 102float Temp; 103float Hum; 104 105// View 106ViewType View = AIR_QUALITY_VIEW; 107 108// Air quality strings 109char AirQuality_s[5]; 110char CO2_s[5]; 111char TVOC_s[5]; 112 113// T&H strings 114char Temp_s[5]; 115char Hum_s[5]; 116 117/** 118 Displays air quality data from the ZMOD4410 sensor. 119 @param sensor Reference to IndoorAirQualitySensor object controlling the sensor. 120*/ 121void displayAqSensorData(IndoorAirQualitySensor& sensor) { 122 if (sensor.enabled()) { 123 Serial.print("- Indoor air quality value: "); 124 Serial.println(sensor.airQuality()); 125 Serial.print("- CO2 (ppm): "); 126 Serial.println(sensor.CO2()); 127 Serial.print("- TVOC (mg/m3): "); 128 Serial.println(sensor.TVOC()); 129 Serial.print("- Ethanol (ppm): "); 130 Serial.println(sensor.ethanol()); 131 Serial.println(""); 132 } else { 133 Serial.println("- Indoor air quality sensor is disabled!"); 134 } 135} 136 137/** 138 Displays temperature and humidity data from the HS4001 sensor. 139 @param sensor Reference to TemperatureHumiditySensor object controlling the sensor. 140*/ 141void displayThSensorData(TemperatureHumiditySensor& sensor) { 142 if (sensor.enabled()) { 143 float temperature = sensor.temperature(); 144 if (isnan(temperature)) { 145 Serial.println("- Temperature: N/A"); 146 } else { 147 Serial.print("- Temperature: "); 148 Serial.print(temperature, 2); 149 Serial.println(" °C"); 150 } 151 Serial.print("- Relative humidity: "); 152 Serial.print(sensor.humidity(), 2); 153 Serial.println(" %"); 154 Serial.println(""); 155 } else { 156 Serial.println("- Temperature sensor is disabled!"); 157 } 158} 159 160#ifdef LOGO 161#include "Arduino_H7_Video.h" 162#include "ArduinoGraphics.h" 163 164Arduino_H7_Video Display(800, 480, GigaDisplayShield); 165#endif 166 167void setup() 168{ 169#ifdef LOGO 170 171 172 delay(5000); 173#endif 174 175 // Initialize serial communication and wait up to 2.5 seconds for a connection 176 Serial.begin(115200); 177 for (auto startNow = millis() + 2500; !Serial && millis() < startNow; delay(500)); 178 179 if (device.begin()) { 180 Serial.println("- Device is connected!"); 181 auto airQualitySensor = device.indoorAirQualitySensor(); 182 183 // Set the sensor mode to indoor air quality 184 airQualitySensor.setMode(IndoorAirQualitySensorMode::indoorAirQuality); 185 186 // The ZMOD4410 can take a sample every 3 seconds in IAQ mode and requires 60 warm-up samples, 187 // meaning the sensor will take about 3 minutes to fully warm-up before accurate readings can 188 // be obtained. In this example, we allow 5 seconds for the sensor to start delivering data. 189 delay(5000); 190 } else { 191 Serial.println("- Device could not be found. Please double-check the wiring!"); 192 } 193 194 // Init display 195 Initialize_Display(); 196} 197 198void loop() 199{ 200 /* ****************************** AQ MODE ****************************** */ 201 if (View == AIR_QUALITY_VIEW) 202 { 203 View = TEMP_HUM_VIEW; 204 // Read data from the ZMOD4410 sensor 205 auto airQualitySensor = device.indoorAirQualitySensor(); 206 displayAqSensorData(airQualitySensor); 207 208 // Fill variables 209 if (airQualitySensor.enabled()) 210 { 211 AirQuality = airQualitySensor.airQuality(); 212 CO2 = airQualitySensor.CO2(); 213 TVOC = airQualitySensor.TVOC(); 214 } 215 else 216 { 217 AirQuality = 0; 218 CO2 = 0; 219 TVOC = 0; 220 } 221 222 // Convert data 223 sprintf(AirQuality_s, "%.2f", AirQuality); 224 sprintf(CO2_s, "%.0f", CO2); 225 sprintf(TVOC_s, "%.2f", TVOC); 226 227 /************************** Plot data **************************/ 228 229 display.fillScreen(0); 230 231 // Reset coordinates 232 x = X_HOME; 233 y = Y_HOME; 234 235#ifdef MEDIUM_FONT 236 fc24.drawText("AIR QUALITY DATA (ZMOD4410):", x, y, FONT_COLOR); 237 y += Y_TAB/2; 238 fc24.drawText("----------------------------------------------", x, y, FONT_COLOR); 239 y += Y_TAB; 240 fc24.drawText("Air quality index:", x, y, FONT_COLOR); 241 fc24.drawText(AirQuality_s, (x + X_TAB), y, FONT_COLOR); 242 243 y += Y_TAB; 244 fc24.drawText("CO2 [ppm]:", x, y, FONT_COLOR); 245 fc24.drawText(CO2_s, (x + X_TAB), y, FONT_COLOR); 246 247 y += Y_TAB; 248 fc24.drawText("TVOC [mg/m3]:", x, y, FONT_COLOR); 249 fc24.drawText(TVOC_s, (x + X_TAB), y, FONT_COLOR); 250#endif 251 252#ifdef BIG_FONT 253 y += Y_TAB; 254 fc24.drawText("Air quality:", x, y, FONT_COLOR, 2); 255 fc24.drawText(AirQuality_s, (x + X_TAB), y, FONT_COLOR, 2); 256 257 y += Y_TAB; 258 fc24.drawText("CO2(ppm):", x, y, FONT_COLOR, 2); 259 fc24.drawText(CO2_s, (x + X_TAB), y, FONT_COLOR, 2); 260 261 y += Y_TAB; 262 fc24.drawText("Tvoc(mg/m3):", x, y, FONT_COLOR, 2); 263 fc24.drawText(TVOC_s, (x + X_TAB), y, FONT_COLOR, 2); 264#endif 265 266 delay(REFRESH_RATE_S*1000); 267 } 268 269 /* ****************************** T&H MODE ****************************** */ 270 else if (View == TEMP_HUM_VIEW) 271 { 272 View = AIR_QUALITY_VIEW; 273 // Read data from the HS4001 sensor 274 auto ThSensor = device.temperatureHumiditySensor(); 275 displayThSensorData(ThSensor); 276 277 // Fill variables 278 if (ThSensor.enabled()) 279 { 280 Temp = ThSensor.temperature(); 281 Hum = ThSensor.humidity(); 282 283 } 284 else 285 { 286 Temp = 0; 287 Hum = 0; 288 } 289 290 // Convert data 291 sprintf(Temp_s, "%.0f", Temp); 292 sprintf(Hum_s, "%.2f", Hum); 293 294 /************************** Plot data **************************/ 295 296 display.fillScreen(0); 297 298 // Reset coordinates 299 x = X_HOME; 300 y = Y_HOME; 301 302#ifdef MEDIUM_FONT 303 fc24.drawText("TEMP & HUM DATA (HS4001):", x, y, FONT_COLOR); 304 y += Y_TAB/2; 305 fc24.drawText("-----------------------------------------", x, y, FONT_COLOR); 306 y += Y_TAB; 307 fc24.drawText("Temperature [C]:", x, y, FONT_COLOR); 308 fc24.drawText(Temp_s, (x + X_TAB), y, FONT_COLOR); 309 310 y += Y_TAB; 311 fc24.drawText("Humidity [%]:", x, y, FONT_COLOR); 312 fc24.drawText(Hum_s, (x + X_TAB), y, FONT_COLOR); 313#endif 314 315#ifdef BIG_FONT 316 y += Y_TAB; 317 fc24.drawText("Temp(C):", x, y, FONT_COLOR); 318 fc24.drawText(Temp_s, (x + X_TAB), y, FONT_COLOR); 319 320 y += Y_TAB; 321 fc24.drawText("Hum(%):", x, y, FONT_COLOR); 322 fc24.drawText(Hum_s, (x + X_TAB), y, FONT_COLOR); 323#endif 324 325 delay(REFRESH_RATE_S*1000); 326 } 327}
board_select.h
c
board_select.h
1/* 2 * This file contains definitions for all of the supported graphic boards. 3 */ 4 5 6#ifdef USE_ILI9341 7 /* 8 * Definitions for the 2.4 inch 320x240 TFT FeatherWing 9 * https://www.adafruit.com/product/3315 10 */ 11 //Assumes Feather M0 or M4 or other compatible 12 #define STMPE_CS 6 13 #define TFT_CS 9 14 #define TFT_DC 10 15 #define SD_CS 5 16 17 #include <Adafruit_ILI9341.h> 18 Adafruit_ILI9341 display = Adafruit_ILI9341(TFT_CS, TFT_DC); 19 #define DWIDTH 320 20 #define DHEIGHT 240 21 #define COLOR_BLACK ILI9341_BLACK 22 #define COLOR_YELLOW ILI9341_YELLOW 23 #define COLOR_WHITE ILI9341_WHITE 24 void Initialize_Display(void){ 25 display.begin(); 26 display.setRotation(1); 27 }; 28#endif 29 30#ifdef USE_HX8357 31 /* 32 * Definitions for the 3.5 inch 480x220 TFT FeatherWing 33 * https://www.adafruit.com/product/3651 34 */ 35 //Assumes Feather M0 or M4 or other compatible 36 #define STMPE_CS 6 37 #define TFT_CS 9 38 #define TFT_DC 10 39 #define SD_CS 5 40 41 #include <Adafruit_GFX.h> 42 #include <Adafruit_HX8357.h> 43 Adafruit_HX8357 display = Adafruit_HX8357(TFT_CS, TFT_DC); 44 #define DWIDTH 480 45 #define DHEIGHT 320 46 #define COLOR_BLACK HX8357_BLACK 47 #define COLOR_YELLOW HX8357_YELLOW 48 #define COLOR_WHITE HX8357_WHITE 49 void Initialize_Display(void){ 50 display.begin(); 51 display.setRotation(1); 52 }; 53#endif 54 55#ifdef USE_HALLOWING 56 /* 57 * Definitions for the Hallowing M0 Express 58 * https://www.adafruit.com/product/3900 59 */ 60 //Hardwired for hallowing 61 #define TFT_CS 39 62 #define TFT_RST 37 63 #define TFT_DC 38 64 #define TFT_BACKLIGHT 7 65 66 #include <Adafruit_GFX.h> 67 #include <Adafruit_ST7735.h> 68 Adafruit_ST7735 display = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); 69 #define DWIDTH 128 70 #define DHEIGHT 128 71 #define COLOR_BLACK ST7735_BLACK 72 #define COLOR_YELLOW ST7735_YELLOW 73 #define COLOR_WHITE ST7735_WHITE 74 void Initialize_Display(void){ 75 pinMode(TFT_BACKLIGHT, OUTPUT); 76 digitalWrite(TFT_BACKLIGHT, HIGH); 77 display.initR(INITR_144GREENTAB); // initialize a ST7735S chip, black tab 78 display.setRotation(2); 79 }; 80#endif 81 82#ifdef USE_PYGAMER 83 /* 84 * Definitions for the PyGamer M4 Express 85 * https://www.adafruit.com/product/4242 86 */ 87 #include <Adafruit_Arcada.h> 88 Adafruit_Arcada display; 89 #define DWIDTH 160 90 #define DHEIGHT 128 91 #define COLOR_BLACK ST77XX_BLACK 92 #define COLOR_YELLOW ST77XX_YELLOW 93 #define COLOR_WHITE ST77XX_WHITE 94 void Initialize_Display(void){ 95 display.begin(); 96 display.displayBegin(); 97 display.setBacklight(255); 98 }; 99#endif 100 101#ifdef USE_GIGA_GFX 102 /* 103 * Definitions for the Arduino Giga R1 and its conmpanion Giga Display. 104 */ 105 106 #include "Arduino_GigaDisplay_GFX.h" 107 108 GigaDisplay_GFX display; 109 #define DWIDTH 800 110 #define DHEIGHT 480 111 #define COLOR_BLACK 0 112 #define COLOR_YELLOW display.color565(0xFF, 0xFF, 0) 113 #define COLOR_WHITE 0xFFFF 114 void Initialize_Display(void){ 115 display.begin(); 116 display.setRotation(1); 117 }; 118#endif 119 120#ifdef USE_MCUFRIEND 121 /* 122 * Definitions for the 2.8 inch MCUFRIEND displays. 123 */ 124 125 #include <Adafruit_GFX.h> 126 #include <MCUFRIEND_kbv.h> 127 MCUFRIEND_kbv display; 128 129 #define DWIDTH 320 130 #define DHEIGHT 240 131 #define COLOR_BLACK 0 132 #define COLOR_YELLOW 0xFFE0 133 #define COLOR_WHITE 0xFFFF 134 void Initialize_Display(void){ 135 uint16_t ID = display.readID(); 136 Serial.print("TFT ID = 0x"); 137 Serial.println(ID, HEX); 138 display.begin(ID); 139 display.setRotation(1); 140 }; 141#endif
Comments
Only logged in users can leave comments