#include #include #include #include #define LILYGO_T5_V213 // needed for the display libraries #include #include #include // screen model, probably correct #include #include #include GxIO_Class io(SPI, EPD_CS, EPD_DC, EPD_RSET); GxEPD_Class display(io, EPD_RSET, EPD_BUSY); SPIClass SDSPI(VSPI); // for sdcard? maybe? SensirionI2CScd4x scd4x; void printUint16Hex(uint16_t value) { Serial.print(value < 4096 ? "0" : ""); Serial.print(value < 256 ? "0" : ""); Serial.print(value < 16 ? "0" : ""); Serial.print(value, HEX); } void printSerialNumber(uint16_t serial0, uint16_t serial1, uint16_t serial2) { Serial.print("Serial: 0x"); printUint16Hex(serial0); printUint16Hex(serial1); printUint16Hex(serial2); Serial.println(); } void setup() { 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); display.fillScreen(GxEPD_WHITE); display.update(); uint16_t error; char errorMessage[256]; 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); } uint16_t serial0; uint16_t serial1; uint16_t serial2; error = scd4x.getSerialNumber(serial0, serial1, serial2); if (error) { Serial.print("Error trying to execute getSerialNumber(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } else { printSerialNumber(serial0, serial1, serial2); } // 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)"); } void loop() { uint16_t error; char errorMessage[256]; delay(5000); // Read Measurement uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; error = scd4x.readMeasurement(co2, temperature, humidity); struct sps30_measurement m; 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; } display.fillScreen(GxEPD_WHITE); display.setCursor(0,20); display.print("Co2:"); display.println(co2); display.print("T:"); display.print(temperature); display.print(" H:"); display.println(humidity); display.print("PM 1:"); display.print(m.mc_1p0); display.print(" PM 2.5:"); display.println(m.mc_2p5); display.print("PM 4:"); display.print(m.mc_4p0); display.print(" PM 10:"); display.println(m.mc_10p0); display.update(); }