Documented the changes and fixes in version 6.1.0, including improvements to market day detection and retry logic after midnight.
Electricity Price Ticker for XIAO ESP32‑C3 (Slovenia, Energy‑Charts)
This project is an Arduino‑IDE‑friendly firmware for the Seeed XIAO ESP32‑C3 that:
- Connects to Wi‑Fi.
- Fetches day‑ahead electricity prices for Slovenia from Energy‑Charts.info.
- Computes final consumer prices (including configurable fees + VAT).
- Displays current and upcoming prices on a 20x4 I²C 2004 LCD.
- Uses an LED and presence sensor to give quick visual feedback.
The code currently implements Version 6.0 of the ticker, focusing on:
- Daily (not hourly) API fetching.
- Robust NVS storage of daily price data for resilience to reboots.
- Automatic CET/CEST handling.
- Preserved UI and button behavior from v5.5.
All available bidding zones (modify in the code):
- AT - Austria
- BE - Belgium
- BG - Bulgaria
- CH - Switzerland
- CZ - Czech Republic
- DE-LU - Germany, Luxembourg
- DE-AT-LU - Germany, Austria, Luxembourg
- DK1 - Denmark 1
- DK2 - Denmark 2
- EE - Estionia
- ES - Spain
- FI - Finland
- FR - France
- GR - Greece
- HR - Croatia
- HU - Hungary
- IT-Calabria - Italy Calabria
- IT-Centre-North - Italy Centre North
- IT-Centre-South - Italy Centre South
- IT-North - Italy North
- IT-SACOAC - Italy Sardinia Corsica AC
- IT-SACODC - Italy Sardinia Corsica DC
- IT-Sardinia - Italy Sardinia
- IT-Sicily - Italy Sicily
- IT-South - Italy South
- LT - Lithuania
- LV - Latvia
- ME - Montenegro
- NL - Netherlands
- NO1 - Norway 1
- NO2 - Norway 2
- NO2NSL - Norway North Sea Link
- NO3 - Norway 3
- NO4 - Norway 4
- NO5 - Norway 5
- PL - Poland
- PT - Portugal
- RO - Romania
- RS - Serbia
- SE1 - Sweden 1
- SE2 - Sweden 2
- SE3 - Sweden 3
- SE4 - Sweden 4
- SI - Slovenia
- SK - Slovakia
Features
Core display & pricing
- Data source: Energy‑Charts.info day‑ahead price API (bidding zone =
SI). - Resolution:
- Prices in 15‑minute intervals (4 per hour).
- Display shows:
- Current hour:
- Hourly average.
- Four 15‑minute prices in compact format (
XX XX XX XX).
- Next 2 hours’ averages.
- Current hour:
- Price calculation:
- Raw MWh prices from API are converted to EUR/kWh.
- Optional surcharges:
POWER_COMPANY_FEE_PERCENTAGE(default 12%).VAT_PERCENTAGE(default 22%).
- LCD:
- 20x4 I²C (PCF8574 / 0x27).
- Custom characters for local language and low/high price markers.
LED behavior
- One white LED connected to GPIO 5.
- LED indicates current 15‑minute segment price:
- Very cheap (
<= 0.05 EUR/kWh): smooth breathing. - Cheap, normal, expensive, very expensive: different steady / blinking / double‑blink patterns.
- Negative or no data: LED off.
- Very cheap (
Presence sensor & backlight
- Optional RCWL‑0516 presence sensor on GPIO 9:
- Presence = backlight on, LED enabled.
- No presence for a while = LCD backlight off, LED disabled.
- If no presence sensor is detected, the backlight is kept on.
Button behavior
- One button (or capacitive touch) on GPIO 4.
- Uses internal pull‑up by default.
- Actions:
- Single short press:
- Scrolls through the hourly view on the primary screen.
- Double press:
- Toggles between:
- Primary price view
- Secondary info view
- Toggles between:
- Long press (≈3s in your current repo):
- Forces a manual data refresh (API fetch), regardless of daily schedule.
- Single short press:
Version 6.0 – Daily Fetch + NVS Storage
Version 6.0 is focused on:
- Reducing API calls
- Persisting daily data in NVS
- Making the device robust to power outages
1. Daily fetch instead of hourly
Previously (v5.5), the firmware fetched data every hour at the top of the hour.
In v6.0, the behavior is:
- On boot (after Wi‑Fi + time sync):
- Try to load today’s data from NVS:
- If found: use it directly, no API call at boot.
- If not found or invalid: schedule an immediate API fetch.
- Try to load today’s data from NVS:
- After midnight (local time):
- Detect day rollover via localtime.
- Immediately:
- Invalidate yesterday’s data (
isTodayDataAvailable = false). - Force display to show “No data for today”.
- Turn off the white LED (no price indication).
- Enter midnight fetch phase.
- Invalidate yesterday’s data (
Midnight fetch phase
When the date changes:
- First fetch is scheduled immediately.
- If it fails:
- The device stays in “No data for today”, LED off.
- Retry schedule:
- 10‑minute interval, up to 5 attempts.
- After 5 failures, retry once at each top of the hour until it succeeds.
As soon as a fetch for today succeeds:
isTodayDataAvailableis set totrue.- The enforced
NO_DATA_OFFSETstate is cleared back toCURRENT_PRICES. - The LCD and LED resume showing today’s prices.
Importantly, yesterday’s data is never re‑used for today, both at boot and after midnight.
2. NVS (non‑volatile) storage of daily data
The ESP32‑C3’s built‑in NVS is used via Preferences:
- Namespace:
"my-ticker". - Keys (in addition to the existing Wi‑Fi credentials):
data_day,data_mon,data_year– calendar date of the stored data.data_prc– full raw JSON response from the Energy‑Charts API.data_last_store– UNIX timestamp when the data was last written.
On boot
After time sync:
- If NVS has data whose date matches today:
data_prcJSON is deserialized into the in‑RAMdoc(StaticJsonDocument).processJsonData()is run, just like after a live fetch.isTodayDataAvailable = true.- No initial API call is needed.
- If the stored date does not match today (or parsing fails):
- The stored data is ignored for display.
- The system starts from “No data for today” and will fetch new data.
After each successful fetch for today
- The entire JSON payload is stored as
data_prcwith the corresponding date and timestamp. - This means:
- A reboot later in the same day can immediately restore the latest prices from NVS.
- Reboots the next morning will detect the date mismatch and fetch new data instead of showing stale data.
3. Secondary info (status) screen
The secondary menu (double‑click to toggle) has 20 lines, shown in 4‑line pages.
It typically includes:
- Current date and time.
- Last successful update timestamp.
- Daily average price in EUR/kWh (with company fee + VAT applied).
- Wi‑Fi RSSI and IP address.
- API success ratio and total calls.
- Device uptime.
- NVS status section:
NVS status:Data day: DD.MM.YYYYorData day: noneLast save: DD.MM.YYorLast save: noneNVS: OK (today)/NVS: old data/NVS: empty
- Credits + version line:
energy-charts.infodynamic electricityprice ticker v6.0by Amir Toki^ 2025
(Exact ordering and layout may differ slightly, based on your latest edits.)
Hardware setup
Microcontroller
- Seeed XIAO ESP32‑C3
LCD (I²C 2004)
- 20x4 (2004) character LCD with I²C backpack (PCF8574).
- Default I²C address:
0x27(configurable in code). - Library:
LiquidCrystal_I2C.
Button / touch input
- GPIO 4, internal pull‑up enabled.
Mechanical pushbutton (default)
- One leg to GPIO 4, other leg to GND.
TTP223 capacitive touch (alternative)
- VCC → 3.3 V
- GND → GND
- OUT → GPIO 4
Code change required for TTP223:
// In handleButton() or wherever the button is read:
int reading = !digitalRead(buttonPin);
// Change to:
int reading = digitalRead(buttonPin); // if TTP223 output is HIGH when touched
(Your current code uses !digitalRead(buttonPin) assuming an active‑LOW mechanical button.)
Presence sensor (RCWL‑0516)
- VCC → 3.3 V
- GND → GND
- OUT → GPIO 9
- 10 kΩ pull‑down resistor between GPIO 9 and GND.
If no sensor is detected at boot, the firmware keeps the LCD backlight always on.
White LED
- LED (with appropriate series resistor) on GPIO 5.
Wi‑Fi provisioning
If stored Wi‑Fi credentials are invalid or missing:
- Device starts in AP mode with SSID:
MyTicker_Setup. - DNS server redirects to a simple captive “Wi‑Fi Setup” page.
- You can enter SSID and password, which are stored in NVS (
Preferences). - The device restarts and attempts to connect with the new credentials.
Building and flashing
- Open the
.inofile in Arduino IDE (ensure ESP32 board support is installed). - Select:
- Board:
Seeed XIAO ESP32C3 - Port: correct serial port
- Board:
- Install the required libraries if missing:
LiquidCrystal_I2CArduinoJson
- Compile and upload.
Versioning and files
Key documentation files:
VERSION.md– current firmware version and compatibility notes.CHANGELOG.md– detailed list of changes between versions.*.ino– main firmware source file (v6.0 and later).
License
This project is licensed under the MIT License – see the LICENSE file for details.