Skip to content

itsfoss/literary-clock

Repository files navigation

Literary Clock - Display Time in Literary Quotes

A clock that doesn't show numbers. Every minute, it displays a literary quote that mentions the current time, like "seventeen minutes past ten," "almost exactly at midnight," and so on, with the time phrase emphasized

The code here is tested to work on a CrowPanel ESP32 4.2" e-paper display.

Photo of the clock

The idea is inspired by Litclock project and the quote database is taken from this awesome project.

What it does

  • Syncs real time over WiFi via NTP at boot, then keeps time locally
  • Matches the current HH:MM against a quotes database and displays one that mentions that exact time
  • Randomly picks among multiple quotes for the same minute, where available
  • Time phrase within the quote is emphasized: bigger font where the display's fixed font sizes allow it, underlined always
  • Quote text is dynamically sized (24px / 16px / 12px) and word-wrapped depending on length, so short quotes render big and long ones still fit without truncation
  • Header shows the current weekday/month/day; footer shows book title and author, right-aligned
  • Partial e-paper refresh once per minute — no unnecessary full-screen flashing
  • Reconnects WiFi automatically if the connection drops

Hardware

  • Elecrow CrowPanel ESP32 4.2" E-Paper HMI Display (400×300, SSD1683 driver, ESP32-S3-WROOM-1-N8R8)
  • USB-C cable + any 5V USB wall adapter for continuous power (this is a clock and it needs to stay powered)
  • Optional: 2.2–3.7V Li-Po battery via the board's BAT connector, if you want it cordless (not required, and not optimized for battery life in this version — see Known Limitations)

Repository structure

literary_clock/
├── literary_clock.ino   — main sketch
├── EPD.cpp / EPD.h            — e-paper driver (from Elecrow's own library)
├── EPD_GUI.cpp / EPD_GUI.h    — drawing/text primitives
├── EPD_SPI.cpp / EPD_SPI.h    — low-level SPI/pin definitions
├── EPD_font.h                 — built-in bitmap fonts (ASCII only)
└── quotes_data.h               — quotes compiled into a flash-resident C array

tools/
└── csv_to_header.py            — converts a quotes CSV into quotes_data.h

data/
└── quotes.csv                  — source quotes (see CSV Format below)

Setup

1. Install Arduino IDE

Download the AppImage (Linux) or installer for your OS from arduino.cc.

2. Add ESP32 board support

File → Preferences → Additional Boards Manager URLs, add:

https://espressif.github.io/arduino-esp32/package_esp32_index.json

Then Tools → Board → Boards Manager, search esp32, install the latest stable release by Espressif Systems (avoid pre-release versions).

3. Board configuration

With the board connected via USB-C, set under Tools:

  • Board: ESP32S3 Dev Module
  • Port: whichever /dev/ttyUSB* or COM port appears
  • Flash Size: 8MB
  • PSRAM: OPI PSRAM
  • Partition Scheme: Huge APP (3MB No OTA/1MB SPIFFS) — required, since the quotes data alone is ~1.4MB and won't fit in the default partition scheme

4. Configure WiFi and open the sketch

Open literary_clock/literary_clock.ino and fill in near the top:

const char* ssid     = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

Note: the ESP32 only supports 2.4GHz WiFi, not 5GHz.

If you're not in the IST timezone, also update:

const long gmtOffset_sec = 19800;   // UTC+5:30
const int daylightOffset_sec = 0;

5. Upload

Select the port, hit upload. First boot will connect to WiFi, sync time, and start refreshing once a minute.

CSV format / regenerating quotes_data.h

quotes_data.h is generated from a pipe-delimited (|) CSV with six columns and no header row:

HH:MM|bold phrase|quote text|book title|author|nsfw flag (YES/NO)

Example:

00:00|midnight|"And almost exactly at midnight, the Count's patience was rewarded."|A Gentleman in Moscow|Amor Towles|NO
  • bold phrase must appear verbatim (case-insensitive) inside the quote text — it's matched at runtime to find and emphasize the time reference.
  • Rows flagged nsfw=YES are skipped during conversion.
  • The display's built-in font is ASCII-only, so tools/csv_to_header.py transliterates accented characters (é→e) and substitutes a few characters that would otherwise be silently dropped (en/em dashes → -, ° → deg, £ → GBP, ¼ → 1/4, ø → o).

To regenerate after editing your CSV:

python3 tools/csv_to_header.py

This reads data/quotes.csv and writes literary_clock/quotes_data.h. Re-upload the sketch afterward.

For full coverage, aim for at least one quote per minute of the day (1440 total) — the sketch falls back to a random quote if no exact match is found for the current minute, which is a fine safety net but shouldn't be the common case.

How it works

  • Font sizing: the display's font only supports fixed sizes (8/12/16/24/48px). The sketch measures each quote and picks the largest of {24, 16, 12} that will actually fit the content area without overflowing, word-wrapping at word boundaries.
  • Bold time phrase: where a valid bigger font size exists one step up (12→16, 16→24), it's used; the 24px tier has no safe bigger option (48px would overflow multi-word phrases off-screen), so it relies on the underline alone. The underline is applied at every tier for visual consistency.
  • Quote lookup: on each minute change, every quote matching the current HH:MM is collected, and one is picked at random.

Known limitations / possible future work

  • Quote repetition: quote selection for a given minute is independent random each time — there's no memory of what was shown previously, so the same quote can occasionally repeat on consecutive days. Adding a "don't repeat the last one shown at this minute" check (or a full rotation) would be a natural improvement.
  • Extreme-length quotes: 3 out of 4794 quotes in the reference dataset are long enough to slightly truncate at the smallest font tier (losing roughly the last 1–3% of the text). Negligible in practice, but worth knowing about if you add unusually long quotes of your own.
  • No deep sleep / battery optimization: the board is expected to stay on continuous USB/wall power. Running on battery would need sleep-between-refreshes logic, which isn't implemented here.
  • No weather or other widgets: left out by design to keep the display focused on the quote.

Troubleshooting

If the screen never updates and stays on the factory demo image, check that you're building from the correct example tree in Elecrow's own repo — their GitHub repo actually ships two different low-level display init sequences for what look like two hardware revisions of this same board, and using the wrong one causes the BUSY pin to hang indefinitely with no visible error. This project's EPD.cpp is confirmed working against the non-"green sticker" (example/arduino/) tree. If you're pulling library files fresh from Elecrow's repo rather than using this repo's copies, make sure you're consistent about which tree you copy from.

Attribution

  • Display driver library and example code: Elecrow
  • Quotes: excerpts from their respective copyrighted books — author and title are displayed alongside each quote. Quotes came from Litclock project

License

MIT License

About

Display time in literary quotes on an esp32 e-ink display

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors