// Images used for display #include "cat-grass.h" // cat_grass #include "catnip.h" // catnip #include "christmas-cactus.h" // christmas_cactus #include "tarragon.h" // tarragon #include "humidity.h" // humidity #include "temp_humidity.h" // temp_humidity #include "temperature.h" // temperature #include "warning_full.h" // warning_full #include "warning.h" // warning #include "battery_0.h" // battery_0 #include "battery_25.h" // battery_25 #include "battery_50.h" // battery_50 #include "battery_75.h" // battery_75 #include "battery_100.h" // battery_100 // SparkFun Fuel Gauge #include "MAX1704X.h" #include "MAX17043.h" // Adafruit temp/humidity sensor // We are using the SHT10 // Humid accuracy +/- 5% // Steady accuracy between 10-80 // example at 10/90 +/- 6%, 0/100 +/- 7.5% #include "SHT1x.h" #define dataPin 43 #define sckPin 35 //serial clock SHT1x th_sensor(dataPin, sckPin); // 2.9" Waveshare 3-color (red) e-ink setup // mapping suggestion for Arduino DUE // BUSY -> 7, RST -> 9, DC -> 8, CS-> 77, CLK -> 76, DIN -> 75 // SPI pins are on 6 pin 2x3 SPI header // base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code // enable or disable GxEPD2_GFX base class #define ENABLE_GxEPD2_GFX 1 #include #include #include #define MAX_DISPAY_BUFFER_SIZE 15000ul // ~15k is a good compromise #define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPAY_BUFFER_SIZE / (EPD::WIDTH / 8)) #define MAX_HEIGHT_3C(EPD) (EPD::HEIGHT <= (MAX_DISPAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8)) GxEPD2_3C display(GxEPD2_290c(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7)); // Delay cheats const unsigned long SECOND = 1000; const unsigned long HOUR = 3600*SECOND; // battery level var float battery_percent; // Temp/Humidity reading vars float temp_c; float humid; void setup() { // Serial.begin(115200); // Initialize the fuel gauge. FuelGauge.begin(); // Initialize display display.init(115200); display.setFullWindow(); display.setRotation(1); display.setFont(&FreeMonoBold9pt7b); display.setTextColor(GxEPD_BLACK); } void loop() { // Clear and reset display for first run // Serial.println("Clearing display"); display.firstPage(); display.clearScreen(); while (display.nextPage()); display.firstPage(); display.setCursor(0, 0); display.println(); // there is a blank line when starting at 0,0 by the looks // Serial.println("END: Clearing display"); // Draw icons for plant status // Serial.println("Drawing icons"); display.drawInvertedBitmap(0, 96, cat_grass, 32, 32, GxEPD_BLACK); display.drawInvertedBitmap(37, 96, catnip, 32, 32, GxEPD_BLACK); display.drawInvertedBitmap(74, 96, tarragon, 32, 32, GxEPD_BLACK); display.drawInvertedBitmap(111, 96, christmas_cactus, 32, 32, GxEPD_BLACK); display.drawInvertedBitmap(148, 96, cat_grass, 32, 32, GxEPD_RED); display.drawInvertedBitmap(185, 96, catnip, 32, 32, GxEPD_RED); display.drawInvertedBitmap(222, 96, tarragon, 32, 32, GxEPD_RED); display.drawInvertedBitmap(259, 96, christmas_cactus, 32, 32, GxEPD_RED); // Serial.println("END: Drawing icons"); // Serial.println("FuelGauge"); // FuelGauge wake up if needed if (FuelGauge.isSleeping()) { FuelGauge.wake(); delay(100); } // Get the voltage, battery percent // and other properties. battery_percent = FuelGauge.percent(); if (battery_percent > 95.0) { display.drawInvertedBitmap(0, 0, battery_100, 32, 32, GxEPD_BLACK); } else if (battery_percent > 75.0) { display.drawInvertedBitmap(0, 0, battery_75, 32, 32, GxEPD_BLACK); } else if (battery_percent > 50.0) { display.drawInvertedBitmap(0, 0, battery_50, 32, 32, GxEPD_BLACK); } else if (battery_percent > 25.0) { display.drawInvertedBitmap(0, 0, battery_25, 32, 32, GxEPD_BLACK); } else { display.drawInvertedBitmap(0, 0, battery_0, 32, 32, GxEPD_BLACK); } display.print(" "); display.print(battery_percent); display.print("% / "); display.print(FuelGauge.voltage()); display.println("V"); if (FuelGauge.alertIsActive()) { display.drawInvertedBitmap(259, 0, warning_full, 32, 32, GxEPD_RED); } // Put FuelGauge to sleep to conserve power FuelGauge.sleep(); // Serial.println("END: FuelGauge"); // Read values from the sensor // Serial.println("Temp/Humidity"); humid = th_sensor.readHumidity(); // Since the humidity reading requires the temperature we simply // retrieve the reading capture from the readHumidity() call. See the lib. temp_c = th_sensor.retrieveTemperatureC(); display.drawInvertedBitmap(0, 37, temperature, 32, 32, GxEPD_BLACK); display.println(); display.print(" "); display.print(temp_c * 9/5 + 32); display.print("F"); display.print(" / "); display.print(temp_c); display.println("C"); display.drawInvertedBitmap(0, 69, humidity, 32, 32, GxEPD_BLACK); display.println(); display.print(" "); display.print(humid); display.println("%"); // Serial.println("END: Temp/Humidity"); // Flush display output // Serial.println("Flushing display buffer"); while (display.nextPage()); // Serial.println("END: Flushing display buffer"); // Hibernate the display to save power display.hibernate(); // Delay looping (deep sleep goes here in the future) // Serial.println("Delay"); delay(HOUR); // Serial.println("END: Delay"); }