Untitled

mail@pastecode.io avatarunknown
c_cpp
17 days ago
6.1 kB
1
Indexable
Never
#include <SimpleTimer.h>
#include <Wire.h>
#include <SPI.h>

#define DUST_SENSOR_DIGITAL_PIN_PM10 5  // DSM501 Pin 2 (Yellow)
#define DUST_SENSOR_DIGITAL_PIN_PM25 6  // DSM501 Pin 4 (red)

#define GOOD "Good"
#define ACCEPTABLE "Acceptable"
#define MODERATE "Moderate"
#define HEAVY "Heavy"
#define SEVERE "Severe"

unsigned long duration;
unsigned long starttime;
unsigned long endtime;
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
unsigned long SLEEP_TIME = 2 * 1000;
unsigned long sampletime_ms = 10 * 1000;

struct structAQI {
  unsigned long durationPM10;
  unsigned long lowpulseoccupancyPM10 = 0;
  unsigned long durationPM25;
  unsigned long lowpulseoccupancyPM25 = 0;
  unsigned long starttime;
  unsigned long endtime;
  float concentrationPM25 = 0;
  float concentrationPM10 = 0;
  int AqiPM10 = -1;
  int AqiPM25 = -1;
  int AQI = 0;
  String AqiString = "";
};
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();

  AQI.AqiPM25 = getACQI(0, AQI.concentrationPM25);
  AQI.AqiPM10 = getACQI(1, AQI.concentrationPM10);

  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() {
  Serial.begin(9600);

  pinMode(DUST_SENSOR_DIGITAL_PIN_PM10, INPUT);
  pinMode(DUST_SENSOR_DIGITAL_PIN_PM25, INPUT);

  // 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();

  Serial.print("PM 2.5:");
  Serial.println(AQI.concentrationPM25);

  Serial.print("Aqui:");
  Serial.println(AQI.AqiPM25);

  Serial.println("--------------");

  Serial.print("PM 10:");
  Serial.print(AQI.concentrationPM10);

  Serial.print("Aqui:");
  Serial.print(AQI.AqiPM10);

  Serial.print("--------------");

  Serial.print(AQI.AqiString);

  delay(1000);
}

void updateAQIDisplay() {
  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;
  }
}

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 <= 30) {
      return 50;
    } else if (density <= 55) {
      return 75;
    } else if (density <= 110) {
      return 100;
    } else {
      return 150;
    }
  } else {  //PM10
    if (density == 0) {
      return 0;
    } else if (density <= 25) {
      return 25;
    } else if (density <= 50) {
      return 50;
    } else if (density <= 90) {
      return 75;
    } else if (density <= 180) {
      return 100;
    } else {
      return 150;
    }
  }
}

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;
    }
  }
}