Overview

The Weather Globe.

The Weather Globe is a standalone, internet-connected desk display built on an ESP32-S3 microcontroller. Utilizing a 1.75" round AMOLED screen, the device acts as a live window onto Earth and the solar system. Its primary feature is a real-time, sun-synchronous rendering of Earth, complete with accurate day/night shadow lines, live cloud cover pulled from NASA VIIRS satellites and refreshed in the background, and illuminated city lights on the night side.

Operating entirely on the device without the need for companion mobile apps or cloud accounts, it features a built-in captive portal for WiFi configuration and a web-based settings dashboard.

Features

Key Features

Live Sun-Synchronous Earth

Calculates the real-time position of the sun to accurately drape a soft twilight terminator (day/night line) across the globe.

Real-Time Satellite Data

Automatically fetches and maps live cloud cover from NASA's VIIRS satellites, layering it over the base map.

Dynamic Night Lights

Renders NASA "Black Marble" city lights exclusively on the shadowed hemisphere of the Earth.

Multi-Planetary Exploration

Allows users to switch the view to any of 10 celestial bodies: Earth, Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, the Moon, and the Sun.

Local Time & Weather Card

On a user-defined schedule, the globe smoothly transitions to a full-screen, data-rich card displaying local time, date, temperature, "feels like" temperature, humidity, and wind speed.

Web Settings Portal

Hosts a local web server (accessible via the device's IP) to adjust motion speed (true 24-hour rotation vs. smooth time-lapse), brightness, camera tilt, screen rotation, and weather card cadence.

Hardware

Specifications.

  • Display: 1.75" round AMOLED, 466 × 466 pixel resolution (CO5300 QSPI driver).
  • Microcontroller: LilyGo T-Display-S3 (Espressif ESP32-S3, dual-core 240 MHz).
  • Memory: 8 MB PSRAM / 16 MB Flash.
  • Connectivity: WiFi 802.11 b/g/n (2.4 GHz).
  • Power: 5V via USB-C.
Software

Architecture.

  • Firmware: Written in C++ using PlatformIO and the Arduino framework.
  • Multi-Threading: Utilizes FreeRTOS to divide labor across the ESP32-S3's two cores. Core 1 runs the render loop uninterrupted for smooth, drift-free globe rotation, while Core 0 manages the cloudTask and infoTask with atomic texture and weather buffer swaps to prevent visual stutter during network calls.
  • Data APIs: Integrates entirely free, no-key public APIs: NASA GIBS/VIIRS (clouds/maps), ip-api (IP-based rough geolocation), Open-Meteo (hyper-local weather), and NTP (time synchronization).
  • Offline Resilience: If the network drops, the globe seamlessly continues its rotation using the most recently cached time and cloud assets, automatically resuming background updates when the connection is restored.
  • Host-Side Tooling: Includes a Python backend suite for generating planet textures, night-light maps, and font/icon atlases. Because the physical SPI screen cannot be easily captured, the backend includes visual verification scripts to preview and test visual changes locally before flashing.
At A Glance

Embedded Precision

Most "Earth globe" gadgets use static textures spinning on a timer. This project calculates the true subsolar point (NOAA solar position) for the current UTC, downloads NASA VIIRS daily cloud mosaics, and additively blends NASA Black Marble city lights on the night side.

Rendering

Spherized Math

A precomputed lookup table maps every pixel on the round display to a geographic normal. The rendering thread shades day to night using a smootherstep terminator with 8×8 Bayer dithering to prevent RGB565 color banding.

Pipelines

NASA Cloud Ingest

A dedicated RTOS task fetches a NASA VIIRS true-color snapshot from the EarthData WVS snapshot API, decodes the JPEG in memory into a 1024×512 buffer, feathers the dateline seam, and publishes the new texture atomically via pointer-swap. It re-fetches roughly every 3 hours once online (and retries within ~10 minutes after a failed download).

Verification

Host Replicas

Because AMOLED screens can't easily be screenshotted, the firmware rendering engine has a Python replica on the desktop. Visual changes are previewed against the replica before being flashed.

Robustness

Cloud Completeness

The fiddliest piece. A freshly-built daily mosaic has missing satellite swaths, so the firmware judges completeness by counting no-data pixels only in the mid-latitude band (≈±45°) — polar night is legitimately black and must not count as a gap. If that band exceeds ~5% missing the day is rejected and the task steps back day-by-day (up to 7 days) to the most recent fully-assembled mosaic. Any remaining no-data pixels are filled from a Blue Marble base image, so the globe never shows a black void — or an invented cloud — as it spins.

By The Numbers

Scope

Honest figures, read straight from the repository — a small, single-purpose firmware plus the host tooling that feeds it.

~1,460 lines

The entire device program in one file, firmware/src/main.cpp (C++ / Arduino), backed by ~3,500 lines of Python host tooling in backend/.

~11.6 MB assets

12 LittleFS binaries — eleven 1 MB RGB565 body textures plus a packed font/icon atlas — in a ~14 MB filesystem partition on the 16 MB flash.

10 bodies

Earth plus the eight other planets, the Moon and the Sun, all sun-shaded; targeting the LilyGo T-Display-S3 AMOLED (ESP32-S3, 8 MB PSRAM) via PlatformIO.

Deep-Dive Diagnostics

Engineering the Edge Cases.

The real story of embedded systems lies in the hardware edge cases. Here are three critical bugs resolved during field-testing:

1. The Odd-Aligned CO5300 AMOLED

Text rendered perfectly on the host replica but garbled randomly on the physical panel. Root cause: the CO5300 display driver passes raw x/y/w/h coordinates without rounding. Any partial SPI write with an odd dimension shifts and corrupts the hardware buffer. The fix involved strict even-padding on every text blit.

2. Sub-Second NTP Judder

During time-lapse animations, the globe would hold still for 30 frames then awkwardly lurch forward. The underlying NTP clock was bound to time(nullptr), which is whole-second granular. The fix derived a sub-second fractional offset using millis(), re-anchoring on every RTC tick to prevent wrapping, so the spin advances smoothly between whole-second clock ticks. (The render loop is unbounded — it yields once per frame and simply runs as fast as the panel allows; frame rate is measured in the serial heartbeat, not capped at a target.)

3. The Phantom Station Hotspot

When the globe was moved to a new house, the captive portal refused to load on 192.168.4.1. The ESP32's SoftAP channel strictly follows the Station radio. The radio kept hunting for the old home network saved deep in the driver, dragging the hotspot off-channel. The fix: explicitly wipe the persistent driver credentials and serve the portal in pure WIFI_AP mode.