Now Reading
One more E-Ink climate show

One more E-Ink climate show

2023-09-26 11:06:21

I made a type of e-ink climate shows that you simply see on tech blogs and hacker information generally. It might probably show the present climate, the temperature and precipitation forecast for the remainder of the week, and my present and upcoming duties from Todoist. It is powered by a pair NiMH AA batteries and lasts no less than a pair months on a single cost, if no more.

hall display

The code could be discovered on my github.

E-ink show

The display screen is a 7.5″, 800 by 480 pixel, 3-color e-ink display that I bought from waveshare. It does black, white, and purple, which is barely uncommon for e-ink and will increase the value and lowers the refresh price, however seems very nice. I consider it really works (skipping over how e-ink works typically) by first pushing the black particles to the entrance, after which pushing the purple particles, that are possibly smaller or lighter or much less dense, additional in entrance of the black ones.

Microcontroller

I purchased a pre-assembled ESP32 board, additionally from waveshare, which accommodates the FPC connector already assembled and related to the ESP32 module’s SPI pins.

I desoldered the on-board LEDs to extend battery life, for the reason that energy LED was at all times on, and the opposite led appeared to be barely receiving/drawing energy throughout sleep. I used to be in a position to flip it off in software program by configuring an inner pulldown to remain on throughout sleep however I wasn’t positive if that might additionally draw some present so I simply eliminated it since I wasn’t utilizing it.

This challenge consists of two totally different Rust initiatives.

There’s the code that runs on the esp32 board related to the show, after which there’s additionally code working on a server that each gathers the info and renders it to a file. Initially I used to be going to do all the pieces on-device, however for the reason that show is battery-powered I believed it will be extra environment friendly to obtain a single file and show it. So all of the API requests, graph drawing, and textual content rendering operations occur on the server, and the show board successfully acts as a dumb terminal which simply shows the info it receives.

On-device software program

ESP32 overview

For the “firmware” working on the esp32 board, I am utilizing esp-idf with the usual library (i.e. not no-std) through the esp-rs challenge.

Setup is a tiny bit sophisticated, however the esp-rs book is a superb information and explains all the pieces pretty clearly. Hopefully at some point it is going to be so simple as “edit your runner in .cargo/config.toml to make use of espflash after which simply cargo run” though I feel for RISC-V boards with no-std it may be fairly shut already. I added a Justfile that exports the libclang and esp toolchain atmosphere variables internally in order that I can simply construct and simply run.

The esp32-std embedded ecosystem is comprised of a number of totally different crates, together with:
esp-idf-sys, which accommodates bindgen bindings to the esp-idf C API
esp-idf-hal, which accommodates higher-level, type-safe wrappers and drivers for {hardware} like GPIO and SPI
esp-idf-svc, which accommodates implementations and wrappers for system providers like Wifi and storage

Moreover, the above crates use and implement traits from the next embedded-rust ecosystem crates:
embedded-hal
embedded-svc

and several other different setup utility binaries like espup, espflash, and embuild, along with a fork of the rust compiler for the Xtensa/ESP32 structure (there are additionally RISC-V ESP32 processors which do not require the forked compiler and llvm).

I principally learn instance code, the assorted initiatives’ talked about above documentation, and the esp-idf documentation to determine learn how to put all the pieces collectively. Particularly this repo is pretty intensive: https://github.com/ivmarkov/rust-esp32-std-demo

It may be considerably complicated to determine which varieties you want from which crates to e.g. activate wifi, however this is not distinctive to esp32 or embedded rust. Libraries will take traits from embedded-hal/svc as impl parameters and it might generally be tough to determine learn how to instantiate concrete variations of these varieties. Usually the pattern code is beneficial in these instances to get issues began.

General, the code is fairly easy.

  1. We “collect” the peripherals we’d like – spi, the modem for wifi, and the gpio pin used to get up through button press
  2. Activate the wifi
  3. Get the show information from the server
  4. Flip off the wifi
  5. Ship the info to the show and wait till we anticipate it is executed
  6. Inform the e-ink show to fall asleep
  7. Inform the gadget to sleep for 90 minutes or till the button is pressed

The URL to request the info from and the wifi SSID and password are simply constants in a src/config.rs file which is not checked in to git. This will get baked into the ultimate binary.

Getting the info

To request the show information from the server, we use the esp_idf_svc::http and embedded_svc::http modules.

There actually is not an excessive amount of to the code – it is a fairly commonplace http request. The one factor of notice is that we explicitly test that we’re getting the correct measurement file again from the server to suit the show.

Waveshare e-ink driver

To ship the picture information to the show, we use the epd-waveshare crate, however as a result of the final launch was revealed to crates.io 2 years in the past, we’ve got to make use of the git repo url straight in our Cargo.toml file. My show makes use of the “epd7in5b_v2” driver. The sticker on the again says v3 however all the pieces appears to work.

Apart from that all the pieces simply works – you arrange the SPI gadget, cross it to the library and provides it the picture information. It does not appear to attend for the show to really end updating, so we look forward to about 20 seconds earlier than sending a sleep sign to the show, which lowers its energy consumption. Because it’s an e-ink show, the picture continues to be displayed even throughout sleep, after all.

Apart: The reminiscence structure for the show information is simply the uncooked bits bitpacked into bytes. The purple pixels are dealt with by merely having two separate buffers packed subsequent to one another. That is inefficient when it comes to area – we might as a substitute do a variable size encoding scheme the place say 0 is white, 10 is black and 11 is purple. Nevertheless, this could make it considerably slower to do commonplace drawing operations on as a result of particular person pixel entry turns into O(n).

Rendering software program

The rendering code was by far essentially the most fascinating. Every little thing is drawn with the imageproc crate, which makes use of the image crate and the rusttype crate for fonts. Moreover, it makes use of the identical epd_waveshare crate and in addition the embedded_graphics crate to pack the picture buffer into the format utilized by the show driver.

So once more, the technique right here is to attract the picture right into a generic picture buffer, after which “render” it into the driving force show library’s buffer kind as if the code had been working straight on the gadget. Then as above the esp32 downloads the file and sends it on to the show with out having to do any additional work.

Gathering the info

I am utilizing weather.gov’s free API for the climate information, which requires only a couple HTTP requests to get the present climate and the forecast. To determine the station and gridpoint parameters for the requests, you will have to make a pair requests manually to another endpoints that take GPS coordinates and return the closest stations and gridpoint.

The todo record information is only a single API request with a filter of -24h to +48h on the due date.

Drawing and measuring textual content

Whereas imageproc has a built-in perform for drawing textual content, I needed to write a number of variations of wrappers to get totally different alignments. The measure_text perform I am fairly positive was taken from instance code someplace in rusttype or imageproc.

Drawing the graphs

Imageproc’s line drawing strategies are simply fundamental Bresenham and haven’t any thickness parameter, so to get thick strains I simply drew them with the beginning and finish factors offset vertically by a pixel. Word that this clearly doesn’t work for completely straight strains and mathematically you’d wish to offset by the vector perpendicular to the unique line, however for the reason that graph is usually horizontal it really works nice for this case.

Relating to the precipitation graph, it was a good quantity of trial and error to get it wanting the best way I imagined it. The code is slightly obscure and I am fairly positive it may be simplified. The concept is that we simply cut up the graph into 6×6 squares, activate some pixels on the diagonal, after which offset the squares themselves. The final half is the half that I feel may very well be simplified (or no less than higher defined) and is expressed within the xm variable within the code.

I actually love how the skinny strains within the precipitation graph actually make it look blue though it is the identical black as the remainder of the picture.

Dithering and “rendering” to the show buffer

Because the show can solely deal with 3 colours however the textual content is rendered with anti-aliasing (and I could not discover a straightforward solution to not anti-alias) I ended up utilizing the picture crate’s dithering performance with only a manually-tuned cutoff level that regarded good with the font and the show. Thankfully e-ink shows are a bit fuzzy as a result of their development, so mixed with the curvy font I selected it’s extremely arduous to see any artifacts with out wanting very carefully.

See Also

After the ultimate picture is dithered to white/black/purple, we use the identical precise crate that is used within the firmware, however this time to write down the buffer as a substitute ofread it. All we’ve got to do is enumerate over the pixels within the picture and name set_pixel contained in the buffer, and the crate takes care of doing the bitpacking for us. It may very well be executed extra effectively, however since we’re not working on the gadget it does not matter as a lot.

Working the rendering software program

In contrast to the firmware, the rendering software program takes an precise json-formatted config file as a cli parameter, together with the placement of the output file.

The rendering binary will get run each hour through a systemd person service and timer file which could be discovered within the scripts/ listing. In my case, the output file will get put right into a listing which nginx is configured to serve static recordsdata from.

Extrasafe

I used my very own extrasafe crate within the rendering software program on the server. It lets you prohibit your software program’s syscall utilization to a subset of your selecting via seccomp. We begin one thread to make the HTTP requests to all of the APIs, then cross that uncooked JSON information to a different thread with even much less privileges to do the parsing, and eventually cross that again to the primary thread, the place we then do our ultimate restriction that solely permits us to write down to the output file. I feel ideally we’d first spawn the threads, wait till the unique thread is restricted, and then run the opposite threads, however with a couple of employee thread within the sequence it turns into tough to arrange all the pieces manually.

I am presently engaged on enhancements to extrasafe to permit using Landlock and in addition possibly a helper perform for the unshare syscall. Particularly I would like to limit the community thread’s filesystem entry to solely the mandatory recordsdata for DNS and SSL, slightly than all recordsdata.

I realized learn how to use CAD software program for this challenge and it was easier than I believed it will be.

First, you choose a airplane to attract on, which could be both a airplane alongside two main axes, or a airplane shaped by a part of your mannequin that you have drawn alreday. Then you possibly can draw 2D shapes on that airplane with commonplace 2D curve instruments like strains, bezier curves, conics, and many others. As soon as you have obtained the elements of your form in place, you then have to constrain the form. Right here “constrain” means to lock within the place, dimension, and different parameters comparable to angles, radii, management level place, which you do with operations like “these two factors are concurrent”, “these two factors are symmetric about this line”, “these two strains are perpendicular”, “the size of this line is 5mm”, “the angle between these two strains is 30 levels”. Lastly, again in “3D mode”, you need to use instruments to extrude, reduce out pockets, revolve, or in any other case 3d-ify the second sketches you drew.

Moreover, you may make a spreadsheet or mapping of labeled dimensions and use them within the second sketches or extrusions instead of utilizing particular dimensions like “5mm” and the mannequin will routinely be up to date while you change the values. General it is truly fairly enjoyable, though possibly a bit tedious.

I attempted out each freecad and onshape, and freecad appeared a bit too straightforward to get right into a buggy state however I in any other case preferred the constraint interface. Particularly one tiny factor I preferred about freecad was that the sketch turned a really seen inexperienced when it is totally constrained. Onshape’s blue/black scheme is fairly low distinction and could be arduous to see, particularly when utilizing flux or redshift. Possibly I simply missed an exterior indicator that stated whether or not the sketch was totally constrained or not. The built-in variables desk in onshape was easier than freecad, the place it’s important to use spreadsheet workbench or a separate plugin, and even then I am fairly positive it’s important to kind spreadsheet.<identify> or dd.dd<identify> everytime you wish to use a variable inside a sketch. I additionally did not see a means in onshape to see an inventory of constraints like you possibly can see in freecad.

I had the case printed by JLCPCB in white resin through SLA for about $20 – $30 USD shipped and it was each very easy and it got here out fairly clear. I needed to do a second revision as a result of I tousled with the bezel measurement (unintentionally made it symmetric slightly than the underside having a bigger lip) and the second order got here out simply nearly as good or higher than the primary. Here’s the oncad project.

I could not discover any low-cost 3D printing providers within the US to do the print for me – I assume they both get outcompeted on labor prices by China or there is not demand for them on a hobbyist stage as a result of hobbyists should buy their very own or use a makerspace’s printer?

The case is mounted on the wall with common Command image hanging strips – I designed pads on the bottom of the case particularly for this goal.

  • Case snap-fit for pcb, possibly for show as nicely/or simply helps
    • I am not likely positive what’s doable for resin when it comes to each printability and adaptability / skinny elements
  • Customized PCB with a decrease quiescient present voltage regulator for improved battery life? Plus on-board battery holder.
  • The climate.gov API is sometimes flakey or gives unhealthy JSON, possibly add a retry choice through the systemd unit file
  • Add some code to notice if the picture from the server hasn’t been up to date (both through evaluating to an RTC or storing the final profitable replace time in flash) after which possibly draw a purple dot or line within the prime nook or someplace. This is able to be equal to only setting one or a pair bytes to all 1s within the binary, so it would not be very tough.
  • Minor points with graph information
  • Make every day excessive/lows purple and smaller
  • Present every day excessive/lows for present day
  • Measure present draw precisely
  • Present ranger / ucurrent gold / borrow one from someplace?
  • Higher check the renderer
  • Arrange some form of testing with qemu for the firmware

It is very easy and enjoyable to get began writing code for microcontrollers in Rust! CAD can also be fairly enjoyable.

Due to Neil Chen and Stan Zhang for reviewing a draft of this publish

Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top