From 3443edf23337fb5d9ce63075ead80c4779cf823a Mon Sep 17 00:00:00 2001 From: dakkar Date: Sun, 27 Mar 2022 12:48:36 +0100 Subject: break code into logical components --- battery.h | 24 ++++++--- co2.h | 62 ++++++++++++++++++++++ data.h | 10 ++++ display.h | 63 +++++++++++++++++++++++ main.ino | 174 ++++++++++---------------------------------------------------- pm.h | 63 +++++++++++++++++++++++ 6 files changed, 243 insertions(+), 153 deletions(-) create mode 100644 co2.h create mode 100644 data.h create mode 100644 display.h create mode 100644 pm.h diff --git a/battery.h b/battery.h index 825a3ab..e53341b 100644 --- a/battery.h +++ b/battery.h @@ -1,19 +1,16 @@ #pragma once #include +#include "data.h" + /* code inspired by https://gist.github.com/jenschr/dfc765cb9404beb6333a8ea30d2e78a1 */ class Battery { +private: uint8_t pin; -public: - /* - the schematics at - https://github.com/Xinyuan-LilyGO/LilyGo-T5-Epaper-Series/tree/master/schematic - show a voltage divider connected to pin 35 - */ - Battery(uint8_t _pin=35) : pin(_pin) {}; + float voltage() { /* Comment from the gist: @@ -35,4 +32,17 @@ public: */ return (float)(analogRead(pin)) / 4095*2*3.3*1.1; } +public: + /* + the schematics at + https://github.com/Xinyuan-LilyGO/LilyGo-T5-Epaper-Series/tree/master/schematic + show a voltage divider connected to pin 35 + */ + Battery(uint8_t _pin=35) : pin(_pin) {}; + + void start() {} + bool dataReady() { return true; } + void read(SensorData *data) { + data->batteryVoltage = voltage(); + } }; diff --git a/co2.h b/co2.h new file mode 100644 index 0000000..ac963f4 --- /dev/null +++ b/co2.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +#include +#include + +#include "data.h" + +class CO2 { +private: + SensirionI2CScd4x scd4x; + +public: + CO2() : scd4x() {} + + void start() { + uint16_t error; + char errorMessage[256]; + + scd4x.begin(Wire); + + // stop potentially previously started measurement + error = scd4x.stopPeriodicMeasurement(); + if (error) { + Serial.print("CO2 stopPeriodicMeasurement() error: "); + errorToString(error, errorMessage, 256); + Serial.println(errorMessage); + } + + error = scd4x.setAutomaticSelfCalibration(1); + if (error) { + Serial.print("CO2 setAutomaticSelfCalibration() error: "); + errorToString(error, errorMessage, 256); + Serial.println(errorMessage); + } + + // Start Measurement + error = scd4x.startPeriodicMeasurement(); + if (error) { + Serial.print("CO2 startPeriodicMeasurement() error: "); + errorToString(error, errorMessage, 256); + Serial.println(errorMessage); + } + } + + bool dataReady() { + return true; + } + + void read(SensorData *data) { + uint16_t error; + char errorMessage[256]; + + error = scd4x.readMeasurement(data->co2, data->temperature, data->humidity); + if (error) { + Serial.print("CO2 readMeasurement() error: "); + errorToString(error, errorMessage, 256); + Serial.println(errorMessage); + } + } +}; diff --git a/data.h b/data.h new file mode 100644 index 0000000..1689f65 --- /dev/null +++ b/data.h @@ -0,0 +1,10 @@ +#pragma once +#include + +struct SensorData { + uint16_t co2; + float temperature; + float humidity; + float batteryVoltage; + struct sps30_measurement pm; +}; diff --git a/display.h b/display.h new file mode 100644 index 0000000..fdab3f3 --- /dev/null +++ b/display.h @@ -0,0 +1,63 @@ +#pragma once + +#define LILYGO_T5_V213 // needed for the display libraries + +#include +#include +#include // screen model, probably correct +#include +#include +#include + +#include "data.h" + +class Display { +private: + GxIO_Class io; + GxEPD_Class display; + +public: + Display() : + io(SPI, EPD_CS, EPD_DC, EPD_RSET), + display(io, EPD_RSET, EPD_BUSY) + {} + + void start() { + SPI.begin(EPD_SCLK, EPD_MISO, EPD_MOSI); + + display.init(); + display.setTextColor(GxEPD_BLACK); + display.setRotation(3); + display.setFont(&FreeMonoBold9pt7b); + } + + void show(const SensorData *data) { + display.fillScreen(GxEPD_WHITE); + + display.setCursor(0,20); + display.print("Co2 "); + display.print(data->co2); + + display.setCursor(100,20); + display.print("t"); + display.print(data->temperature,1); + + display.setCursor(150,20); + display.print(" h"); + display.print(data->humidity,0); + display.print("%"); + + display.setCursor(0,45); + display.println(" PM"); + display.print(" 1.0 "); display.println(data->pm.mc_1p0,1); + display.print(" 2.5 "); display.println(data->pm.mc_2p5,1); + display.print(" 4.0 "); display.println(data->pm.mc_4p0,1); + display.print("10.0 "); display.println(data->pm.mc_10p0,1); + + display.setCursor(100,45); + display.print("Batt "); display.print(data->batteryVoltage); + + // "partial" update + display.updateWindow(0, 0, GxEPD_WIDTH, GxEPD_HEIGHT, false); + } +}; diff --git a/main.ino b/main.ino index ce9f981..8dcb387 100644 --- a/main.ino +++ b/main.ino @@ -1,164 +1,46 @@ #include -#include -#include #include -#define LILYGO_T5_V213 // needed for the display libraries - -#include -#include -#include // screen model, probably correct -#include -#include -#include - +#include "data.h" #include "battery.h" +#include "display.h" +#include "co2.h" +#include "pm.h" -GxIO_Class io(SPI, EPD_CS, EPD_DC, EPD_RSET); -GxEPD_Class display(io, EPD_RSET, EPD_BUSY); -SPIClass SDSPI(VSPI); // for sdcard - -SensirionI2CScd4x scd4x; - -Battery batt; - -uint16_t co2 = 0; -float temperature = 0.0f; -float humidity = 0.0f; -struct sps30_measurement m; - -void showThings(bool all=false) { - display.fillScreen(GxEPD_WHITE); - - display.setCursor(0,20); - display.print("Co2 "); - display.print(co2); +Battery battery; +PM pm; +CO2 co2; - display.setCursor(100,20); - display.print("t"); - display.print(temperature,1); +SensorData data; - display.setCursor(150,20); - display.print(" h"); - display.print(humidity,0); - display.print("%"); - - display.setCursor(0,45); - display.println(" PM"); - display.print(" 1.0 "); display.println(m.mc_1p0,1); - display.print(" 2.5 "); display.println(m.mc_2p5,1); - display.print(" 4.0 "); display.println(m.mc_4p0,1); - display.print("10.0 "); display.println(m.mc_10p0,1); - - display.setCursor(100,45); - display.print("Batt "); display.print(batt.voltage()); - - // "partial" update - display.updateWindow(0, 0, GxEPD_WIDTH, GxEPD_HEIGHT, false); -} +Display display; void setup() { + Serial.begin(115200); + while (!Serial) { + delay(100); + } - Serial.begin(115200); - while (!Serial) { - delay(100); - } - - // the board's definition says SCL=23, but I have SCL=22 - Wire.begin(21,22); - - SPI.begin(EPD_SCLK, EPD_MISO, EPD_MOSI); - - display.init(); - display.setTextColor(GxEPD_BLACK); - display.setRotation(3); - display.setFont(&FreeMonoBold9pt7b); + // the board's definition says SCL=23, but I have SCL=22 + Wire.begin(21,22); - showThings(); + display.start(); + display.show(&data); - uint16_t error; - char errorMessage[256]; + battery.start(); + co2.start(); + pm.start(); + Serial.println("Waiting for first measurement... (5 sec)"); - scd4x.begin(Wire); - - // stop potentially previously started measurement - error = scd4x.stopPeriodicMeasurement(); - if (error) { - Serial.print("Error trying to execute stopPeriodicMeasurement(): "); - errorToString(error, errorMessage, 256); - Serial.println(errorMessage); - } - - error = scd4x.setAutomaticSelfCalibration(1); - if (error) { - Serial.print("Error trying to execute setAutomaticSelfCalibration(): "); - errorToString(error, errorMessage, 256); - Serial.println(errorMessage); - } - - // Start Measurement - error = scd4x.startPeriodicMeasurement(); - if (error) { - Serial.print("Error trying to execute startPeriodicMeasurement(): "); - errorToString(error, errorMessage, 256); - Serial.println(errorMessage); - } - - // this will try to re-init Wire, emit a warning, and carry on - sensirion_i2c_init(); - - while (sps30_probe() != 0) { - Serial.print("SPS sensor probing failed\n"); - delay(500); - } - - int16_t ret; - uint8_t auto_clean_days = 4; - uint32_t auto_clean; - - ret = sps30_set_fan_auto_cleaning_interval_days(auto_clean_days); - if (ret) { - Serial.print("error setting the auto-clean interval: "); - Serial.println(ret); - } - - ret = sps30_start_measurement(); - if (ret < 0) { - Serial.print("error starting measurement\n"); - } - - Serial.println("Waiting for first measurement... (5 sec)"); + delay(5000); } void loop() { - uint16_t error; - char errorMessage[256]; - - delay(5000); - - error = scd4x.readMeasurement(co2, temperature, humidity); - - char serial[SPS30_MAX_SERIAL_LEN]; - uint16_t data_ready; - int16_t ret; - - do { - ret = sps30_read_data_ready(&data_ready); - if (ret < 0) { - Serial.print("error reading data-ready flag: "); - Serial.println(ret); - } else if (!data_ready) - Serial.print("data not ready, no new measurement available\n"); - else - break; - delay(100); /* retry in 100ms */ - } while (1); - - ret = sps30_read_measurement(&m); - - if (error || ret <0 || co2 ==0) { - return; - } + if (battery.dataReady()) battery.read(&data); + if (pm.dataReady()) pm.read(&data); + if (co2.dataReady()) co2.read(&data); - showThings(); + display.show(&data); + + delay(5000); } diff --git a/pm.h b/pm.h new file mode 100644 index 0000000..634c1b4 --- /dev/null +++ b/pm.h @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include "data.h" + +class PM { +private: + uint8_t auto_clean_days; +public: + PM(uint8_t acd=4) :auto_clean_days(acd) {} + + void start() { + // this will try to re-init Wire, emit a warning, and carry on + sensirion_i2c_init(); + + while (sps30_probe() != 0) { + Serial.print("PM sensor probing failed\n"); + delay(500); + } + + int16_t ret; + + ret = sps30_set_fan_auto_cleaning_interval_days(auto_clean_days); + if (ret) { + Serial.print("PM setting the auto-clean interval error: "); + Serial.println(ret); + } + + ret = sps30_start_measurement(); + if (ret < 0) { + Serial.print("PM starting measurement error\n"); + } + } + + bool dataReady() { + uint16_t data_ready; + int16_t ret; + + ret = sps30_read_data_ready(&data_ready); + if (ret < 0) { + Serial.print("PM reading data-ready flag error: "); + Serial.println(ret); + return false; + } else if (!data_ready) { + return false; + } + + return true; + } + + void read(SensorData *data) { + char serial[SPS30_MAX_SERIAL_LEN]; + int16_t ret; + + ret = sps30_read_measurement(&(data->pm)); + + if (ret <0) { + Serial.print("PM reading measurement error: "); + Serial.println(ret); + } + } +}; -- cgit v1.2.3