UpNext

I used a Raspberry Pi and an ePaper display to make a subtle, unobtrusive digital desktop calendar. The code is available on github.

Origins

After building the Internet Radio, I was talking with a coworker about ideas for new projects that leveraged small, cheap computers like the Raspberry Pi in useful and unobtrusive ways. He suggested making a digital “calendar bot” that would sit on your desk and make sure you didn’t miss your next meeting. I've always liked ideas that build ambient awareness of digital information (similar to my Personal Dashboard), so I took the commission! I call it “UpNext,” and for the last year it’s been a pleasant and helpful desk companion.

About UpNext

With no need for interactivity, the UpNext hardware is very simple: a 4.2” ePaper display, a Raspberry Pi, and a case. The Pi connects to wifi automatically, then starts a script that uses the Google Calendar API to fetch my daily schedule and pick the most helpful current or upcoming meeting to render on the display.

I chose an ePaper screen because I didn't want the device to feel “digital” - given that I already look at screens 10+ hours a day, I didn’t want yet another backlit screen on my desk. While the ePaper display is much more challenging to work with than a traditional LCD screen, it helps the device be a passive, ambient source of information rather than a bright screen that calls attention to itself.

I designed the user interface to be highly glanceable and focused on the information that you need to be on time: what's your next event, where is it, and how long until it starts. To round out the experience, there’s a small clock in the top right and a secondary event line so you know if you have back-to-back meetings. When there’s plenty of time before your next event, UpNext lets you know that you have the time to be heads-down.

The original mockups

When you have current, overlapping, or all-day events, UpNext uses a handful of heuristics to determine which are the most helpful events to show, such as whether you’ve confirmed your attendance (higher priority) or if an event is recurring (lower priority).

Building UpNext

The biggest technical challenge of this project was working with the ePaper display. I chose the Waveshare 4.2” because it was reasonably priced, interfaced via SPI, and had passable documentation and sample code for the Raspberry Pi. Once it arrived, I connected it to a spare Raspberry Pi, ran the sample code, and ran square into the major drawback of this type of display: ePaper screens look terrible when they refresh. Using the default setup, updating any portion of the screen required 10 seconds of repeated flashing. This was definitely not going to provide the subtle, unobtrusive feeling I was hoping for.

Refreshing the screen with the original waveform looks terrible

After some searching, I came across a small community of people that had modified the provided drivers to achieve fast, partial screen updates. Building off their work, after a few days of experimenting with different settings and reading through data sheets, I was able to design a setup that provided fast, partial screen updates (code). The tradeoff was that after several updates pixels would gradually fade until a full-screen refresh reset all the dots into their proper place [1].

With some experimenting, I found that pixels would look crisp for about ten partial updates each. To maintain good readability while minimizing distracting full-screen refreshes, I wrote an abstraction layer that managed the rendering process instead of rendering content directly to the display. Rather than always updating the full screen, the code firsts takes the content to be displayed and determines the minimum amount of the screen that needed to be updated. It then keeps track of a "budget" for each region of the screen - once a region has been updated enough times, the whole screen is refreshed.

Once the screen drivers were built, the rest of the software was fairly straightforward. I hadn’t written C++ in over a decade, so it was a bit of a challenge to figure out components like API requests and text rendering, but with the help of a lot of googling I was able to get enough of a solid foundation to start on the UI. The original UI code was pretty simple, but over the past year I’ve added enough refinements that picking which event(s) to show and how is now quite sophisticated. The device feels quite responsive - the script is set up to start when the Raspberry Pi boots up, and checks for new events every 10 seconds.

With the software completed, I purchased a suitably sized project case and cut a viewport for the display and charging cable. Lacking screw-holes, I hot-glued the display and Raspberry Pi into place, closed up the case, and that was it! I will still occasionally ssh into the device to make small tweaks, but for the most part it quietly and dutifully does its job of keeping me aware of what’s coming up.

Reflections

UpNext definitely met the original goal - it’s a pleasant, unobtrusive addition to my desk that does one thing and does it well. I particularly like that there’s no expectation of interactivity: unlike so many other digital devices, UpNext provides value without nudging you to engage more often.

Working with an ePaper screen was a substantially bigger task than I expected, but it gave me a much deeper appreciation for all the layers of work that go into making this text appear as pixels on your screen. Writing the program in C++ wasn't essential, but was a good excuse to re-familiarize myself with the language, and it’s not that much harder to write a simple program in C++ than in python or javascript.

Using the excuse that I was “still polishing the experience,” I’ve kept the first one for myself, but now that it’s good enough to publish this post, I’m finally building my coworker his own. They’re about $100 in parts - if you want one, let me know!

Footnotes