From a510673221fe872a75ed1f868ba6d3a1a762615e Mon Sep 17 00:00:00 2001 From: uvok Date: Sun, 10 Aug 2025 18:29:01 +0200 Subject: Finish article --- _drafts/building-an-epaper-badge.md | 260 ++++++++++++++++++++++++++++++------ 1 file changed, 222 insertions(+), 38 deletions(-) diff --git a/_drafts/building-an-epaper-badge.md b/_drafts/building-an-epaper-badge.md index 866e0e8..43cd56b 100644 --- a/_drafts/building-an-epaper-badge.md +++ b/_drafts/building-an-epaper-badge.md @@ -14,32 +14,33 @@ Two weeks before [Awoostria]({% post_url 2025-07-30-awoostria-con-report %}): So it begins… The story how I built myself an ePaper badge. -Actually, the story begins way earlier, when I still had a physical Raspberry -Pi running stuff in my home network. I wanted to tinker around a bit and bought -myself a Waveshare ePaper. These are simple black-and-white displays which -maintain their content when the power switches off. They are also inside eBook -readers. +Actually, the story begins way earlier (unrelated, when I still had a physical +Raspberry Pi running stuff in my home network). I wanted to tinker around a bit +and bought myself a Waveshare ePaper. These are simple black-and-white displays +which maintain their content when the power switches off. They are also inside +eBook readers. -Some years ago I wanted to build myself an electronic door sign for the EAST -convention with these, and I wanted to go "as minimal as possible". I wanted to -use one of the MSP430 controllers I had laying around, and I wanted to switch -motives via MiFare RFID transponders (using an MFRC5xx reader). Work on that -development never really took off. +This was also when I wanted to build myself an electronic door sign for the +EAST convention with these, and I wanted to go "as minimal as possible". I +wanted to use one of the MSP430 controllers I had laying around, and I wanted +to change motives via MiFare RFID transponders (using an MFRC5xx reader). Work +on that development never really took off. (Ugh, too little flash for all the +pictures, too much stuff to code myself!) ## Requirements So this time, I simply said "fuck it", and threw an ESP32 on the problem. Also, I decided to use [PlatformIO](https://platformio.org/), a toolchain/SDK/library manager. I started with the Arduino framework, which is… -pretty wasteful in terms of resources (Flash/RAM/…), but speeds up development -significantly. +pretty wasteful in terms of resources (Flash, RAM, CPU etc.), but speeds up +development significantly. I had a simple ESP32 devboard, and one of the Waveshare modules, and started coding. … -But wait, what to I even want to achieve? Well, I wanted to "mood badge", i.e. +But wait, what do I even want to achieve? Well, I wanted to "mood badge", i.e. show my current mood with funny pictures. I couldn't get one on previous conventions, so I was just gonna build one myself. @@ -64,7 +65,8 @@ support *some* Waveshare displays. The problem with Waveshare displays is, they don't disclose which display controller they use. So it's kind of an trial-or-error procedure. Or rather, you can look at their example code, figure out which commands they are using, and compare what commands GxEPD2 uses. -That's a bit cumbersome. +That's a bit cumbersome. But still better than writing everything myself. Also, +it supports graphics primitives! ## Get the picture on the display @@ -76,13 +78,15 @@ but that makes it even more complicated, actually. Even when you don't use it, refresh is slow. So, you definitely can't throw a color picture on the display, nor a monochrome -one. There are displays which support a few gray-levels, though. +one. There are displays which support a few gray-levels, but I don't have one +of those. So. What to? The solution is "dithering". I.e. you trick your eye into perceiving grey by having clusters of black and white pixels. There is some -background to dithering (see below), but I simply used either GIMP, the -Floyd-something algorithm, or one of the "ordered" modes of ImageMagick. It was -a bit of trial-and-error and seeing-what-looks-best. +technical background to dithering (see the Reference section), but I simply +used either GIMP with the Floyd-something algorithm, or one of the "ordered" +modes of ImageMagick. It was a bit of trial-and-error and +seeing-what-looks-best. The result, then, looks like this: @@ -100,26 +104,30 @@ rotation first, though. ## How to attach the badge to myself I have a Waveshare module/PiHat (which is too heavy), and a simple "ePaper -sheet" including a housing for it. The housing can only fit the ePaper, not the -devboard, though. Also, it would be too cumbersome to attach to the devboard - -loose wires! So, at this point, I decided to switch from the prototyping -platform onto something better. +sheet" including a plastic housing for it. The housing can only fit the ePaper, +not the devboard, though. Also, it would be too cumbersome to attach to the +devboard - loose wires! So, at this point, I decided to switch from the +prototyping platform onto something better. Fortunately, Elecrow provides a -[CrowPanel](https://www.elecrow.com/crowpanel-esp32-2-9-e-paper-hmi-display-with-128-296-resolution-black-white-color-driven-by-spi-interface.html), +[CrowPanel](https://www.elecrow.com/wiki/CrowPanel_ESP32_E-paper_2.9-inch_HMI_Display.html), which is exactly what I need. It has a display, a built-in ESP32 controller, a housing, and even some switches! As a huge plus, they even specify which display controller they use. I had to try some of the GxEPD2 display classes, but finally found one working. I decided to glue magnets onto the housing, and attach the display via magnets -on the inner side of my shirt &emdash; not ideal. I positioned the magnets in +on the inner side of my shirt — not ideal. I positioned the magnets in the (vertical) middle of the housing, so it wobbles and is not readable. Also, I accidentally washed the shirt after Awoostria with the magnets still sticking -inside &emdash; and now there's a hole in it. :( This problem is still +inside — and now there's a hole in it :( . This problem is still unsolved. I can kinda attach the magnets to the housing screws at the top, but that's not *very* stable. +When starting to work with the Elecrow display, at first nothing would work. +When I looked at their example code I noticed there's an additional power pin +that needs to be toggled. + ## Set what is displayed @@ -129,10 +137,10 @@ something "more direct", so I added the of coding, I added a service and some characteristics, so the available motives could be read via BLE. Also, the motive could be selected via another characteristic. I started writing the characteristic with *nRF Connect For -Mobile*, but started writing an app later. +Mobile*, but started writing an app [later](#theapp). Actually, the switch-selection was a bit troublesome. Redrawing the whole -display takes around 2 seconds &emdash; but that is not acceptable when +display takes around 2 seconds — but that is not acceptable when navigating the presets one-by-one. By looking at the API, I found out you can select a "partial region". @@ -142,14 +150,14 @@ vertical-center-right of the display with the mood text. The picture stays the same, but the text reflects the selected mood. The selection is confirmed my pressing the rotary switch. -This is still not ideal. The first update must be a full one, and I don't save -the selected preset in NVS &emdash; I don't want to destroy the flash by -hundreds/thousands of write cycles. I don't have a solution to this, yet. Maybe -I'm gonna integrate an microSD card (there's a slot for that!n the CrowPanel). -I'm gonna research a good wear-levelling file system for that. Probably not +This is still not ideal. The first update after power-up must be a full one, +and I don't save the selected preset in NVS — I don't want to destroy the +flash by lots of write cycles. I don't have a solution to this, yet. Maybe I'm +gonna integrate an microSD card (there's a slot for that in the CrowPanel). +I'm gonna research a good wear-levelling file system for that. Probably not FAT. That doesn't need to be readable on the PC. (And even if, simple stuff -can be written in FUSE). Drawing the first motive on power-up would also be an -option, but I don't like it that much. +can be written in FUSE). Alternatively, drawing the first motive on power-up +would also be an option, but I don't like it that much. ## Power saving @@ -170,7 +178,15 @@ why! Apropos of powering: The badge is normally unpowered and only powered if I need to change the motive. I don't want to have an USB cable hanging on me the whole -time! +time! Using a battery might be an option, but I had problems with mismatched +connectors — the Elecrow display doesn't have a standard JST connector +like the LiPo battery I bought (Li-Ion might even be the safer option? I have +no clue about this stuff. With a quick search, I only found these cyclindric +Li-Ion batteries and have no idea how I would connect them). The badge seems to +have a "mini" variant of that connector. + +For the time being, I power it with a USB powerbank, but this I still consider +an unsolved problem. ## The app @@ -1020,9 +1036,177 @@ settled for Flutter. Again, this was completely new to me. I started off with a popular BLE library, which turned out to be an unfortunate choice, as Linux support had a few quirks. That was probably a good thing in hindsight, as this made me abstract -away the BLE stuff in implementation classes, and only use the abstract base -classes in the code. Well, you can see what the code looks like, I linked my -repo below. +away the BLE stuff in implementation classes, so I could easily try out +different libraries, and only use the abstract base classes in the code. Well, +you can see what the code looks like, I linked my repo below. This is what the +motive selection looks like: + +Screenshot of the Flutter app, allowing selection from
+  sleepy, hungry, hugs?, uvok, overstim, contact, games? ## Resources -- cgit v1.2.3