Untitled
c_cpp
21 days ago
12 kB
1
Indexable
Never
#include <SimpleTimer.h> #include <Wire.h> #include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_PCD8544.h> Adafruit_PCD8544 display = Adafruit_PCD8544(8, 9, 10, 11, 12); /* Connect the DSM501 sensor as follow * https://www.elektronik.ropla.eu/pdf/stock/smy/dsm501.pdf * 1 green vert - Not used * 2 yellow jaune - Vout2 - 1 microns (PM1.0) * 3 white blanc - Vcc * 4 red rouge - Vout1 - 2.5 microns (PM2.5) * 5 black noir - GND */ #define DUST_SENSOR_DIGITAL_PIN_PM10 5 // DSM501 Pin 2 of DSM501 (jaune / Yellow) #define DUST_SENSOR_DIGITAL_PIN_PM25 6 // DSM501 Pin 4 (rouge / red) #define COUNTRY 0 // 0. France, 1. Europe, 2. USA/China #define EXCELLENT "Excellent" #define GOOD "Good" #define ACCEPTABLE "Acceptable" #define MODERATE "Moderate" #define HEAVY "Heavy" #define SEVERE "Severe" #define HAZARDOUS "Dangerous" unsigned long duration; unsigned long starttime; unsigned long endtime; unsigned long lowpulseoccupancy = 0; float ratio = 0; unsigned long SLEEP_TIME = 2 * 1000; // Sleep time between reads (in milliseconds) //unsigned long sampletime_ms = 1 * 1000; // Durée de mesure - sample time (ms) unsigned long sampletime_ms = 10 * 1000; // Durée de mesure - sample time (ms) //unsigned long sampletime_ms = 5 * 60 * 1000; // Durée de mesure - sample time (ms) struct structAQI{ // variable enregistreur - recorder variables unsigned long durationPM10; unsigned long lowpulseoccupancyPM10 = 0; unsigned long durationPM25; unsigned long lowpulseoccupancyPM25 = 0; unsigned long starttime; unsigned long endtime; // Sensor AQI data float concentrationPM25 = 0; float concentrationPM10 = 0; int AqiPM10 = -1; int AqiPM25 = -1; // Indicateurs AQI - AQI display int AQI = 0; String AqiString = ""; int AqiColor = 0; }; struct structAQI AQI; SimpleTimer timer; void updateAQILevel(){ AQI.AQI = AQI.AqiPM10; } void updateAQI() { // Actualise les mesures - update measurements AQI.endtime = millis(); float ratio = AQI.lowpulseoccupancyPM10 / (sampletime_ms * 10.0); float concentration = 1.1 * pow( ratio, 3) - 3.8 *pow(ratio, 2) + 520 * ratio + 0.62; // using spec sheet curve if ( sampletime_ms < 3600000 ) { concentration = concentration * ( sampletime_ms / 3600000.0 ); } AQI.lowpulseoccupancyPM10 = 0; AQI.concentrationPM10 = concentration; ratio = AQI.lowpulseoccupancyPM25 / (sampletime_ms * 10.0); concentration = 1.1 * pow( ratio, 3) - 3.8 *pow(ratio, 2) + 520 * ratio + 0.62; if ( sampletime_ms < 3600000 ) { concentration = concentration * ( sampletime_ms / 3600000.0 ); } AQI.lowpulseoccupancyPM25 = 0; AQI.concentrationPM25 = concentration; Serial.print("Concentrations => PM2.5: "); Serial.print(AQI.concentrationPM25); Serial.print(" | PM10: "); Serial.println(AQI.concentrationPM10); AQI.starttime = millis(); // Actualise l'AQI de chaque capteur - update AQI for each sensor if ( COUNTRY == 0 ) { // France AQI.AqiPM25 = getATMO( 0, AQI.concentrationPM25 ); AQI.AqiPM10 = getATMO( 1, AQI.concentrationPM10 ); } else if ( COUNTRY == 1 ) { // Europe AQI.AqiPM25 = getACQI( 0, AQI.concentrationPM25 ); AQI.AqiPM10 = getACQI( 1, AQI.concentrationPM10 ); } else { // USA / China AQI.AqiPM25 = getAQI( 0, AQI.concentrationPM25 ); AQI.AqiPM10 = getAQI( 0, AQI.concentrationPM10 ); } // Actualise l'indice AQI - update AQI index updateAQILevel(); updateAQIDisplay(); Serial.print("AQIs => PM25: "); Serial.print(AQI.AqiPM25); Serial.print(" | PM10: "); Serial.println(AQI.AqiPM10); Serial.print(" | AQI: "); Serial.println(AQI.AQI); Serial.print(" | Message: "); Serial.println(AQI.AqiString); } void setup() { // put your setup code here, to run once: Serial.begin(9600); pinMode(DUST_SENSOR_DIGITAL_PIN_PM10,INPUT); pinMode(DUST_SENSOR_DIGITAL_PIN_PM25,INPUT); display.begin(); display.clearDisplay(); // clears the screen and buffer display.display(); display.setTextColor(BLACK); display.setContrast(70); // wait 60s for DSM501 to warm up for (int i = 1; i <= 5; i++) { delay(1000); // 1s Serial.print(i); Serial.println(" s (wait 60s for DSM501 to warm up)"); } Serial.println("Ready!"); AQI.starttime = millis(); timer.setInterval(sampletime_ms, updateAQI); } void loop() { AQI.lowpulseoccupancyPM10 += pulseIn(DUST_SENSOR_DIGITAL_PIN_PM10, LOW); AQI.lowpulseoccupancyPM25 += pulseIn(DUST_SENSOR_DIGITAL_PIN_PM25, LOW); timer.run(); display.clearDisplay(); display.setContrast(70); display.setTextSize(1); display.setCursor(0,0); display.print("PM 2.5:"); display.setTextSize(1); display.setCursor(45,0); display.print(AQI.concentrationPM25); display.setTextSize(1); display.setCursor(0,10); display.print("Aqui:"); display.setTextSize(1); display.setCursor(35,10); display.print( AQI.AqiPM25); display.setTextSize(1); display.setCursor(0,16); display.print("--------------"); display.setTextSize(1); display.setCursor(0,22); display.print("PM 10:"); display.setTextSize(1); display.setCursor(45,22); display.print(AQI.concentrationPM10); display.setTextSize(1); display.setCursor(0,30); display.print("Aqui:"); display.setTextSize(1); display.setCursor(35,30); display.print(AQI.AqiPM10); display.setTextSize(1); display.setCursor(0,35); display.print("--------------"); display.setTextSize(1); display.setCursor(15,40); display.print(AQI.AqiString); display.display(); delay(1000); } /* * Calcul l'indice de qualité de l'air français ATMO * Calculate French ATMO AQI indicator */ int getATMO( int sensor, float density ){ if ( sensor == 0 ) { //PM2,5 if ( density <= 11 ) { return 1; } else if ( density > 11 && density <= 24 ) { return 2; } else if ( density > 24 && density <= 36 ) { return 3; } else if ( density > 36 && density <= 41 ) { return 4; } else if ( density > 41 && density <= 47 ) { return 5; } else if ( density > 47 && density <= 53 ) { return 6; } else if ( density > 53 && density <= 58 ) { return 7; } else if ( density > 58 && density <= 64 ) { return 8; } else if ( density > 64 && density <= 69 ) { return 9; } else { return 10; } } else { if ( density <= 6 ) { return 1; } else if ( density > 6 && density <= 13 ) { return 2; } else if ( density > 13 && density <= 20 ) { return 3; } else if ( density > 20 && density <= 27 ) { return 4; } else if ( density > 27 && density <= 34 ) { return 5; } else if ( density > 34 && density <= 41 ) { return 6; } else if ( density > 41 && density <= 49 ) { return 7; } else if ( density > 49 && density <= 64 ) { return 8; } else if ( density > 64 && density <= 79 ) { return 9; } else { return 10; } } } void updateAQIDisplay(){ /* * 1 EXCELLENT * 2 GOOD * 3 ACCEPTABLE * 4 MODERATE * 5 HEAVY * 6 SEVERE * 7 HAZARDOUS */ if ( COUNTRY == 0 ) { // Système ATMO français - French ATMO AQI system switch ( AQI.AQI) { case 10: AQI.AqiString = SEVERE; break; case 9: AQI.AqiString = HEAVY; break; case 8: AQI.AqiString = HEAVY; break; case 7: AQI.AqiString = MODERATE; break; case 6: AQI.AqiString = MODERATE; break; case 5: AQI.AqiString = ACCEPTABLE; break; case 4: AQI.AqiString = GOOD; break; case 3: AQI.AqiString = GOOD; break; case 2: AQI.AqiString = EXCELLENT; break; case 1: AQI.AqiString = EXCELLENT; break; } } else if ( COUNTRY == 1 ) { // European CAQI switch ( AQI.AQI) { case 25: AQI.AqiString = GOOD; break; case 50: AQI.AqiString = ACCEPTABLE; break; case 75: AQI.AqiString = MODERATE; break; case 100: AQI.AqiString = HEAVY; break; default: AQI.AqiString = SEVERE; } } else if ( COUNTRY == 2 ) { // USA / CN if ( AQI.AQI <= 50 ) { AQI.AqiString = GOOD; } else if ( AQI.AQI > 50 && AQI.AQI <= 100 ) { AQI.AqiString = ACCEPTABLE; } else if ( AQI.AQI > 100 && AQI.AQI <= 150 ) { AQI.AqiString = MODERATE; } else if ( AQI.AQI > 150 && AQI.AQI <= 200 ) { AQI.AqiString = HEAVY; } else if ( AQI.AQI > 200 && AQI.AQI <= 300 ) { AQI.AqiString = SEVERE; } else { AQI.AqiString = HAZARDOUS; } } } /* * CAQI Européen - European CAQI level * source : http://www.airqualitynow.eu/about_indices_definition.php */ int getACQI( int sensor, float density ){ if ( sensor == 0 ) { //PM2,5 if ( density == 0 ) { return 0; } else if ( density <= 15 ) { return 25 ; } else if ( density > 15 && density <= 30 ) { return 50; } else if ( density > 30 && density <= 55 ) { return 75; } else if ( density > 55 && density <= 110 ) { return 100; } else { return 150; } } else { //PM10 if ( density == 0 ) { return 0; } else if ( density <= 25 ) { return 25 ; } else if ( density > 25 && density <= 50 ) { return 50; } else if ( density > 50 && density <= 90 ) { return 75; } else if ( density > 90 && density <= 180 ) { return 100; } else { return 150; } } } /* * AQI formula: https://en.wikipedia.org/wiki/Air_Quality_Index#United_States * Arduino code https://gist.github.com/nfjinjing/8d63012c18feea3ed04e * On line AQI calculator https://www.airnow.gov/index.cfm?action=resources.conc_aqi_calc */ float calcAQI(float I_high, float I_low, float C_high, float C_low, float C) { return (I_high - I_low) * (C - C_low) / (C_high - C_low) + I_low; } int getAQI(int sensor, float density) { int d10 = (int)(density * 10); if ( sensor == 0 ) { if (d10 <= 0) { return 0; } else if(d10 <= 120) { return calcAQI(50, 0, 120, 0, d10); } else if (d10 <= 354) { return calcAQI(100, 51, 354, 121, d10); } else if (d10 <= 554) { return calcAQI(150, 101, 554, 355, d10); } else if (d10 <= 1504) { return calcAQI(200, 151, 1504, 555, d10); } else if (d10 <= 2504) { return calcAQI(300, 201, 2504, 1505, d10); } else if (d10 <= 3504) { return calcAQI(400, 301, 3504, 2505, d10); } else if (d10 <= 5004) { return calcAQI(500, 401, 5004, 3505, d10); } else if (d10 <= 10000) { return calcAQI(1000, 501, 10000, 5005, d10); } else { return 1001; } } else { if (d10 <= 0) { return 0; } else if(d10 <= 540) { return calcAQI(50, 0, 540, 0, d10); } else if (d10 <= 1540) { return calcAQI(100, 51, 1540, 541, d10); } else if (d10 <= 2540) { return calcAQI(150, 101, 2540, 1541, d10); } else if (d10 <= 3550) { return calcAQI(200, 151, 3550, 2541, d10); } else if (d10 <= 4250) { return calcAQI(300, 201, 4250, 3551, d10); } else if (d10 <= 5050) { return calcAQI(400, 301, 5050, 4251, d10); } else if (d10 <= 6050) { return calcAQI(500, 401, 6050, 5051, d10); } else { return 1001; } } }