Skip to content

MartiniMartin/xkcd-epaper-reader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

XKCD E-Paper Reader

A standalone daily XKCD comic reader built on CircuitPython 10. The device connects to WiFi once per day, fetches the latest comic, dithers it to 1-bit, and renders it on a 7.5" black/white/red e-paper display. A physical button wakes the device from deep sleep to show the comic's alt-text. Everything runs on a Li-Po cell.

![Hardware: XIAO ESP32-S3 + Waveshare 7.5" e-paper display]


Hardware

Component Detail
MCU Seeed XIAO ESP32-S3 — 512 KB SRAM + 8 MB PSRAM, 8 MB Flash, Wi-Fi
Display DEPG0750RNU790F30HP — 7.5", 800×480, Black/White/Red, SPI (UC8179)
Button Momentary push-button
Power Single Li-Po cell via XIAO onboard USB-C charger (BQ25101)

Wiring

E-Paper Display (SPI)

E-Paper Pin XIAO ESP32-S3 Pin
VCC 3V3
GND GND
DIN (MOSI) D10 / GPIO9
CLK (SCK) D8 / GPIO7
CS D3 / GPIO4
DC D2 / GPIO3
RST D1 / GPIO2
BUSY D0 / GPIO1

Button

Button XIAO ESP32-S3 Pin
One leg D5 / GPIO6
Other leg GND

GPIO6 is configured with an internal pull-up; pressing the button pulls it LOW.


How It Works

Boot / wake from deep sleep
    │
    ├─ Button press (PinAlarm)
    │       Load alt-text from /last_alt.txt
    │       Render text → 1-bit bitmap
    │       Display on e-paper
    │       Deep sleep again
    │
    └─ Scheduled wake (TimeAlarm) or first boot
            Read last comic number from /last_comic.txt
            Connect to WiFi
            GET xkcd.com/info.0.json
            If new comic:
                Download PNG
                Decode → grayscale → scale → Floyd-Steinberg dither
                Display 1-bit bitmap on e-paper
                Save comic number + alt-text to flash
            Disconnect WiFi
            Deep sleep for 24 h (or until button press)

The device spends almost all its time in deep sleep, drawing ~1 µA from the display and the ESP32-S3's deep sleep current.


File Structure

CIRCUITPY/
├── code.py              # Main entry point
├── settings.toml        # WiFi credentials
├── epaper.py            # UC8179 SPI driver
├── image_utils.py       # PNG download, decode, scale, dither
├── text_render.py       # Alt-text → 1-bit bitmap renderer
├── fonts/
│   └── LeagueSpartan-Bold-16.bdf   # Bitmap font for alt-text
└── lib/
    ├── adafruit_requests.mpy
    ├── adafruit_connection_manager.mpy
    ├── adafruit_pngdecoder.mpy
    └── adafruit_bitmap_font/

Setup

1. Flash CircuitPython

Download the CircuitPython 10.x UF2 for the XIAO ESP32-S3 from circuitpython.org and flash it to the board.

2. Install libraries

Copy the following from the Adafruit CircuitPython 10.x bundle into the lib/ folder on your CIRCUITPY drive:

  • adafruit_requests.mpy
  • adafruit_connection_manager.mpy
  • adafruit_pngdecoder.mpy
  • adafruit_bitmap_font/ (directory)

3. Add a font

Copy a .bdf bitmap font into fonts/ on the CIRCUITPY drive. The default expected path is fonts/LeagueSpartan-Bold-16.bdf. Any Adafruit-bundled .bdf font works — update FONT_PATH in text_render.py if you use a different file name.

4. Configure WiFi

Edit settings.toml and fill in your credentials:

CIRCUITPY_WIFI_SSID = "your_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_password"

5. Copy project files

Copy code.py, epaper.py, image_utils.py, and text_render.py to the root of the CIRCUITPY drive.

6. Test

Open a serial console at 115 200 baud and watch the output. On first boot the device will connect to WiFi, fetch the latest comic, and display it. The first BWR refresh takes ~15 seconds.

To test the sleep/wake cycle quickly, set SLEEP_SECONDS = 30 in code.py, then restore it to 86400 for normal use.


Image Pipeline

  1. PNG downloaded in chunks into a bytearray (8 MB PSRAM gives ample headroom)
  2. Decoded row-by-row with adafruit_pngdecoder
  3. Converted to 8-bit grayscale: g = (77·R + 150·G + 29·B) >> 8
  4. Nearest-neighbor scaled to 800×480 with white letterbox padding
  5. Floyd-Steinberg dithered to 1-bit
  6. Packed MSB-first into a 48 000-byte buffer and sent to the display

The red plane is left empty — XKCD comics are black and white.


Power

The XIAO ESP32-S3 includes a BQ25101 Li-Po charger accessible via its USB-C port. Deep sleep current is dominated by the display (~1 µA image retention) and the ESP32-S3 deep sleep mode (~20 µA). A 1 000 mAh cell should last several weeks between charges.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages