Thanks PeteKnight. Since you asked for it here’s the entire sketch. It was working perfectly until I added in Blynk. I’ve stripped out the Blynk auth token, wifi username and password for security. I do have serial print and debug enabled but neither have produced any clues that are useful for troubleshooting this.
#include <Arduino.h>
#include <TFT_eSPI.h>
#include <Button2.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <driver/adc.h>
#include <TJpg_Decoder.h>
#include <FS.h>
#include "SPI.h"
#include "SPIFFS.h"
#include "esp_adc_cal.h"
#define FS_NO_GLOBALS
#define BLYNK_TEMPLATE_ID "TMPL7YmZ1ldk"
#define BLYNK_DEVICE_NAME "TTGOTDisplay"
#define BLYNK_AUTH_TOKEN "REDACTED"
#define BLYNK_PRINT Serial
#define BLYNK_DEBUG
#define BUTTON2_PIN 35
#define BUTTON1_PIN 0
Button2 button1;
Button2 button2;
// Define our tft and a single sprite
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite img = TFT_eSprite(&tft);
// define creates a mini function or alias
// need this for the wakeup function!
#define BUTTON_PIN_BITMASK 0x800000000 // 2^35 in hex
// Allows us to store data even during sleep
// https://savjee.be/videos/programming-esp32-with-arduino/using-rtc-memory/
RTC_DATA_ATTR int bootCount = 0;
// Text string for display of data
char text[] = "Hello World";
const char *SSID = "MYSSIDHERE";
const char *PASSWORD = "secretpassword";
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
// Variable for formatted time
String formattedTime;
unsigned long time_now = millis();
// Blynk timer
BlynkTimer timer;
// Function for use with TJpgDec.setCallback(img_output)
bool img_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
if ( y >= img.height() ) return 0;
img.pushImage(x, y, w, h, bitmap);
return 1;
}
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;
}
}
void b1handler(Button2& btn) {
switch (btn.getType()) {
case single_click:
Serial.println("b1 single");
strcpy(text,"b1 single");
img.drawString(text,20,20,4);
img.pushSprite(0,0);
time_now = millis();
break;
case double_click:
Serial.println("b1 double");
strcpy(text,"b1 double");
img.drawString(text,20,20,4);
img.pushSprite(0,0);
time_now = millis();
break;
case triple_click:
Serial.println("b1 triple");
strcpy(text,"b1 triple");
img.drawString(text,20,20,4);
img.pushSprite(0,0);
time_now = millis();
break;
case long_click:
Serial.println("b1 long");
strcpy(text,"b1 long");
img.drawString(text,20,20,4);
img.pushSprite(0,0);
time_now = millis();
//Serial.println("long press complete. Sleeping.");
//esp_deep_sleep_start();
break;
}
Serial.print("click");
Serial.print(" (");
Serial.print(btn.getNumberOfClicks());
Serial.println(")");
}
void b2handler(Button2& btn) {
switch (btn.getType()) {
case single_click:
Serial.println("b2 single");
strcpy(text,"b2 single");
img.drawString(text,20,20,4);
img.pushSprite(0,0);
time_now = millis();
break;
case double_click:
Serial.println("b2 double");
strcpy(text,"b2 double");
img.drawString(text,20,20,4);
img.pushSprite(0,0);
time_now = millis();
break;
case triple_click:
Serial.println("b2 triple");
strcpy(text,"b2 triple");
img.drawString(text,20,20,4);
img.pushSprite(0,0);
time_now = millis();
break;
case long_click:
Serial.println("b2 long");
strcpy(text,"b2 long");
img.drawString(text,20,20,4);
img.pushSprite(0,0);
Serial.println("long press complete. Sleeping.");
esp_deep_sleep_start();
time_now = millis();
break;
}
Serial.print("click");
Serial.print(" (");
Serial.print(btn.getNumberOfClicks());
Serial.println(")");
}
void displayInit(){
tft.begin();
tft.setRotation(1);
tft.setTextColor(TFT_DARKGREEN,TFT_BLACK);
tft.setSwapBytes(true);
tft.fillScreen(TFT_BLACK);
tft.setTextFont(2);
}
void gradientTest(){
img.fillRectHGradient(0, 0, 240, 135, TFT_YELLOW, TFT_BLUE);
img.pushSprite(0,0);
delay(1000);
img.fillRect(0,0,240,135,TFT_BLACK);
}
void batteryMonitorSetup(){
esp_adc_cal_characteristics_t adc_chars;
esp_adc_cal_value_t val_type = esp_adc_cal_characterize((adc_unit_t)ADC_UNIT_1, (adc_atten_t)ADC_ATTEN_DB_2_5, (adc_bits_width_t)ADC_WIDTH_BIT_12, 1100, &adc_chars);
pinMode(14, OUTPUT);
}
void blynkTimerEvent()
{
digitalWrite(14, HIGH);
delay(1);
float measurement = (float) analogRead(34);
float battery_voltage = (measurement / 4095.0) * 7.26;
digitalWrite(14, LOW);
Serial.println(battery_voltage);
Blynk.virtualWrite(battery_voltage, millis() / 1000);
}
void setup() {
// Fire up the serial port
Serial.begin(115200);
while (!Serial) {
delay(20);
}
// Initialise SPIFFS to enable access to files in /data
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialization failed!");
while (1) yield();
}
Serial.println("\r\nSPIFFS initialization done.");
// ESP32 will crash if any of the fonts are missing
bool font_missing = false;
if (SPIFFS.exists("/weathericons40.vlw") == false) font_missing = true;
if (font_missing)
{
Serial.println("\r\nFont missing in SPIFFS, did you upload it?");
while(1) yield();
}
else Serial.println("\r\nFonts found OK.");
batteryMonitorSetup();
// Initialize our TFT display
displayInit();
tft.print("Connecting to ");
tft.println(SSID);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(300);
tft.print(".");
}
tft.println("");
tft.println("WiFi connected.");
tft.println("IP address: ");
tft.println(WiFi.localIP());
timeClient.begin();
timeClient.setTimeOffset(-18000);
timeClient.update();
timer.setInterval(1000L, blynkTimerEvent);
formattedTime = timeClient.getFormattedTime();
tft.print("The time is: ");
tft.println(formattedTime);
tft.println("Connecting to Blynk...");
Blynk.config(BLYNK_AUTH_TOKEN);
Blynk.connect();
while (Blynk.connect() == false) {
// Wait until connected
Serial.println("Trying to connect...");
delay(1000);
}
tft.println("Connected to Blynk server.");
delay(3000);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
// Right button on T-Display is GPIO_NUM_35
// pinMode(GPIO_NUM_35, INPUT);
//esp_sleep_enable_ext0_wakeup(GPIO_NUM_35,0); //1 = High, 0 = Low
esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ALL_LOW);
button1.begin(BUTTON1_PIN);
button1.setClickHandler(b1handler);
button1.setLongClickHandler(b1handler);
button1.setDoubleClickHandler(b1handler);
button1.setTripleClickHandler(b1handler);
button2.begin(BUTTON2_PIN);
button2.setClickHandler(b2handler);
button2.setLongClickHandler(b2handler);
button2.setDoubleClickHandler(b2handler);
button2.setTripleClickHandler(b2handler);
TJpgDec.setJpgScale(1);
TJpgDec.setCallback(img_output);
img.createSprite(240,135);
//gradientTest();
img.setTextColor(TFT_DARKGREEN, TFT_BLACK);
img.setTextPadding(160);
img.drawString(text,20,20,4);
img.loadFont("weathericons40");
img.setCursor(180,0);
img.setTextColor(TFT_BLUE, TFT_BLACK);
img.print("");
img.unloadFont();
img.setTextColor(TFT_DARKGREEN, TFT_BLACK);
//TJpgDec.drawFsJpg(170, 0, "/battery_01.jpg");
img.pushSprite(0,0);
//delay(1000);
}
void loop() {
if ( (millis() - time_now) > 60000) {
// Serial.println("Time has passed.");
// esp_deep_sleep_start();
;
}
button1.loop();
button2.loop();
img.drawString(timeClient.getFormattedTime(),5,70,7);
img.pushSprite(0,0);
Blynk.run();
timer.run();
//Serial.println(blevel);
}