A small Arduino sketch for the M5Stack Cardputer that displays current amateur radio (HF) propagation conditions on the built-in screen — solar activity indices, band-by-band conditions, a Sporadic-E hint for Europe, and the real, measured MUF (Maximum Usable Frequency) from a German ionosonde station.
Built for hams who want a quick, glanceable propagation readout on a pocket-sized device, without needing a phone or laptop.
73 DL2MBN
[Deutsche Version / German version: README_de.md]
- Solar indices: Solar Flux Index (SFI), A-Index, K-Index, with
trend arrows (
^/v/=) versus the last fetch - Band conditions for 80–40m, 30–20m, 17–15m and 12–10m, shown separately for day and night, color-coded (green / yellow / red)
- Sporadic-E indicator for Europe (relevant for 10m/6m VHF openings)
- Real MUF for Germany, sourced from the Juliusruh ionosonde (JR055, operated by the Leibniz Institute of Atmospheric Physics, on the island of Rügen) — both the classic MUF(3000km) used for HF DX planning, and the local value directly above the station
- Three pages (cycle with Tab): band overview, a details page with trend arrows, and a grayline page showing local time, today's sunrise/sunset for a configurable location, and whether grayline propagation is currently active
- Audible alarm: beeps when any band newly turns "Good", or when the K-Index jumps to 5+ (onset of a geomagnetic storm, G1+)
- On-device Wi-Fi setup wizard: scan for networks, select with the keyboard, type in the password — no credentials hardcoded in the source. Credentials are stored persistently in the ESP32's flash (NVS), so you only enter them once
- Grid locator location entry: set your QTH as a Maidenhead locator
(e.g.
JO31nx) directly on the device, on the Grayline page — no code edits or recompiling needed. Stored persistently, just like the Wi-Fi credentials - Battery indicator in the top-right corner (percentage + icon, color-coded, shows charging state)
- Screen timeout: display dims after 2 minutes of inactivity, any key wakes it back up
- Detailed on-screen error messages instead of a generic "no data" — Wi-Fi failures, HTTP status codes, and parsing failures are all shown with enough detail to actually debug them
- Can be flashed directly via USB, or exported as a standalone
.binand installed from an SD card using bmorcelli's M5Launcher — no PC connection required at install time
| Source | What it provides | Format |
|---|---|---|
| hamqsl.com (N0NBH Solar Data) | SFI, A-Index, K-Index, categorical band conditions, Sporadic-E | XML |
| Ionosonde Juliusruh (JR055) | Real, measured MUF over Germany | HTML (scraped) |
The hamqsl feed is a documented, stable XML API. The Juliusruh MUF table has no official API and is scraped from its HTML page — this is noticeably less stable than an XML/JSON feed, but it's the best publicly available real-time MUF data point located in Germany. If the site changes its layout, the sketch will show a clear parsing error on screen rather than silently displaying wrong numbers.
- M5Stack Cardputer (ESP32-S3, 240×135 display, physical keyboard)
- Wi-Fi network (2.4 GHz — the ESP32 cannot see 5 GHz-only networks)
-
Add the M5Stack board index URL under
File → Preferences → Additional Boards Manager URLs:https://static-cdn.m5stack.com/resource/arduino/package_m5stack_index.json -
Open
Tools → Board → Boards Manager, search for M5Stack, and install it. -
Select the board:
Tools → Board → M5Stack Arduino → Cardputer. -
Open
Tools → Manage Librariesand install:M5CardputerM5GFXM5Unified
(
Preferences.h, used for storing Wi-Fi credentials, ships with the ESP32 core — no separate install needed.) -
QTH_LOCATORin the sketch can stay as-is (default"JO50", roughly the center of Germany) — you can set your own locator conveniently directly on the device instead (see Usage below); that's the easier route and survives future firmware updates. -
Open
CardputerPropagation.inoand upload it, or useSketch → Export Compiled Binaryand copy the resulting.binto an SD card to install via M5Launcher.
No Wi-Fi credentials need to be entered in the code — that's handled entirely on-device via the setup wizard described below.
The Wi-Fi setup wizard opens automatically:
- The device scans for nearby networks
;= move up,.= move down,s= rescan- Enter selects the highlighted network
- Type the password, Enter to connect, Del to remove the last character
- On success, the credentials are saved to flash and propagation data is fetched immediately
| Key | Action |
|---|---|
r |
Refresh data manually |
w |
Reopen the Wi-Fi setup wizard (e.g. to switch networks) |
Tab |
Cycle to the next page (Bands / Details / Grayline) |
| (any key) | Wake the screen if it has dimmed |
Data refreshes automatically every 15 minutes. After 2 minutes of inactivity the backlight dims; the key press that wakes it up does not trigger any other action.
Note: the grayline page derives its location from an amateur radio
Maidenhead locator. The constant QTH_LOCATOR in the sketch (default
"JO50", roughly the center of Germany) is only the initial value used
on first boot — set your own locator directly on the device instead:
| Key (on the Grayline page) | Action |
|---|---|
l |
Open locator entry |
| (type 4 or 6 characters) | e.g. JO31nx |
Enter |
Save and recalculate sunrise/sunset immediately |
Fn |
Cancel without saving |
Latitude/longitude are computed automatically from the locator and stored persistently, the same way Wi-Fi credentials are.
The screen shows the actual failure reason instead of a generic error, so check what's displayed:
| Message | Meaning | Fix |
|---|---|---|
| Connection fails on the password screen | Wrong password, or a 5 GHz-only network | Double-check the password; the ESP32 only supports 2.4 GHz |
HTTP status code: 301 |
Server issued a redirect | Should already be handled via HTTPS URLs |
HTTP status code: 403/503 |
Server blocking or overloaded | Retry later |
MUF: table not found |
Juliusruh page layout changed | The scraper in fetchMuf() needs updating |
Wi-Fi not connected on the main screen |
Connection dropped during runtime and auto-reconnect failed | Press w to run the Wi-Fi wizard again |
"No networks found" with a scan code other than 0 |
Wi-Fi scan itself failed (radio busy/error) | Press s to retry; the module is reset before each scan |
- Both data sources are fetched over HTTPS with
setInsecure()(certificate validation is skipped — acceptable for a hobby project, not recommended if you're adapting this for anything sensitive). - Wi-Fi credentials are stored unencrypted in the ESP32's NVS flash region. This is standard practice for hobby IoT projects, but keep it in mind if you ever hand the device to someone else — there's currently no built-in "forget network" option.
- List navigation in the Wi-Fi wizard uses
;(up) and.(down), since the Cardputer keyboard has no dedicated arrow keys (these two keys double as arrows on the physical keycaps). Adjust inhandleWifiScanKeys()if your unit differs. - Band names (
80m-40m,30m-20m,17m-15m,12m-10m) and field names follow hamqsl.com's current XML schema; if they change their format,getBandCondition()will need updating. - The grayline calculation uses the center of the locator cell (with a 6-character locator, roughly ±1.25' latitude / ±2.5' longitude off the exact spot — negligible for propagation purposes). Trend arrows and the alarm always compare against the most recent successful fetch, not a longer history.
Released under the Unlicense — public domain. Use it however you like, no attribution required.