Flashing
Flash the method that matches your board. The ESP8266 and the SmallTV Pro install over the air from their stock web UI. The ESP32-C2 and the NM-TV-154 install over the USB cable with esptool. Back up the stock image first on any board so you can always go back.
Get the firmware image from the Actions tab (latest build run) or the Releases page, or build it yourself.
SmallTV (ESP8266)
Section titled “SmallTV (ESP8266)”Over the air, from the stock web UI
Section titled “Over the air, from the stock web UI”The stock GeekMagic firmware exposes an OTA updater at /update that accepts any valid ESP8266 image, so you can install this without opening the device.
- Find the device IP. It is shown on screen or in the stock Settings app.
- Browse to
http://<device-ip>/update. - Upload
smalltv-mod-firmware.bin. It reboots into this firmware.
Upload smalltv-mod-firmware-lean.bin instead if you want the build without Home Assistant screens and the usage meter, which leaves more heap for the radar and the cash.ch tickers. Both files install the same way and you can swap between them later. See Which release file to download.
Back up the stock firmware first if you want the option to return to it. The stock image is not redistributed here, so read it off your own device over the UART header before you overwrite it.
UART header, for recovery or a direct install
Section titled “UART header, for recovery or a direct install”The serial header is the guaranteed way in. Use it if OTA is not available, if the device will not boot, or if you would rather skip OTA and flash directly.
Open the case first: remove the two screws on the underside and lift out the inner tray that holds the PCB. Six labelled pads sit on the board:
| Pad | Wire it to |
|---|---|
3V3 | 3.3 V on the adapter |
GND | GND on the adapter |
TXD0 | the adapter’s RX |
RXD0 | the adapter’s TX |
GPIO0 | GND, to enter flash mode (only during power-on) |
RST | optional, tie to GND briefly to reset |
Use a 3.3 V USB-UART adapter. Hold GPIO0 to GND while powering on to enter flash mode, then release it. Pad map from ViToni/esphome-geekmagic-smalltv.
Back up the stock image first if you might want it back:
esptool.py --port COM5 read_flash 0x0 0x400000 stock-backup.binThen flash. On a SmallTV-ultra, erase first so the stock partition layout goes with it; on a plain SmallTV the erase is optional but harmless:
# clear the old layout (partition + data), then write the firmwareesptool.py --port COM5 erase_flashesptool.py --port COM5 write_flash 0x0 smalltv-mod-firmware.binThat single image carries everything the ESP8266 needs, so there is no separate partition file to flash. On first boot it recreates its own filesystem and opens the SmallTV-Setup portal.
SmallTV-ultra (stock updater says “Not Enough Space”)
Section titled “SmallTV-ultra (stock updater says “Not Enough Space”)”The SmallTV-ultra is the same ESP-12F (ESP8266) as the original SmallTV: same 4 MB flash, the same 1.54” 240×240 ST7789 panel, and the same pin map. Only its stock firmware differs. The “Ultra” firmware (for example Ultra-V9.0.50) reserves most of the flash for image and GIF storage, which leaves its OTA updater a small app slot. Uploading smalltv-mod-firmware.bin at /update fails with Update error: ERROR[4]: Not Enough Space, even though the flash has plenty of free user space, because the full image does not fit that small slot.
The fix is a two-step install through a tiny loader, no soldering. The loader is a ~308 KB image that does fit the stock slot. Once running it uses this firmware’s own 4m1m flash layout, whose app region is large, so the full image fits on the second hop.
- Get
smalltv-mod-loader.binfrom the Releases page. - Browse to
http://<device-ip>/updateand uploadsmalltv-mod-loader.bin. It fits the stock slot. The device reboots into the loader. - The loader opens an open WiFi access point named
SmallTV-Loader. Join it and browse tohttp://192.168.4.1/update. - Upload
smalltv-mod-firmware.binthere. It fits because the loader uses this firmware’s flash layout, which gives the sketch about 1,020 KB against an image of roughly 694 KB. The device reboots into the full smalltv-mod. - It comes up in the usual
SmallTV-Setupcaptive portal for WiFi. From here it is a normal ESP8266 smalltv-mod device.
After this first install, normal OTA works from the System tab, because this firmware’s layout has room for two sketch copies. You only need the loader once.
If the loader ever will not come back up, flash over the serial header instead. The board is a plain ESP-12F, so the UART recovery steps above apply directly: esptool.py --port COM5 write_flash 0x0 smalltv-mod-firmware.bin.
SmallTV (ESP32-C2 / ESP8684)
Section titled “SmallTV (ESP32-C2 / ESP8684)”The ESP32-C2 has no OTA path from the stock firmware, so the first install goes over the USB-C cable. The onboard CH340C handles it with auto-reset, so no button is needed. You need a system Python with esptool (pip install esptool).
Back up the stock image first
Section titled “Back up the stock image first”python -m esptool --chip esp32c2 --port COM3 read_flash 0x0 0x400000 stock-backup.binKeep stock-backup.bin somewhere safe. Writing it back with write_flash 0x0 stock-backup.bin returns the device to factory at any point.
Write this firmware
Section titled “Write this firmware”Download smalltv-mod-firmware-c2.factory.bin from the Releases page: a single merged image with the bootloader, partition table, and app (a local build produces the same file as firmware.factory.bin). Write it at offset 0:
python -m esptool --chip esp32c2 --port COM3 --baud 921600 write_flash 0x0 smalltv-mod-firmware-c2.factory.binWith a source checkout, pio run -e smalltv_c2 -t upload does the same thing.
NM-TV-154 (classic ESP32)
Section titled “NM-TV-154 (classic ESP32)”Same procedure as the ESP32-C2, with --chip esp32 and smalltv-mod-firmware-esp32.factory.bin from the Releases page (or build it with pio run -e smalltv_esp32).
Back up the stock image first
Section titled “Back up the stock image first”The NMMiner stock firmware is not redistributed anywhere official, so this backup is your only way back:
python -m esptool --chip esp32 --port COM3 read_flash 0x0 0x400000 stock-backup.binIf esptool flash_id reports more than 4 MB of flash, adjust the read length to match.
Write this firmware
Section titled “Write this firmware”python -m esptool --chip esp32 --port COM3 --baud 921600 write_flash 0x0 smalltv-mod-firmware-esp32.factory.binWith a source checkout, pio run -e smalltv_esp32 -t upload does the same thing.
SmallTV Pro (classic ESP32, 8 MB)
Section titled “SmallTV Pro (classic ESP32, 8 MB)”The SmallTV Pro has no USB-serial chip: its USB-C port is power only. There are two ways in: over the air from the stock web UI (no tools, no soldering), or over an internal UART header (needs opening the case and a 3.3 V USB-UART adapter).
Over the air, from the stock web UI
Section titled “Over the air, from the stock web UI”The stock firmware exposes an OTA updater, the same way the ESP8266 SmallTV does. This firmware’s 8 MB partition layout matches the stock table exactly (same OTA slots, verified from a live device), so the stock updater can install it directly:
- Find the device IP (shown in the stock Settings app).
- Browse to
http://<device-ip>/update. - Upload
smalltv-mod-firmware-esp32-pro.bin(the plain app image, not the.factory.bin) from the Releases page. It reboots into this firmware.
This path keeps the stock bootloader and partition table in place and cannot be undone without a backup, and the stock image is not redistributed anywhere official. If you want the option to return to stock, take the UART backup below before flashing OTA.
UART header, for backup, recovery, or a direct install
Section titled “UART header, for backup, recovery, or a direct install”Open the case. The PCB has a 6-pad serial header (pad map from the HA community thread):
| Pad | Function | Wire it to |
|---|---|---|
| 1 (square) | GND | GND on the adapter |
| 2 | TX | the adapter’s RX |
| 3 | RX | the adapter’s TX |
| 4 | 3V3 | 3.3 V on the adapter |
| 5 | GPIO0 | GND during power-on to enter download mode |
| 6 | RST | optional, tie to GND briefly to reset |
Hold pad 5 (GPIO0) to GND while the device powers on, then release it. Back up the full 8 MB stock image first:
python -m esptool --chip esp32 --port COM3 read_flash 0x0 0x800000 stock-backup.binWriting it back with write_flash 0x0 stock-backup.bin returns the device to factory at any point. To install this firmware over UART instead of OTA, write the merged image:
python -m esptool --chip esp32 --port COM3 --baud 921600 write_flash 0x0 smalltv-mod-firmware-esp32-pro.factory.binWith a source checkout, pio run -e smalltv_esp32_8mb -t upload does the same thing over the adapter’s COM port.
After the first flash
Section titled “After the first flash”Every board then updates from the browser: open the web UI’s System tab and either let the device pull the newest GitHub release itself (each board fetches its own image) or upload a firmware file manually. The manual upload takes the plain app image (smalltv-mod-firmware*.bin), not the .factory.bin.
The ESP32 boards download and flash in place. The ESP8266 (from 2.7.0) uses an update-at-boot flow instead, because the download’s 16 KB TLS buffer only fits before the firmware’s features start: the device queues the update, reboots, shows updating... while it downloads, then reboots again into the new version. Expect two reboots and a couple of minutes; if the download fails, the device boots normally and the System tab shows why.
Recovery
Section titled “Recovery”- Re-flash anything (your stock backup or this firmware) with the method for your board.
- Factory reset in the System tab wipes saved settings and restarts in SETUP MODE. It does not change the firmware.
- On the ESP32 boards, if a bad flash leaves the device unresponsive, it still enters download mode over USB, so esptool can always rewrite it.