[Devember 2022] Polish and release my RPi world stats display

Edit: Update 1 here

Project Context

In August 2021, I made a tool for displaying miscellaneous info about the world (current time, weather forecast, stock / crypto prices), generating an image displaying that info, and drawing it to an e-paper display I have. It’s been sitting on my desk for the last year, working great, but half-finished this whole time.

Here’s an older picture of the current state of the project sitting on my desk!

It works by displaying a list of “cards”, each tasked with displaying one piece of info - time, weather, stock price, etc.

My goal

My goal is to finish all the TODOs I’ve carried around for the last year, and build a second in time to give to a friend for Christmas. To list a few TODOs:

  • Build a card layout manager so I don’t manually place cards at specific pixels
  • Make cards reconfigurable, less hard-coding everything
  • Make the day/night cycle for weather data look better - have a night sky during night time, create night versions of weather sprites with a moon instead of a sun, etc.
  • Have the price cards actually turn red when prices go down (which is a lot)
  • Get partial display updates working, so I can update the clock every 5 minutes and update the other stats every 15 minutes
  • Add a “daily Kanji character” card for showing a Kanji character, stroke order, and meaning, every day. My friend is a weeb, he’ll appreciate it.
  • Wrap everything up into a Nix flake with outputs for both the package and system configuration, to generate pre-configured disk images ready to burn to an SD card.
  • Write enough documentation that people can build their own without relying on me or understanding the code.

Stretch goals:

  • Make a web configurator - rather than requiring users to SSH into the pi to change configuration, create a basic web UI for configuring and reordering cards, and run a webserver on the device
  • I have a neat idea for generating some sprite scenery based on the last week of weather - make some sprites for trees, grass, flowers, rain, snow, etc, and simulate a little environment that piles up snow and melts based on the weather and the current season. That’s probably a whole devember project on its own, maybe next year
  • 3D print a case for it

My repo

The code is currently kept on my gitlab instance, here. Maybe I’ll push it to the official gitlab instance, maybe not, we’ll see.

4 Likes

Hey, those waveshare ePaper displays are pretty neat! I think your project is a good use of one too.

I also have one of those 7-color displays, and was wondering if the partial display updates would work or not.

I looked through all of their repositories and only found one implementation here:

I don’t know why, but the main repo for their code doesn’t have this function. However, the rp2040 version does! :face_with_raised_eyebrow:

I haven’t tested this function on my 4.01" model, but I wouldn’t be surprised if it just “worked” anyway.

Note that I checked waveshare’s store, and their selection guide doesn’t list any of the ACeP (7-color) displays as supporting partial refresh, so who knows if this feature really works. :person_shrugging:

I guess you may just have to just wait and watch the display have a seizure for 30 seconds while updating the clock. :stuck_out_tongue_winking_eye:

I wound up writing my own display driver for the EPD 5.65" displays, because the one waveshare ships is terribly slow. For instance, it sends pixels one byte at a time, when SPI can handle sending the entire buffer at once. On a low-power Raspberry Pi Zero, I was able to cut down the process of sending an image from 50 seconds to 5 seconds.

I haven’t touched partial updates since last August, but I almost got them working. No guarantee my current implementation works, but it should be close. You can see my implementation for partial updates here, but in short, I just have to set the window mode for the SPD1656 chip controlling the display before uploading the buffer.

It shouldn’t be too hard to cut out my display driver as a standalone thing, that might be worth releasing on its own.

Haha, I just got used to it, and accepted just updating it once every 5 minutes. After a few days, I stopped noticing it in my peripheral. That long update time is why I want to try getting partial updates properly integrated, so I can update the clock more regularly than everything else.

For a while I did experiment with flashing custom LUTs to the display for fast refreshes. I found some very basic documentation on the SPD chip (it’s in my repo, in the docs folder) for how the LUT works (it’s basically a state machine), and there was a project on Hackaday with some great research into it, but I was never able to do anything other than display garbage. As it turns out, epaper is really complicated, and temperature sensitive!

1 Like

Oh, cool! I’ll have to read that hackaday post later.
If you haven’t seen it yet, Ben from Applied Science has a video where he got some pretty impressive results with the greyscale and 3-color panels:

I’m not surpised about waveshare’s code. The arduino examples only support the Uno, and nothing else. I had to rewrite a lot of their code to make SPI work on the ESP32, Teensy, and Pico. I may try and tidy that up into its own library in the future.

I think that since your code is significantly faster, you should definitely release it as a python library. I think more people would enjoy developing with these things if they had a quicker update cycle. :slight_smile:

1 Like

Update 1

I’ve finished some non-visible items on my TODO list.

  • I wrote a card layout manager, so much like a layout manager for any other UI kit, I can add cards with either an explicit size (in y pixels) or a given number of x/y shares. Once all the explicitly sized rows are taken into account, the remaining space is divvied up between the remaining rows depending on how many shares they take.

  • I added a configuration generating / loading utility. Cards can now generate a config based on their current setup, and be deserialized from a config. Thanks to some very light recursive magic, the entire runtime config (current display type, update frequency, cards, layout) is described in a single .json object. Configs are now saved as .json files in ~/.config/worldmon.

  • Added day/night for the weather card. See my pictures below. Each night, a different starfield is generated, with variously sized white, yellow, and red stars. On about 15% of nights, at least one black hole is spawned as well, which you can see in my close-up photo. I still have more I want to add to the day/night cycle, but this is a good start.

  • I’m now gracefully handling failures in updating or rendering cards. Rather than crashing outright, it takes the most recent successful render and redisplays that with an exclamation mark.

In the second image, I was experimenting with card failures by failing card renders 50% of the time. I forgot that the layout manager is itself a card, whoops. I can recursively handle failures!

  • I’ve created a nix flake which provides worldmon as a package, as well as a nixos module for setting up proper permissions and systemd units. I haven’t needed to manually restart my script once since!

Further work

I’m not done with all my TODOs, and I likely won’t be done until early January. Oh well, I’m sure a late Christmas gift will still be acceptable.

Current task

Currently, I’m working on night versions of weather sprites. After that, I’ll split the price cards into red/green based on the time period’s starting price.

4 Likes