diff --git a/m5paper-stockticker.ino b/m5paper-stockticker.ino index b65fff2..876d95a 100644 --- a/m5paper-stockticker.ino +++ b/m5paper-stockticker.ino @@ -1,12 +1,26 @@ -#include +// ======================================================= +// M5Paper Stock Ticker - M5Paper v1.1 (classic ESP32) edition +// ======================================================= +// Target: M5Paper ESP32 Development Kit V1.1 (SKU K049-B) +// - ESP32-D0WDQ6-V3, 540x960 @4.7" e-ink (IT8951E), BM8563 RTC +// +// Difference vs. the main sketch (../m5paper-stockticker.ino): +// The classic M5Paper's low-power management differs from newer boards, +// so sleep/wake is handled through M5Unified's board-aware power API +// (M5.Power.deepSleep) instead of a raw esp_deep_sleep_start() with a +// manual radio teardown. deepSleep() puts the e-ink panel to sleep and +// drops the board to its rated ~10uA deep-sleep state, waking on the +// ESP32 RTC timer (any duration, so overnight/weekend sleeps are fine). +// +// Everything else - portfolio, market-hours logic, layout - is identical. +// Copy your config.h (and images.h) into this folder before flashing. +// ------------------------------------------------------- +#include #include #include #include #include #include -#include -#include -#include #include "images.h" #include "config.h" @@ -21,6 +35,10 @@ const char* ntpServer = "pool.ntp.org"; const long gmtOffset_sec = GMT_OFFSET_SEC; const int daylightOffset_sec = DAYLIGHT_OFFSET_SEC; +// If WiFi/NTP fails, retry after this many seconds instead of powering off +// (the classic M5Paper's powerOff needs a manual button press to restart). +#define WIFI_RETRY_SECONDS 900 // 15 minutes + // ------------------------------------------------------- // Portfolio - symbol / shares / total cost basis ($) // ------------------------------------------------------- @@ -47,38 +65,6 @@ const int NUM_STOCKS = sizeof(myPortfolio) / sizeof(myPortfolio[0]); // ------------------------------------------------------- struct StockData { float price, change, pct; bool valid; }; -void prepareForSleepAndEnter(uint64_t sleepUs) { - // Disable all wake sources first, then allow only timer wake. - esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); - esp_sleep_enable_timer_wakeup(sleepUs); - - // Shut down radios and protocol stacks. - WiFi.disconnect(true, true); - WiFi.mode(WIFI_OFF); - esp_wifi_stop(); - esp_wifi_deinit(); - - btStop(); - esp_bt_controller_disable(); - esp_bt_controller_deinit(); - - // Power down optional domains where this core/target exposes them. -#ifdef ESP_PD_DOMAIN_RTC_PERIPH - esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); -#endif -#ifdef ESP_PD_DOMAIN_RTC_FAST_MEM - esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF); -#endif -#ifdef ESP_PD_DOMAIN_RTC_SLOW_MEM - esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF); -#endif -#ifdef ESP_PD_DOMAIN_XTAL - esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF); -#endif - - esp_deep_sleep_start(); -} - bool fetchStock(const char* sym, StockData& out) { out = { 0.0f, 0.0f, 0.0f, false }; if (WiFi.status() != WL_CONNECTED) { Serial.println("[FH] no WiFi"); return false; } @@ -271,11 +257,11 @@ const char* marketPhase(const struct tm& et) { return "mid"; } -// Microseconds until the next market event: the opening bell (9:30 AM ET), -// midday (12:45 PM ET), or the closing bell (4:00 PM ET), whichever comes -// first, Mon-Fri only. We wake for these three events, so the ticker refreshes -// three times per session. -uint64_t usUntilNextEvent(const struct tm& et) { +// Seconds until the next market event: the opening bell (9:30 AM ET), midday +// (12:45 PM ET), or the closing bell (4:00 PM ET), whichever comes first, +// Mon-Fri only. We wake for these three events, so the ticker refreshes three +// times per session. +uint64_t secsUntilNextEvent(const struct tm& et) { const long events[3] = { EVT_OPEN, EVT_MID, EVT_CLOSE }; long secsToday = et.tm_hour * 3600 + et.tm_min * 60 + et.tm_sec; for (int d = 0; d <= 7; d++) { @@ -287,9 +273,9 @@ uint64_t usUntilNextEvent(const struct tm& et) { long cand = base + events[e]; if (cand > 0 && (best < 0 || cand < best)) best = cand; } - if (best > 0) return (uint64_t)best * 1000000ULL; + if (best > 0) return (uint64_t)best; } - return 24ULL * 3600ULL * 1000000ULL; // fallback: 24h + return 24ULL * 3600ULL; // fallback: 24h } // ------------------------------------------------------- @@ -312,7 +298,7 @@ void setup() { M5.Display.setTextColor(TFT_BLACK, TFT_WHITE); M5.Display.setTextSize(2); M5.Display.setCursor(20, 20); - M5.Display.print("WiFi connection failed."); + M5.Display.print("WiFi connection failed - retrying later."); M5.Display.setCursor(20, 55); M5.Display.printf("SSID: %s", ssid); M5.Display.setCursor(20, 90); @@ -321,7 +307,8 @@ void setup() { M5.Display.setCursor(205, 90); M5.Display.printf("%d%%", batPct); delay(2000); - M5.Power.powerOff(); + // Don't powerOff (would need a manual restart) - nap and try again. + M5.Power.deepSleep((uint64_t)WIFI_RETRY_SECONDS * 1000000ULL, false); return; } @@ -420,17 +407,14 @@ void setup() { } } - // Page indicator - // M5.Display.setTextSize(1); - // M5.Display.setCursor(890, 525); - //M5.Display.print("Pa. 1/1"); - M5.Display.endWrite(); delay(1000); // We wake at open, midday, and close, so update now and sleep until - // whichever event comes next (Mon-Fri). - prepareForSleepAndEnter(usUntilNextEvent(etTm)); + // whichever event comes next (Mon-Fri). M5.Power.deepSleep handles the + // classic M5Paper's e-ink + power-down and wakes on the ESP32 RTC timer. + WiFi.disconnect(true, true); + M5.Power.deepSleep(secsUntilNextEvent(etTm) * 1000000ULL, false); } -void loop() {} \ No newline at end of file +void loop() {}