A small solar-powered desk toy built as a gift. An ESP32-S3 drives a 240×240 TFT showing outdoor temperature and weather, local time, sunrise / sunset, and indoor temp/humidity. It dims itself on a sun-bell curve through the day, slips into a calm dark-mode "night screen" in the small hours, and — for personality — periodically runs little "doing science" animations (excavating rocks, analyzing weather, transmitting to Earth, and more). On first power-up it plays a little landing sequence — descending onto an alien surface before the UI appears. An RGB LED breathes to indicate battery state.
| Part | Detail |
|---|---|
| MCU | ESP32-S3 SuperMini (HW-747), run at 80 MHz |
| Display | ST7789 240×240 IPS, 8-pin SPI, driven via Adafruit_ST7789 + Adafruit_GFX |
| Sensor | SHT31 temp/humidity (I2C 0x44) on GPIO 8/9 |
| LED | Single WS2812B (NeoPixel) on GPIO 48 |
| Battery | LiPo 3.7 V, 2000 mAh |
| Solar | 0.6 W / 5 V mini panel (≈120 mA peak in full sun) |
| Charger | TP4056 (solar → battery), separate boost (5 V) → ESP32 5V pin |
| Power switch | SPST inline on the boost output (VOUT+ → switch → 5V pin) |
| Battery sense | 2×100 kΩ voltage divider on GPIO 4 |
| Screen | GPIO |
|---|---|
| BLK | 12 (PWM backlight) |
| CS | 11 |
| DC | 10 |
| RES | 5 |
| SDA (MOSI) | 6 |
| SCL (SCLK) | 7 |
| VCC | 3V3 |
| GND | GND |
- Outdoor weather — temperature, condition icon (WMO code), sunrise/sunset via Open-Meteo (no API key), refreshed every 30 min during waking hours (radio stays off at night).
- Geolocation — city name and coordinates via ipapi.co.
- Clock — 12-hour time + date synced via NTP, timezone from the weather API. Repaints only when the displayed minute changes.
- Indoor readout — SHT31 temp (°F) and humidity (%), 2 decimals.
- Sun-curve backlight — brightness follows a sunrise → solar-noon → sunset bell: brightest (~11%) at midday, ~2% at the daylight edges, ~1.5% overnight.
- Night screen (1:00–5:30 AM) — instead of blanking, a dark-mode screen (muted greens/purples + a crescent moon) runs on cached data with WiFi off. A "goodnight" wind-down and a "good morning" wake-up animation bracket it.
- Science activities — every ~16–32 min the lander takes over the screen for ~15 s with a cute animation, then hands back to the clock: EXCAVATING, ANALYZING WX, TRANSMITTING, STAR CATALOG, DIAGNOSTICS, SEISMOMETER, PANORAMA. Two more fire reactively — SOLAR ARRAY when the battery is charging from the sun, and AUX REACTOR when running on USB power. Suppressed during quiet hours.
- Battery indicator — color-coded icon (green/yellow/red), or "USB" when on external power.
- LED breath — a slow pulse-then-rest heartbeat, color-coded by battery state (blue unknown, red low, yellow mid, green good). Its brightness tracks the same sun-curve as the screen, so it dims through the day and at night.
- Boot sequence — only on first boot (background refreshes stay silent): a retro spaceship over a scrolling starfield during connect/fetch, a friendly animated "RETRYING" screen if the network hiccups, then the lander descends to an alien surface — TOUCHDOWN (dust kick-up) and INITIALIZING (antenna beacon + status lights) — before wiping to the live UI.
The continuous draw is dominated by the always-awake CPU (~23 mA at 80 MHz); backlight, display, and LED are each single-digit mA. Through the boost→LDO supply chain that works out to roughly ~46 mA from the battery.
| Estimate | |
|---|---|
| Average battery draw | ~46 mA |
| Battery | 2000 mAh |
| Runtime, no light | ~1.8 days per charge |
The 0.6 W panel charges the LiPo through the TP4056. In full direct sun it delivers ~100–120 mA — more than the device draws — so it runs and recharges at the same time and can stay topped up indefinitely. To be net-neutral over a full 24 h it needs the panel to average the ~46 mA draw (~1,100 mAh/day), i.e. roughly 10 full-sun-equivalent hours.
In practice (e.g. on a windowsill in a cloudy climate), the panel is a life-extender rather than a full power source: expect a recharge every ~2–3 days, longer in a bright south/west window, with the 2000 mAh battery buffering through gloomy stretches. Placement in real direct sun is the single biggest factor.
Note: the supply path boosts the LiPo to 5 V and then drops it back to 3.3 V, wasting ~30–40% in conversion. A single 3.3 V buck off the LiPo would be the largest efficiency win available (hardware change).
Requires PlatformIO and an include/secrets.h
(copy include/secrets.example.h). List one or more WiFi networks — the
strongest one in range is used:
#define WIFI_NETWORKS \
WIFI_AP("home-ssid", "home-pass") \
WIFI_AP("phone-ssid", "phone-pass")pio run # build
pio run -t upload # flash (use the ESP32's own USB-C port, not the TP4056)
pio device monitor # serial monitor (115200)Pure logic (battery discharge curve, weather-code mapping) has host-side unit
tests under test/ — no hardware needed:
pio test -e native