ES-Mask
Environmental Sense Mask which monitors the Air Quality, VOC, CO2, Temperature and Humidity using ES-Mask Mobile Application.
Components and supplies
1
Nicla Sense ME
1
Fan 5V
1
Tactile switch
1
24 Bit WS2812 5050 RGB LED
1
0.96″ OLED Display Module
1
Dot Pcb
1
Arduino MKR 1010 WiFi
Tools and machines
1
Soldering kit
1
Solder Soldering Wire
Apps and platforms
1
Android Studio
1
Unity
Project description
Code
Nicla Sense ME Code
c
1//Nicla Sense ME MAC ID: 49:7F:14:78:0B:50 2 3#include <ArduinoBLE.h> 4#include <Arduino_BHY2.h> 5#include <Nicla_System.h> 6 7#define RedON 255 8#define RedOFF 0 9#define GreenON 255 10#define GreenOFF 0 11#define BlueOFF 0 12 13SensorBSEC bsec(SENSOR_ID_BSEC); 14Sensor temperature(SENSOR_ID_TEMP); 15Sensor gas(SENSOR_ID_GAS); 16Sensor pressure(SENSOR_ID_BARO); 17Sensor humidity(SENSOR_ID_HUM); 18 19 20//16-bit or 128-bit UUID in String format 21#define NICLA_SENSE_UUID(val) ("19b10000-" val "-537e-4f6c-d104768a1214") 22 23// Step(1): Set the Service Name and Service UUID. 24BLEService E_MASK_SERVICE(NICLA_SENSE_UUID("1000")); 25 26 27 28// Step(2): Set the Characteristic Name and Characteristic UUID.(BLERead | BLENotify | BLEWrite | BLEIndicate) 29 30/*BLEByteCharacteristic(uuid, properties) 31BLEShortCharacteristic(uuid, properties) 32BLEIntCharacteristic(uuid, properties) 33BLECharacteristic TempHumiPresData2BytesCharacteristic(NICLA_SENSE_UUID("1004"), BLERead | BLENotify, 3 * sizeof(byte)); 34BLECharacteristic TempHumiPresData2ShortCharacteristic(NICLA_SENSE_UUID("1003"), BLERead | BLENotify, 3 * sizeof(short)); // Array of 3x 2 Bytes, XYZ 35BLEStringCharacteristic stringcharacteristic("183E", BLERead | BLEWrite, 31);*/ 36//BLECharacteristic TempHumiPresData2ShortCharacteristic(NICLA_SENSE_UUID("1003"), BLERead | BLENotify, 3 * sizeof(short)); // Array of 3x 2 Bytes, XYZ 37 38 39BLEStringCharacteristic eMask_Data_CharasStr(NICLA_SENSE_UUID("1001"), BLENotify, 31); 40 41 42int IAQ, CO2, BSEC_Gas_Res; 43float B_VOC; 44int Temp, Baro, Humi, Gas; 45String IAQ_COMMENT, CO2_COMMENT, B_VOC_COMMENT; 46 47 48 49void setup() 50{ 51 52 Serial.begin(115200); 53 // Step(3a): 54 BLE.begin(); 55 56 nicla::begin(); 57 nicla::leds.begin(); 58 59 BHY2.begin(); 60 61 bsec.begin(); 62 temperature.begin(); 63 pressure.begin(); 64 humidity.begin(); 65 // gas.begin(); 66 67 68 69 // Step(3b): Set the Local Name and Device Name. 70 BLE.setLocalName("eMask_Nicla_Sense"); 71 BLE.setDeviceName("eMask_Nicla_Sense"); 72 73 // Step(4): Add the BLE.setAdvertisedService and Service Name. 74 BLE.setAdvertisedService(E_MASK_SERVICE); 75 76 // Step(5): Add Characteristic using (Service Name).addCharacteristic(Characteristic Name); // Display Order must match the Characteristics Definetion. 77 E_MASK_SERVICE.addCharacteristic(eMask_Data_CharasStr); 78 79 // Step(6): Add BLE.addService(Service Name); 80 BLE.addService(E_MASK_SERVICE); 81 82 // Step(7): Add BLE.advertise(); 83 BLE.advertise(); 84} 85 86void loop() 87{ 88 static auto printTime = millis(); 89 90 // Update function should be continuously polled 91 92 if (millis() - printTime >= 100) { 93 printTime = millis(); 94 95 loadNanoSenseVals(); 96 97 } 98} 99 100 101 void BSEC_TPHG_SensorData() 102 { 103 BHY2.update(); 104 105 IAQ = bsec.iaq(); 106 CO2 = bsec.co2_eq(); 107 B_VOC = bsec.b_voc_eq(); 108 109 Temp = int(temperature.value()); 110 Humi = int(humidity.value()); 111 } 112 113 114 115 116 117 118 119 void loadNanoSenseVals() 120 { 121 122 123 124 // Step(8): Add BLEDevice central = BLE.central() for BLE(Peripheral) Device to connect with Central Device. 125 BLEDevice central = BLE.central(); 126 127 128 if (central) 129 { 130 Serial.print("Connected to central: "); 131 Serial.println(central.address()); 132 133 //#Green - Connected// 134 nicla::leds.setColor(RedOFF, GreenON ,BlueOFF); 135 136 //Serial.print("Updating sensor values"); 137 138 139 ////////////////Characteristics - Subscribe////////////// 140 141 //////////Nicla-data//////////// 142 143 144 145 if (eMask_Data_CharasStr.subscribed()) 146 { 147 BSEC_TPHG_SensorData(); 148 149 String Nicla_Data = 150 String(IAQ) + String("|") + 151 String(CO2) + String("|") + 152 String(B_VOC) + String("|") + 153 String(Temp) + String("|") + 154 String(Humi); 155 156 157 Serial.println( 158 String("IAQ : ") + IAQ + String(" , ") + 159 String("CO2 : ") + CO2 + String(" , ") + 160 String("B_VOC : ") + B_VOC + String(" , ") + 161 String("TEMP : ") + Temp + String(" , ") + 162 String("HUMI : ") + Humi); 163 Serial.println(""); 164 165 Serial.println(Nicla_Data); 166 Serial.println(""); 167 168 eMask_Data_CharasStr.writeValue(Nicla_Data); 169 170 } 171 172 173 174 175 176 177 178 179 } else { 180 181 Serial.println("Device Not Connected"); 182 //#red - Not Connected// 183 nicla::leds.setColor(RedON, GreenOFF ,BlueOFF); 184 185 186 } 187 188 189 190 }
MKR Code
c
1#include <FastLED.h> 2#include "Arduino.h" 3#include "Arduino_BHY2Host.h" 4#include <Wire.h> 5#include <Adafruit_GFX.h> 6#include <Adafruit_SSD1306.h> 7 8 9 10 11#define LED_PIN 6 12#define NUM_LEDS 24 13#define BRIGHTNESS 64 14#define LED_TYPE WS2812 15#define COLOR_ORDER GRB 16 17CRGB leds[NUM_LEDS]; 18int color, IAQ_Color; 19 20 21 22SensorBSEC bsec(SENSOR_ID_BSEC); 23int IAQ; 24String IAQ_Comment; 25 26 27#define SCREEN_WIDTH 128 // OLED display width, in pixels 28#define SCREEN_HEIGHT 64 // OLED display height, in pixels 29 30// declare an SSD1306 display object connected to I2C 31Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); 32 33 34void setup() 35{ 36 // debug port 37 Serial.begin(115200); 38 //while(!Serial); 39 40 BHY2Host.begin(false, NICLA_VIA_ESLOV); 41 42 bsec.begin(); 43 44 if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 45 Serial.println(F("SSD1306 allocation failed")); 46 while (true); 47 } 48 49 50 51 oled.setTextSize(2); // text size 52 oled.setTextColor(WHITE); // text color 53 oled.setCursor(0, 10); // position to display 54 // Display static text 55 oled.println("e-Mask !!!"); 56 oled.display(); 57 58 delay(2000); // wait for initializing 59 oled.clearDisplay(); // clear display 60 61 FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS); 62 FastLED.setBrightness( BRIGHTNESS ); 63 64 65 66} 67 68void loop() 69{ 70 71 BHY2Host.update(); 72 static auto printTime = millis(); 73 74 75 76 77 if (millis() - printTime >= 100) { 78 printTime = millis(); 79 80 81 82 Serial.println(String("IAQ : ") + IAQ + String(" - ") + IAQ_Comment); 83 Serial.println(""); 84 85 IAQ_Value(); 86 OLED_Display(); 87 88 } 89} 90 91 92 93 void IAQ_Value() 94 { 95 CRGB Good; 96 CRGB Moderate; 97 CRGB Bad; 98 CRGB White = CRGB::White; 99 CRGB Black = CRGB::Black; 100 101 CRGB Green = CRGB::Green; 102 CRGB Yellow = CRGB::Yellow; 103 CRGB Maroon = CRGB::Maroon; 104 105 IAQ = bsec.iaq(); 106 107 108 //IAQ Level 109 if ( IAQ <= 50) 110 { 111 IAQ_Comment = "Excellent"; Good = Green; Moderate = Black; Bad = Black; 112 } 113 else if (IAQ >= 51 && IAQ <= 150) 114 { 115 IAQ_Comment = "Good"; Good = Green; Moderate = Black; Bad = Black; 116 } 117 else if (IAQ >= 151 && IAQ <= 350) 118 { 119 IAQ_Comment = "Moderate"; Good = Green; Moderate = Yellow; Bad = Black; 120 } 121 else if (IAQ >= 351) 122 { 123 IAQ_Comment = "Hazardous"; Good = Green; Moderate = Yellow; Bad = Maroon; 124 } 125 else {} 126 127 128 129 130 leds[3] = Good; 131 leds[4] = Good; 132 leds[5] = Good; 133 leds[6] = Good; 134 leds[7] = Good; 135 leds[8] = Good; 136 137 leds[9] = Moderate; 138 leds[10] = Moderate; 139 leds[11] = Moderate; 140 leds[12] = Moderate; 141 leds[13] = Moderate; 142 leds[14] = Moderate; 143 144 leds[15] = Bad; 145 leds[16] = Bad; 146 leds[17] = Bad; 147 leds[18] = Bad; 148 leds[19] = Bad; 149 leds[20] = Bad; 150 151 152 153 FastLED.show(); 154 155 } 156 157 void OLED_Display(){ 158 159 //OLED Display Input 160 oled.clearDisplay(); 161 162 oled.setTextSize(2); // text size 163 oled.setTextColor(WHITE); // text color 164 oled.setCursor(0, 10); // position to display 165 oled.println(IAQ_Comment); 166 oled.println(""); 167 oled.print("IAQ : "); // text to display 168 oled.println(IAQ); // text to display 169 170 oled.display(); // show on OLED 171 172 delay(200); 173 }
Documentation
ES-Mask Circuit Diagram
eMask_Frizz.jpg

BME680 IAQ Classification Table
file.None

BME680 VOC Classification Table
BSEC_VOC_Level.png

Comments
Only logged in users can leave comments