{"id":51327796,"url":"https://github.com/sfrechette/astro-micro-station","last_synced_at":"2026-07-01T20:02:40.623Z","repository":{"id":358723533,"uuid":"1235856819","full_name":"sfrechette/astro-micro-station","owner":"sfrechette","description":"A standalone astronomy display for the LILYGO T-Display S3 Pro (ESP32-S3).   Tracks the sun, moon, and light conditions — sunrise, sunset, golden hour, blue hour, twilight phases, moon phase and illumination — across four touch-navigated screens. Data fetched from ipgeolocation.io and cached locally for offline use.","archived":false,"fork":false,"pushed_at":"2026-06-15T21:00:12.000Z","size":684,"stargazers_count":15,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-15T23:04:10.742Z","etag":null,"topics":["astronomy","c","cpp","esp32","home-assistant","lilygo","lilygo-t-display-s3-pro","moon","moonphase","platformio","sunrise"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sfrechette.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-11T18:11:17.000Z","updated_at":"2026-06-15T21:00:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sfrechette/astro-micro-station","commit_stats":null,"previous_names":["sfrechette/astro-micro-station"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sfrechette/astro-micro-station","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfrechette%2Fastro-micro-station","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfrechette%2Fastro-micro-station/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfrechette%2Fastro-micro-station/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfrechette%2Fastro-micro-station/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sfrechette","download_url":"https://codeload.github.com/sfrechette/astro-micro-station/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfrechette%2Fastro-micro-station/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35020872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["astronomy","c","cpp","esp32","home-assistant","lilygo","lilygo-t-display-s3-pro","moon","moonphase","platformio","sunrise"],"created_at":"2026-07-01T20:02:39.940Z","updated_at":"2026-07-01T20:02:40.618Z","avatar_url":"https://github.com/sfrechette.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Astronomy Micro Station for LILYGO T-Display S3 Pro\n\nA standalone astronomy display for the LILYGO T-Display S3 Pro (ESP32-S3).  \nTracks the sun, moon, and light conditions — sunrise, sunset, golden hour, blue hour, twilight phases, moon phase and illumination — across four touch-navigated screens. Data fetched from ipgeolocation.io and cached locally for offline use.\n\n![Hardware](https://img.shields.io/static/v1?label=Hardware\u0026message=LilyGO%20T-Display%20S3%20Pro\u0026color=red)\n![ESP32-S3](https://img.shields.io/badge/ESP32-S3-blue)\n![Platform](https://img.shields.io/badge/Platform-PlatformIO-orange)\n![License](https://img.shields.io/badge/License-MIT-green)\n\n![screen1](docs/images/astro_01.JPEG)\n![screen1](docs/images/astro_02.JPEG)\n![screen1](docs/images/astro_03.JPEG)\n![screen1](docs/images/astro_04.JPEG)\n\n---\n\n## Screens\n\n| # | Screen | Content |\n| --- | ------ | ------- |\n| 0 | **Moon Detail** | Phase image, illumination, rise/set, altitude, azimuth, distance |\n| 1 | **Day / Sun** | Sunrise, sunset, solar noon, day length, altitude, azimuth, night begin/end |\n| 2 | **Morning Twilight** | Astronomical, nautical, civil twilight · blue hour · golden hour (AM) |\n| 3 | **Evening Twilight** | Golden hour · blue hour · civil, nautical, astronomical twilight (PM) |\n\nAll data is fetched from the [ipgeolocation.io Astronomy API](https://ipgeolocation.io/astronomy-api.html) every 15 minutes and cached to LittleFS for offline boot.\n\nEvery screen shares a common status bar at the bottom:\n\n| Position | Content |\n| -------- | ------- |\n| Bottom left | Date of last API fetch (`2026-05-11`) |\n| Bottom centre | Navigation dots (active screen highlighted) |\n| Bottom right | Time of last API fetch (`08:34:11.738`) |\n\n---\n\n## Hardware\n\n| Component | Detail |\n| --------- | ------ |\n| Board | [LilyGO T-Display S3 Pro](https://lilygo.cc/en-us/products/t-display-s3-pro?variant=43111690141877)|\n| MCU | ESP32-S3R8, 240 MHz dual-core LX7 |\n| Display | 2.33\" IPS TFT, 480×222, ST7796, SPI |\n| Touch | CST226SE capacitive (I2C) |\n| Light / Proximity | LTR-553ALS-01 (I2C, shared bus) |\n| Flash | 16 MB (6 MB app + 8 MB LittleFS) |\n| PSRAM | 8 MB OPI (Octal) |\n| Battery | Built-in 3.8 V 470 mAh + SY6970 PMIC |\n| Connectivity | WiFi 802.11 b/g/n |\n\n### GPIO Pin Map\n\n| Function | Pin |\n| -------- | --- |\n| Display MOSI | 17 |\n| Display SCLK | 18 |\n| Display MISO | 8 |\n| Display CS | 39 |\n| Display DC | 9 |\n| Display RST | 47 |\n| Backlight PWM | 48 |\n| I2C SDA (touch + sensor) | 5 |\n| I2C SCL (touch + sensor) | 6 |\n| Touch RST | 13 |\n| Touch IRQ | 21 |\n| Brightness UP button | 16 (active LOW) |\n| Brightness DOWN button | 12 (active LOW) |\n\n---\n\n## Quick Start\n\n### 1. Clone the repo\n\n```bash\ngit clone https://github.com/stephanef/astro-micro-station.git\ncd astro-micro-station\n```\n\nOpen the folder in VSCode with the PlatformIO extension installed — dependencies are resolved automatically on first build.\n\n### 2. Configure secrets\n\nCopy `include/secrets_template.h` to `include/secrets.h` and fill in your credentials:\n\n```cpp\n// Required\n#define WIFI_SSID       \"your-network\"\n#define WIFI_PASSWORD   \"your-password\"\n#define ASTRO_API_KEY   \"your-key\"        // free at ipgeolocation.io\n\n// Required — your coordinates\n#define OBSERVER_LAT    43.7001f          // decimal degrees, positive = North\n#define OBSERVER_LON    -79.4163f         // decimal degrees, negative = West\n#define OBSERVER_TZ     \"America/Toronto\"\n#define UTC_OFFSET_SEC  -18000            // EDT = -14400  |  EST = -18000\n\n// Optional — only needed if MQTT_ENABLED is defined in config.h\n#define MQTT_BROKER     \"192.168.1.x\"     // your Mosquitto broker IP\n#define MQTT_USER       \"\"                // leave empty if broker has no auth\n#define MQTT_PASS       \"\"\n```\n\nGet a free API key at [ipgeolocation.io/signup](https://app.ipgeolocation.io/signup).  \nFree tier: 1000 req/day — at 15-minute refresh this app uses ~96 req/day.\n\nTo disable Home Assistant integration entirely, comment out `#define MQTT_ENABLED` in `config.h` — the MQTT credentials in `secrets.h` are then ignored.\n\n`secrets.h` is gitignored and never committed. `config.h` (non-sensitive settings) is safe to commit as-is or copy from `config.example.h`.\n\n### 3. Build and flash\n\n```bash\npio run --target upload\npio device monitor        # 115200 baud\n```\n\nIf the board does not auto-enter flash mode:\n\n1. Hold **BOOT**\n2. Press **RESET**\n3. Release **BOOT**\n4. Run `pio run --target upload`\n\n### 4. First boot — LittleFS\n\nOn the very first boot the LittleFS partition is blank and will be formatted automatically. You will see `[LittleFS] OK` in the monitor. From that point the last successful API response is cached at `/astro_cache.json` and loaded on any boot where WiFi is unavailable.\n\n---\n\n## Navigation\n\n| Input | Action |\n| ----- | ------ |\n| **Tap** anywhere | Next screen (cycles 0 → 1 → 2 → 3 → 0) |\n| **Long press** (\u003e 0.8 s) | Toggle red night-vision mode |\n| **Wave hand** at top sensor | Wake display from dim |\n| **Brightness UP** button (IO16) | Increase backlight, hold to repeat |\n| **Brightness DOWN** button (IO12) | Decrease backlight, hold to repeat |\n\nBacklight dims automatically after `DIM_TIMEOUT_SEC` seconds of inactivity (default 30 s). Brightness level is preserved across dim/wake cycles.\n\n---\n\n## Night-Vision (Red Mode)\n\nLong-press anywhere to toggle. In red mode:\n\n- Background, cards, and text shift to deep red tones\n- Moon phase image is re-rendered as red-luminance (shading preserved)\n- Backlight target drops to `BACKLIGHT_RED_MODE` (default 60/255)\n\n---\n\n## Home Assistant Integration (optional)\n\nEnable by defining `MQTT_ENABLED` in `config.h` (already set by default).  \nSet `MQTT_TOPIC_STATUS` to your preferred base topic (default: `astronomy`).\n\n### Auto-discovery — no YAML required\n\nThe device uses **MQTT Discovery**. On every MQTT connection it publishes 19 sensor config messages to `homeassistant/sensor/astro_\u003cname\u003e/config`. Home Assistant picks these up automatically and creates a single **Astro Micro Station** device with all sensors grouped under it — no `configuration.yaml` editing needed, exactly like other auto-discovered devices.\n\nSensors registered automatically:\n\n| Sensor | Source topic |\n| ------ | ------------ |\n| Moon Phase, Moon Illumination, Moonrise, Moonset, Moon Altitude, Moon Azimuth, Moon Distance | `astronomy/moon` |\n| Sunrise, Sunset, Solar Noon, Day Length, Sun Altitude, Sun Azimuth | `astronomy/sun` |\n| Golden Hour AM, Blue Hour AM, Civil Twilight AM | `astronomy/morning` |\n| Golden Hour PM, Blue Hour PM, Civil Twilight PM | `astronomy/evening` |\n\n### MQTT topics\n\nAfter every successful API fetch (every 15 minutes) the device publishes 4 **retained** JSON topics:\n\n| Topic | Content |\n| ----- | ------- |\n| `astronomy` | `online` / `offline` (LWT — broker publishes `offline` automatically if device disconnects) |\n| `astronomy/sun` | date, time, sunrise, sunset, solar noon, day length, altitude, azimuth, distance, night begin/end, midnight |\n| `astronomy/moon` | phase, phase name, illumination %, rise, set, altitude, azimuth, angle, distance |\n| `astronomy/morning` | astronomical, nautical, civil twilight · blue hour · golden hour times |\n| `astronomy/evening` | golden hour · blue hour · civil, nautical, astronomical twilight times |\n\n### Troubleshooting — device not appearing in Home Assistant\n\n1. Go to **Settings → Devices \u0026 Services → MQTT → Configure**, subscribe to `homeassistant/sensor/astro_sunrise/config` and click **START LISTENING**. You should see a JSON config payload immediately (it is retained).\n2. If nothing appears, check the serial monitor for `[MQTT] Discovery:` lines at boot.\n3. If discovery messages are present but no device appears in HA, restart the HA MQTT integration: **Settings → Devices \u0026 Services → MQTT → Reload**.\n4. Verify broker IP and credentials match `MQTT_BROKER` / `MQTT_USER` in `config.h`.\n\nTo disable MQTT entirely, comment out `#define MQTT_ENABLED` in `config.h`.\n\n---\n\n## Serial Monitor Output\n\nKey log prefixes for diagnostics:\n\n| Prefix | Meaning |\n| ------ | ------- |\n| `[Boot]` | Startup sequence |\n| `[WiFi]` | Connection status and RSSI |\n| `[NTP]` | Time sync |\n| `[LittleFS]` | Filesystem mount result |\n| `[AstroAPI]` | HTTP fetch, parse result, cache save/load |\n| `[fetchAstro]` | Heap + PSRAM snapshot after each fetch |\n| `[Display]` | Init, sprite buffer, heap + PSRAM at boot |\n| `[Mem]` | Hourly heap + PSRAM trend (watch `min` for leaks) |\n| `[Nav]` | Screen change events |\n| `[MQTT] →` | Data topic published (sun / moon / morning / evening) |\n| `[MQTT] Discovery:` | Auto-discovery config published for one sensor |\n\nExample memory line:\n\n```text\n[Mem]  heap=186432  min=164208  maxBlock=163840  psram=7823104\n```\n\nThe `min` value is the all-time low — a steadily decreasing `min` indicates a heap leak.\n\n---\n\n## API Data — Refresh Behaviour\n\nAll fields are fetched from the API and replaced on **every 15-minute refresh** — nothing is cached selectively. The distinction below is purely about how fast the API values move, not about how often the device fetches them.\n\n### Stable throughout the day (API returns the same value all 24 h)\n\n| Field | Notes |\n| ----- | ----- |\n| Sunrise / Sunset | Set once at midnight for the date |\n| Solar noon | Set once for the date |\n| Day length | Set once for the date |\n| Night begin / end | Set once for the date |\n| Astronomical / Nautical / Civil twilight | All begin/end times set for the date |\n| Blue hour begin / end (AM \u0026 PM) | Set for the date |\n| Golden hour begin / end (AM \u0026 PM) | Set for the date |\n| Moonrise / Moonset | Set for the date |\n| Moon phase | Changes once every ~3.7 days |\n| Moon illumination | Changes by \u003c 1 % per hour |\n\n### Continuously changing (visibly different each 15-minute fetch)\n\n| Field | Rate of change |\n| ----- | -------------- |\n| Sun altitude | ~15° per hour near transit |\n| Sun azimuth | ~15° per hour |\n| Moon altitude | ~0.5° per hour |\n| Moon azimuth | ~0.5° per hour |\n| Moon distance | Tens of km per hour (perigee/apogee drift) |\n| Fetch date / time (`fetchDate` / `currentTime`) | Timestamp of the API call — updates every fetch |\n\n---\n\n## Adjusting for Your Location\n\nIn `include/secrets.h`:\n\n```cpp\n#define OBSERVER_LAT    43.7001f          // decimal degrees, positive = North\n#define OBSERVER_LON    -79.4163f         // decimal degrees, negative = West\n#define OBSERVER_TZ     \"America/Toronto\"\n#define UTC_OFFSET_SEC  -18000            // EDT = -14400  |  EST = -18000\n```\n\n---\n\n## File Structure\n\n```text\nastro-micro-station/\n├── platformio.ini              # Build config, libraries, pin definitions\n├── partitions_custom.csv       # 6 MB app / 8 MB LittleFS\n├── include/\n│   ├── secrets.h               # ⚠ gitignored — WiFi, API key, MQTT creds, coordinates\n│   ├── secrets_template.h      # Safe template — copy to secrets.h and fill in\n│   ├── config.h                # Non-sensitive settings (safe to commit)\n│   ├── config.example.h        # Template for config.h\n│   ├── AstroAPI.h              # ipgeolocation.io data structures + class\n│   ├── DisplayManager.h        # Colour palette, screen class declaration\n│   ├── MQTTManager.h           # HA status publisher (stub when disabled)\n│   ├── icons.h                 # ICON_ASTRO — 22×22 RGB565 PROGMEM\n│   └── moon_icons.h            # 8 moon phase images — 155×155 RGB565 PROGMEM\n├── src/\n│   ├── main.cpp                # Setup, loop, WiFi, NTP, touch FSM, brightness\n│   ├── AstroAPI.cpp            # HTTP fetch, JSON parse, LittleFS cache\n│   ├── DisplayManager.cpp      # All screen rendering\n│   └── MQTTManager.cpp         # MQTT connection + discovery + data publish\n└── assets/\n    ├── moon-phases/            # Source SVGs for moon phase images (8 files)\n    ├── icons/                  # Source PNG for header icon\n    └── tools/\n        └── svg_to_h.py         # Converts SVGs → moon_icons.h (run in venv)\n```\n\n---\n\n## Regenerating Moon Phase Images\n\nThe moon phase header file is generated from SVG sources using a Python script:\n\n```bash\ncd assets/tools\npython3 -m venv venv \u0026\u0026 source venv/bin/activate\npip install cairosvg pillow\npython3 svg_to_h.py\n# output written to include/moon_icons.h\n```\n\nSource files are in `assets/moon-phases/`. The script renders each SVG to 155×155 greyscale RGB565, alpha-composited on black, with `0xFFFF` as the chroma key for transparency.\n\n---\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/sfrechette/astro-micro-station/issues)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsfrechette%2Fastro-micro-station","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsfrechette%2Fastro-micro-station","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsfrechette%2Fastro-micro-station/lists"}