Hi all,
I'm having a bit of an issue with a 2.9" Waveshare E-Paper BW V2 display, used together with an Arduino Nano ESP32 microcontroller.
Specifically, I have a function that draws some text and normally performs a partial update, with a full update being performed every 10 refreshes, with 20 seconds between refreshes. To keep track of the refreshes a "bootCount" variable is used.
For testing and easier flashing I disabled the controller's deep sleep while simulating the behaviour of the bootCount variable and the successive calls to the display drawing function - in this case everything works flawslessly and the display stays crisp.
If, however, I enable the "real" deep sleep of the controller and use the display.init additional parameters to avoid a full refresh except on the first "real" boot, on successive partial refreshes the updated characters look very fuzzy. Once the threshold for a full refresh is reached, the display is crisp, but once again becomes fuzzy in the updated areas during partial refreshes.
The full (short) code follows - to switch between the two behaviours it's enough to change the "testing" boolean to either true or false.
// https://github.com/ZinggJM/GxEPD/tree/master
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include <GxEPD2_7C.h>
// constructor for AVR Arduino, copy from GxEPD_Example else
GxEPD2_BW<GxEPD2_290_T94_V2, GxEPD2_290_T94_V2::HEIGHT> display(GxEPD2_290_T94_V2(/*CS=5*/ SS, /*DC=*/9, /*RST=*/8, /*BUSY=*/7)); // GDEM029T94 128x296, SSD1680, Waveshare 2.9" V2 variant
// FreeFonts from Adafruit_GFX
#include <Fonts/FreeMonoBold9pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <Fonts/FreeMonoBold18pt7b.h>
#include <Fonts/FreeMonoBold24pt7b.h>
const GFXfont* f = &FreeMonoBold18pt7b;
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 10 /* Time ESP32 will go to sleep (in seconds) */
unsigned long currentMillis;
unsigned long previousTempRHMillis;
unsigned long tempRHInterval = 1000;
RTC_DATA_ATTR int bootCount = 0;
float t;
float rh;
bool testing = true; // If true disables deep sleep and fakes bootCount variable, in addition to separately calling a display refresh a number of times
Adafruit_BME280 bme; // I2C
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(1000);
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
//Print the wakeup reason for ESP32
print_wakeup_reason();
/*
First we configure the wake up source
We set our ESP32 to wake up every 5 seconds
*/
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");
// Initialize sensor
unsigned status = bme.begin(0x76);
// Initialize e-paper display
if (bootCount == 1) {
display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
} else {
display.init(115200, false, 2, false); // Omits initial full refresh on successive restarts after deep sleep
}
// Measure conditions
measureTemp();
measureRH();
drawDataOnDisplay();
// For testing without deep sleep - simulate bootCount and use it for partial update
if (testing == true) {
for (int i = 0; i < 100; i++) {
bootCount++;
drawDataOnDisplay();
delay(TIME_TO_SLEEP*1000);
}
}
// Going to deep sleep
Serial.println("Going to sleep now");
delay(1000);
Serial.flush();
if (testing == false) {
esp_deep_sleep_start();
}
Serial.println("This will never be printed");
}
void loop() {
}
void measureTemp() {
t = bme.readTemperature();
Serial.print("Temperature: ");
Serial.print(t);
Serial.println(" °C");
}
void measureRH() {
rh = bme.readHumidity();
Serial.print("Humidity = ");
Serial.print(rh);
Serial.println(" %");
}
void drawDataOnDisplay() {
display.setTextColor(GxEPD_BLACK);
display.setRotation(3);
display.setFont(f);
display.setFullWindow();
display.fillScreen(GxEPD_WHITE);
display.setCursor(0, 24);
display.firstPage();
display.print("T: ");
display.print(t);
display.println(" C");
display.print("rh: ");
display.print(rh);
display.println(" %");
display.print("Bootcount: ");
display.println(bootCount);
if ((bootCount % 10) == 0) {
display.display(false); // Full update
} else {
display.display(true); // Partial update
}
display.hibernate();
}
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch (wakeup_reason) {
case ESP_SLEEP_WAKEUP_EXT0: Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1: Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER: Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD: Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP: Serial.println("Wakeup caused by ULP program"); break;
default: Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason); break;
}
}