Files
aqi-monitor/aqi.ino
2023-04-12 21:41:15 -07:00

177 lines
4.8 KiB
C++

#include <Arduino.h>
#include <SensirionI2CSen44.h>
#include <Wire.h>
#include <LiquidCrystal.h>
SensirionI2CSen44 sen44;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int buttonPin = 6;
// to simulate "parallelism"
unsigned long currentTime;
unsigned long sen44Time = 0;
unsigned long lcdTime = 0;
unsigned long buttonTime = 0;
// display standard values by default
bool isStandardValues = true;
// sen44 values
uint16_t massConcentrationPm1p0 = 0;
uint16_t massConcentrationPm2p5 = 0;
uint16_t massConcentrationPm4p0 = 0;
uint16_t massConcentrationPm10p0 = 0;
float vocIndex = 0;
float ambientHumidity = 0;
float ambientTemperature = 0;
float feelsLikeTemperature = 0;
// calculate heat index
float heatIndex(float t, float rh) {
float hi = 0.0;
if (t <= 40.0)
hi = t;
else {
float hitemp = 61.0 + ((t - 68.0) * 1.2) + (rh * 0.094);
float hifinal = 0.5 * (t + hitemp);
hi = -42.379 + 2.04901523 * t + 10.14333127 * rh - 0.22475541 * t * rh -
6.83783 * (pow(10, -3)) * (pow(t, 2)) -
5.481717 * (pow(10, -2)) * (pow(rh, 2)) +
1.22874 * (pow(10, -3)) * (pow(t, 2)) * rh +
8.5282 * (pow(10, -4)) * t * (pow(rh, 2)) -
1.99 * (pow(10, -6)) * (pow(t, 2)) * (pow(rh, 2));
if (hifinal > 79.0) {
if ((rh <= 13) && (t >= 80.0) && (t <= 112.0))
hi = hi - ((13.0 - rh) / 4.0) * sqrt((17.0 - fabs(t - 95.0)) / 17.0);
else if ((rh > 85.0) && (t >= 80.0) && (t <= 87.0))
hi = hi + ((rh - 85.0) / 10.0) * ((87.0 - t) / 5.0);
} else
hi = hifinal;
}
return hi;
}
// convert celcius to fahrenheit
float celsiusToFahrenheit(float degrees) {
return degrees * 1.8 + 32;
}
void setup() {
Serial.begin(115200);
while (!Serial)
delay(100);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// set up the button pin
pinMode(buttonPin, INPUT_PULLUP);
Wire.begin();
uint16_t error;
char errorMessage[256];
sen44.begin(Wire);
error = sen44.deviceReset();
if (error) {
Serial.print("Error trying to execute getSerialNumber(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
}
// Start Measurement
error = sen44.startMeasurement();
if (error) {
Serial.print("Error trying to execute startMeasurement(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
}
// Clean Fan
sen44.startFanCleaning();
}
void loop() {
currentTime = millis();
delay(50);
// Display Button
if (currentTime - buttonTime >= 100) {
buttonTime = currentTime;
if (digitalRead(buttonPin) == LOW) {
isStandardValues = !isStandardValues;
}
}
// sen44
if (currentTime - sen44Time >= 1000) {
sen44Time = currentTime;
uint16_t error;
char errorMessage[256];
// Read Measurement
error = sen44.readMeasuredMassConcentrationAndAmbientValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, vocIndex, ambientHumidity, ambientTemperature);
if (error) {
Serial.print("Error trying to execute "
"readMeasuredMassConcentrationAndAmbientValues(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
return;
}
ambientTemperature = celsiusToFahrenheit(ambientTemperature);
feelsLikeTemperature = heatIndex(ambientTemperature, ambientHumidity);
}
// Display
if (currentTime - lcdTime >= 500) {
lcdTime = currentTime;
lcd.clear();
if (isStandardValues) {
lcd.setCursor(0, 0);
lcd.print("t:");
lcd.print(round(ambientTemperature));
lcd.setCursor(8, 0);
lcd.print("h:");
lcd.print(round(ambientHumidity));
lcd.setCursor(0, 1);
lcd.print("f:");
lcd.print(round(feelsLikeTemperature));
lcd.setCursor(8, 1);
lcd.print("v:");
lcd.print(vocIndex, 0);
} else {
lcd.setCursor(0, 0);
lcd.print(" 1:");
lcd.print(massConcentrationPm1p0);
lcd.setCursor(8, 0);
lcd.print(" 2:");
lcd.print(massConcentrationPm2p5);
lcd.setCursor(0, 1);
lcd.print(" 4:");
lcd.print(massConcentrationPm4p0);
lcd.setCursor(8, 1);
lcd.print("10:");
lcd.print(massConcentrationPm10p0);
}
}
}