Finish lca2019 post

This commit is contained in:
Wesley Moore 2019-01-27 11:26:22 +11:00
parent 20c7413375
commit a12f0395d0
No known key found for this signature in database
GPG key ID: BF67766C0BC2D0EE
12 changed files with 229 additions and 153 deletions

View file

@ -1,31 +1,31 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
addressable (2.5.2) addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0) public_suffix (>= 2.0.2, < 4.0)
adsf (1.4.0) adsf (1.4.1)
rack (>= 1.0.0, < 3.0.0) rack (>= 1.0.0, < 3.0.0)
bitly (1.1.0) bitly (1.1.2)
httparty (>= 0.7.6) httparty (>= 0.7.6)
multi_json (~> 1.3) multi_json (~> 1.3)
oauth2 (>= 0.5.0, < 2.0) oauth2 (>= 0.5.0, < 2.0)
builder (3.2.3) builder (3.2.3)
coderay (1.1.2) coderay (1.1.2)
colored (1.2) colored (1.2)
concurrent-ruby (1.0.5) concurrent-ruby (1.1.4)
cri (2.13.0) cri (2.15.3)
colored (~> 1.2) colored (~> 1.2)
ddmemoize (1.0.0) ddmemoize (1.0.0)
ddmetrics (~> 1.0) ddmetrics (~> 1.0)
ref (~> 2.0) ref (~> 2.0)
ddmetrics (1.0.1) ddmetrics (1.0.1)
ddplugin (1.0.2) ddplugin (1.0.2)
faraday (0.12.2) faraday (0.15.4)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
ffi (1.9.25) ffi (1.10.0)
formatador (0.2.5) formatador (0.2.5)
fssm (0.2.10) fssm (0.2.10)
guard (2.14.2) guard (2.15.0)
formatador (>= 0.2.4) formatador (>= 0.2.4)
listen (>= 2.7, < 4.0) listen (>= 2.7, < 4.0)
lumberjack (>= 1.0.12, < 2.0) lumberjack (>= 1.0.12, < 2.0)
@ -35,72 +35,73 @@ GEM
shellany (~> 0.0) shellany (~> 0.0)
thor (>= 0.18.1) thor (>= 0.18.1)
guard-compat (1.2.1) guard-compat (1.2.1)
guard-nanoc (2.1.3) guard-nanoc (2.1.4)
guard (~> 2.8) guard (~> 2.8)
guard-compat (~> 1.0) guard-compat (~> 1.0)
nanoc (>= 4.3.8, < 5.0) nanoc (>= 4.3.8, < 5.0)
haml (5.0.3) haml (5.0.4)
temple (>= 0.8.0) temple (>= 0.8.0)
tilt tilt
hamster (3.0.0) hamster (3.0.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
httparty (0.15.6) httparty (0.16.3)
mime-types (~> 3.0)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
jwt (1.5.6) json_schema (0.20.1)
jwt (2.1.0)
listen (3.1.5) listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7) rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2) ruby_dep (~> 1.2)
lumberjack (1.0.13) lumberjack (1.0.13)
method_source (0.9.0) method_source (0.9.2)
mime-types (3.1) mime-types (3.2.2)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521) mime-types-data (3.2018.0812)
mini_portile2 (2.3.0) mini_portile2 (2.4.0)
multi_json (1.12.2) multi_json (1.13.1)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.0.0) multipart-post (2.0.0)
nanoc (4.9.3) nanoc (4.11.0)
addressable (~> 2.5) addressable (~> 2.5)
cri (~> 2.8) cri (~> 2.15)
ddmemoize (~> 1.0) ddmemoize (~> 1.0)
ddmetrics (~> 1.0) ddmetrics (~> 1.0)
ddplugin (~> 1.0) ddplugin (~> 1.0)
hamster (~> 3.0) hamster (~> 3.0)
json_schema (~> 0.19)
parallel (~> 1.12) parallel (~> 1.12)
ref (~> 2.0) ref (~> 2.0)
slow_enumerator_tools (~> 1.0) slow_enumerator_tools (~> 1.0)
tomlrb (~> 1.2) tomlrb (~> 1.2)
nenv (0.3.0) nenv (0.3.0)
nokogiri (1.8.1) nokogiri (1.10.1)
mini_portile2 (~> 2.3.0) mini_portile2 (~> 2.4.0)
notiffany (0.1.1) notiffany (0.1.1)
nenv (~> 0.1) nenv (~> 0.1)
shellany (~> 0.0) shellany (~> 0.0)
oauth2 (1.4.0) oauth2 (1.4.1)
faraday (>= 0.8, < 0.13) faraday (>= 0.8, < 0.16.0)
jwt (~> 1.0) jwt (>= 1.0, < 3.0)
multi_json (~> 1.3) multi_json (~> 1.3)
multi_xml (~> 0.5) multi_xml (~> 0.5)
rack (>= 1.2, < 3) rack (>= 1.2, < 3)
parallel (1.12.1) parallel (1.13.0)
pry (0.11.3) pry (0.12.2)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.9.0) method_source (~> 0.9.0)
public_suffix (3.0.3) public_suffix (3.0.3)
rack (2.0.3) rack (2.0.6)
rake (12.1.0) rake (12.3.2)
rb-fsevent (0.10.3) rb-fsevent (0.10.3)
rb-inotify (0.9.10) rb-inotify (0.10.0)
ffi (>= 0.5.0, < 2) ffi (~> 1.0)
rb-kqueue (0.2.5)
ffi (>= 0.5.0)
rdiscount (2.2.0.1) rdiscount (2.2.0.1)
ref (2.0.0) ref (2.0.0)
rouge (3.2.1) rouge (3.3.0)
ruby_dep (1.5.0) ruby_dep (1.5.0)
rubypants (0.6.0) rubypants (0.7.0)
sass (3.5.1) sass (3.7.3)
sass-listen (~> 4.0.0) sass-listen (~> 4.0.0)
sass-listen (4.0.0) sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.9, >= 0.9.4)
@ -109,9 +110,9 @@ GEM
slow_enumerator_tools (1.1.0) slow_enumerator_tools (1.1.0)
systemu (2.6.5) systemu (2.6.5)
temple (0.8.0) temple (0.8.0)
thor (0.20.0) thor (0.20.3)
tilt (2.0.8) tilt (2.0.9)
tomlrb (1.2.7) tomlrb (1.2.8)
PLATFORMS PLATFORMS
ruby ruby
@ -128,7 +129,6 @@ DEPENDENCIES
nanoc (~> 4.0) nanoc (~> 4.0)
nokogiri nokogiri
rake rake
rb-kqueue (>= 0.2)
rdiscount rdiscount
rouge rouge
rubypants rubypants
@ -136,4 +136,4 @@ DEPENDENCIES
systemu systemu
BUNDLED WITH BUNDLED WITH
1.16.3 1.17.2

View file

@ -1,23 +1,31 @@
This week I attended linux.conf.au (for the first time) in Christchurch, New This week I attended [linux.conf.au] (for the first time) in Christchurch, New
Zealand. It's a week long conference covering Linux, open open source software Zealand. It's a week long conference covering Linux, open open source software
and hardware, privacy, security and much more. The theme this year was [IoT]. and hardware, privacy, security and much more. The theme this year was [IoT].
In line with the theme I built a digital conference badge to take to the In line with the theme I built a digital conference badge to take to the
conference. It used a tri-colour e-Paper display and was powered by a Rust conference. It used a tri-colour e-Paper display and was powered by a Rust
program I built running on Raspbian Linux. This post describes how it was program I built running on [Raspbian Linux][Raspbian]. This post describes how
built, how it works, and how it fared at the conference. it was built, how it works, and how it fared at the conference. The [source
code is on GitHub][source].
### Building <figure>
<a href="/images/2019/badge-at-end-of-conference.jpg"><img src="/images/2019/badge-at-end-of-conference_thumb.jpg" width="600" alt="The badge in its final state after the conference." /></a>
<figcaption>The badge in its final state after the conference</figcaption>
</figure>
## Building
After booking my tickets in October I decided I wanted to build a digital After booking my tickets in October I decided I wanted to build a digital
conference badge. I'm not entirely sure what prompted me to do this but it was conference badge. I'm not entirely sure what prompted me to do this but it was
a combination of seeing projects like the [BADGEr] in past, the theme of a combination of seeing projects like the [BADGEr] in the past, the theme of
linux.conf.au 2019 being IoT, and an excuse to write more Rust. Since it was linux.conf.au 2019 being IoT, and an excuse to write more Rust. Since it was
ostensibly a Linux conference it also seemed appropriate for it to run Linux. ostensibly a Linux conference it also seemed appropriate for it to run Linux.
Over the next few weeks I collected the parts and adaptors to build the badge. The main components were: Over the next few weeks I collected the parts and adaptors to build the badge.
The main components were:
* [Raspberry Pi Zero W] - AU$15.00 * [Raspberry Pi Zero W] &mdash; AU$15.00
* [Pimoroni Inky pHAT] e-Paper display - AU$38.00 * [Pimoroni Inky pHAT] e-Paper display &mdash; AU$38.00
* 4800mAh/3.7V USB battery pack that I already owned
The Raspberry Pi Zero W is a single core 1Ghz ARM SoC with 512Mb RAM, Wi-FI, The Raspberry Pi Zero W is a single core 1Ghz ARM SoC with 512Mb RAM, Wi-FI,
Bluetooth, microSD card slot, and mini HDMI. The Inky pHAT is a 212x104 pixel Bluetooth, microSD card slot, and mini HDMI. The Inky pHAT is a 212x104 pixel
@ -25,40 +33,35 @@ tri-colour (red, black, white) e-Paper display. It takes about 15 seconds to
refresh the display but it draws very little power in between updates and the refresh the display but it draws very little power in between updates and the
image persists even when power is removed. image persists even when power is removed.
I powered the badge with a several year old 4800mAh USB battery pack that I
already owned. Some rough calculations suggested that it should run for many
hours on this battery but I didn't actually test this until day 1 of the
conference.
### Support Crates ### Support Crates
The first part of the project involved building a Rust driver for the The first part of the project involved building a Rust driver for the
controller in the e-Paper display. That involved determining what controller controller in the e-Paper display. That involved determining what controller
the display used, as Pimoroni did not document the display they used for the the display used, as Pimoroni did not document it. Searching online for some of
Inky pHAT. Searching online for some of the comments in the Python driver the comments in [the Python driver][inky] suggested the display was possibly a
suggested the display was possibly a HINK-E0213A07 - Electronic Paper display HINK-E0213A07 from Holitech Co. Further searching based on [the datasheet for
from Holitech Co. Further searching based on [the datasheet for that that display][HINK-E0213A07] suggested that the controller was a [Solomon
display][HINK-E0213A07] suggested that the controller was a [Solomon Systech Systech SSD1675][SSD1675]. Cross referencing the display datasheet, [SSD1675
SSD1675][SSD1675]. Cross referencing the display datasheet, [SSD1675 datasheet], and the [Python source of Pimoroni's Inky pHAT driver][inky]
datasheet], and the [Python source of Pimoroni's Inky pHAT suggested I was on the right track.
driver][https://github.com/pimoroni/inky] suggested I was on the right track.
I set about building the Rust driver for the SSD1675 using the [embedded HAL I set about building the Rust driver for the SSD1675 using the [embedded HAL
traits]. These traits allow embedded Rust drivers to be built against a traits][embedded-hal]. These traits allow embedded Rust drivers to be built
defacto-standard set of traits that allow the driver to be used in any against a de facto standard set of traits that allow the driver to be used in
environment that implements the traits. For example I make use of traits for any environment that implements the traits. For example I make use of traits
[SPI] devices, and [GPIO] pins, which are implemented for for [SPI] devices, and [GPIO] pins, which are implemented for
[Linux][embedded-linx], as well as say, [STM32 dev boards]. This allows the [Linux][linux-embedded-hal], as well as say, [the STM32F30x family of
driver to be written once and be potentially usable on may different devices. microcontrollers][stm32f30x-hal]. This allows the driver to be written once and
used on many devices.
The result was the [ssd1675 crate]. It's a so called no-std crate. That means The result was the [ssd1675 crate]. It's a so called no-std crate. That means
it does not use the Rust standard library, instead sticking only to the core it does not use the Rust standard library, instead sticking only to the core
library. This allows the crate to be used in devices and microcontrollers library. This allows the crate to be used on devices and microcontrollers
without features like file systems, or heap allocators. The crate also makes without features like file systems, or heap allocators. The crate also makes
use of the [embedded-graphics crate][embedded-graphics], which makes it easy to use of the [embedded-graphics crate][embedded-graphics], which makes it easy to
draw text and basic shapes on the display in a memory efficient manner. draw text and basic shapes on the display in a memory efficient manner.
Whilst testing the ssd1675 crate I also built another crate, [profont], which While testing the ssd1675 crate I also built another crate, [profont], which
provides 7 sizes of the [ProFont font] for embedded graphics. The profont crate provides 7 sizes of the [ProFont font] for embedded graphics. The profont crate
was published 24 Nov 2018, and ssd1675 was published a month later on 26 Dec was published 24 Nov 2018, and ssd1675 was published a month later on 26 Dec
2018. 2018.
@ -68,62 +71,116 @@ was published 24 Nov 2018, and ssd1675 was published a month later on 26 Dec
Now that I had all the prerequisites in place I could start working on the Now that I had all the prerequisites in place I could start working on the
badge proper. I had a few goals for the badge and its implementation: badge proper. I had a few goals for the badge and its implementation:
* I wanted the badge to have some interactive component. * I wanted it to have some interactive component.
* I wanted there to be some sort of Internet aspect to tie in with the IoT * I wanted there to be some sort of Internet aspect to tie in with the IoT
theme of the conference. theme of the conference.
* I wanted the badge to be entirely powered by a single, efficient Rust binary, * I wanted the badge to be entirely powered by a single, efficient Rust binary,
that did not shell out to other commands, or anything like that. that did not shell out to other commands or anything like that.
* Ideally it would be relatively power efficient. * Ideally it would be relatively power efficient.
<figure> <figure>
<img src="/images/2019/badge-early-revision_thumb.jpg" width="600" alt="Photo of e-Paper display showing my name, websize, IP address and uname information." /> <a href="/images/2019/badge-early-revision.jpg"><img src="/images/2019/badge-early-revision_thumb.jpg" width="600" alt="An early revision of the badge from 6 Jan 2019 showing my name, website, badge IP, and kernel info." /></a>
<figcaption>An early revision of the badge from 6 Jan 2019</figcaption> <figcaption>An early revision of the badge from 6 Jan 2019</figcaption>
</figure> </figure>
I settled on having the badge program serve up a web page with some information I settled on having the badge program serve up a web page with some information
about the project, myself, and some live stats of the Raspberry Pi (uptime, about the project, myself, and some live stats of the Raspberry Pi (OS, kernel,
free RAM, etc.). The plain text version of the page looked like this: uptime, free RAM). The plain text version of the page looked like this:
[Insert sample response hre] Hi I'm Wes!
The interactive part came in the form of a virtual 'hi' counter. Each HTTP POST Welcome to my conference badge. It's powered by Linux and
to the `/hi` endpoint incremented the count, which was shown on the badge. The Rust running on a Raspberry Pi Zero W with a tri-colour Inky
badge showed a URL to access in order to view the page, the URL was just the pHAT ePaper dispay. The source code is on GitHub:
badge's IP address on the conference Wi-Fi. To provide a little protection
against abuse I added code that only allowed a give IP to increment the count
once per hour.
When building the badge software these are some of the details and goals I implemented: https://github.com/wezm/linux-conf-au-2019-epaper-badge
* Wi-Fi going away
* IP address changing Say Hello
* Memory use of large POSTs (don ---------
12 people have said hi.
Say hello in person and on the badge. To increment the hello
counter on the badge:
curl -X POST http://10.0.0.18/hi
About Me
--------
I'm a software developer from Melbourne, Australia. I
currently work at GreenSync building systems to help make
better use of renewable energy.
Find me on the Internet at:
Email: wes@wezm.net
GitHub: https://github.com/wezm
Mastodon: https://mastodon.social/@wezm
Twitter: https://twitter.com/wezm
Website: http://www.wezm.net/
Host Information
----------------
(_\)(/_) OS: Raspbian GNU/Linux
(_(__)_) KERNEL: Linux 4.14.79+
(_(_)(_)_) UPTIME: 3m
(_(__)_) MEMORY: 430.3 MB free of 454.5 MB
(__)
.------------------------.
| Powered by Rust! |
'------------------------'
/
/
_~^~^~_
\) / o o \ (/
'_ - _'
/ '-----' \
The interactive part came in the form of a virtual "hello" counter. Each HTTP
POST to the `/hi` endpoint incremented the count, which was shown on the badge.
The badge displayed the URL of the page. The URL was just the badge's IP
address on the conference Wi-Fi. To provide a little protection against abuse I
added code that only allowed a given IP to increment the count once per hour.
When building the badge software these are some of the details and things I
strived for:
* Handle Wi-Fi going away
* Handle IP address changing
* Prevent duplicate submissions * Prevent duplicate submissions
* Pluralisation of text on the badge and on the web page * Pluralisation of text on the badge and on the web page
* Automatically shift the text as the count requires more digits * Automatically shift the text as the count requires more digits
* Serve plain text and HTML pages:
* If the web page is requested with an `Accept` header that doesn't include * If the web page is requested with an `Accept` header that doesn't include
`text/html` (E.g. `curl`) then the response is plain text and the method to `text/html` (E.g. `curl`) then the response is plain text and the method to,
"say hello" is a curl command. If the user agent indicates they accept HTML "say hello", is a `curl` command.
then the page is HTML and conttains a form with a button to, "say hello". * If the user agent indicates they accept HTML then the page is HTML and
contains a form with a button to, "say hello".
* Avoid aborting on errors: * Avoid aborting on errors:
* I kind of ran out of time to handle all errors well, but most are handled * I kind of ran out of time to handle all errors well, but most are handled
gracefully and won't abort the program. In some cases a default is used in gracefully and won't abort the program. In some cases a default is used in
the face of an eror. In other cases I just resorted to logging a mesasge and the face of an error. In other cases I just resorted to logging a message and
carrying on. carrying on.
* Keep memory usage low: * Keep memory usage low:
* The web server efficiently discards any large POST requests sent to it, to * The web server efficiently discards any large POST requests sent to it, to
avoid exhausing RAM. Typical RAM stats showed around 420Mb free of the avoid exhausting RAM.
512Mb most of the time, of which some is taken for the GPU. The Rust * Typical RAM stats showed the Rust program using about 3Mb of RAM.
program itself using about 4Mb. * Be relatively power efficient:
* Be relatively power efficient
* Use Rust instead of a scripting language * Use Rust instead of a scripting language
* Only update the display when something it's showing changes * Only update the display when something it's showing changes
* Only check for changes every 15 seconds (the rest of the time that tread just slept) * Only check for changes every 15 seconds (the rest of the time that thread just sleeps)
* Put the display into deep sleep after updating * Put the display into deep sleep after updating
I used [hyper] for the HTTP server. To get a feel for the limits of the device I used [hyper] for the HTTP server built into the binary. To get a feel for the
I did some rudimentary HTTP benchmarking with [wrk] and concluded that 300 requests limits of the device I did some rudimentary HTTP benchmarking with [wrk] and
per second was was probably going to be fine. ;) concluded that 300 requests per second was was probably going to be fine. `;-)`
Running 10s test @ http://10.0.0.18:8080/ Running 10s test @ http://10.0.0.18:8080/
4 threads and 100 connections 4 threads and 100 connections
@ -136,41 +193,38 @@ per second was was probably going to be fine. ;)
### Mounting ### Mounting
When I started the project I imagined it would hang it around my neck like When I started the project I imagined it would hang it around my neck like a
conference lanyard. When departure day arrived I still hadn't worked out how conference lanyard. By the time departure day arrived I still hadn't worked out
this would work in practice (power delivery being a major concern). In the end how this would work in practice (power delivery being a major concern). In the
I settled on attaching it to the strap on my backpack. My bag has lots of end I settled on attaching it to the strap on my backpack. My bag has lots of
webbing so there were plenty of loops to hold it in place. I was also able to webbing so there were plenty of loops to hold it in place. I was also able to
use the velcro covered holes intended for water tubes to get the cable neatly use the Velcro covered holes intended for water tubes to get the cable neatly
into the bag. into the bag.
## At the Conference ## At the Conference
I had everything pretty much working for the start of the conference, although I had everything pretty much working for the start of the conference. Although
I did make some final improvements and add a systemd unit to automatically start I did make some improvements and add a [systemd unit] to automatically start
and restart the Rust binary once I arrived in my accommodation on the Sunday and restart the Rust binary. At this point there were still two unknowns:
before the conference. At this point there were still two unknowns: battery battery life and how the Raspberry Pi would handle coming in and out of Wi-Fi
life and how the Raspberry Pi would handle coming in and out of Wi-Fi range. range. The Wi-Fi turned out fine: It automatically reconnected whenever it
The Wi-Fi turned out fine: automatically reconnecting whenever it came into came into range of the Wi-Fi.
range of the Wi-Fi.
<figure> <figure>
<img src="/images/2019/badge-sunday-night_thumb.jpg" width="600" alt="Badge display a count of zero." /> <a href="/images/2019/badge-sunday-night.jpg"><img src="/images/2019/badge-sunday-night_thumb.jpg" width="600" alt="Badge displaying a count of zero." /></a>
<figcaption>Ready for day 1</figcaption> <figcaption>Ready for day 1</figcaption>
</figure> </figure>
### Reception ### Reception
At this point I had not had time to test battery life, so day one I hooked it Day 1 was a success! I had several people talk to me about the badge and
up and hoped for the best. Day 1 was a success! I had my first few people talk increment the counter. Battery life was good too. After 12 hours of uptime the
to me about the badge and increment the counter. Battery life was good too. battery was still showing it was half full. Later in the week I left the badge
After 12 hours of uptime the battery was still showing it was half full. Later running overnight and hit 24 hours uptime. The battery level indicator was on
in the week I left the badge running overnight to hit 24 hours uptime. The the last light so I suspect there wasn't much juice left.
battery level indicator was on the last light so I suspect there wasn't much
juice left.
<figure> <figure>
<img src="/images/2019/badge-first-hello_thumb.jpg" width="600" alt="Badge display showing a hello count of 1." /> <a href="/images/2019/badge-first-hello.jpg"><img src="/images/2019/badge-first-hello_thumb.jpg" height="600" alt="Me with badge display showing a hello count of 1." /></a>
<figcaption>Me after receiving my first hello on the badge</figcaption> <figcaption>Me after receiving my first hello on the badge</figcaption>
</figure> </figure>
@ -184,28 +238,31 @@ pixels. The change was a success, most people scanned the QR code from this
point on. point on.
<figure> <figure>
<img src="/images/2019/badge-with-qr-code_thumb.jpg" width="600" alt="Badge display now including QR code." /> <a href="/images/2019/badge-with-qr-code.jpg"><img src="/images/2019/badge-with-qr-code_thumb.jpg" width="600" alt="Badge display now including QR code." /></a>
<figcaption>Badge display showing the newly added QR code</figcaption> <figcaption>Badge display showing the newly added QR code</figcaption>
</figure> </figure>
On day 2 I also ran into [E. Dunham][edunham], and rambled briefly about my On day 2 I also ran into [E. Dunham][edunham], and rambled briefly about my
badge project and that it was built with Rust. To my absolute delight [the badge project and that it was built with Rust. To my absolute delight [the
project was featured in their talk the next day][edunham-talk]. The project was project was featured in their talk the next day][edunham-talk]. The project was
mentioned and linked on slide and I was asked to raise my hand in case anyone mentioned and linked on a slide and I was asked to raise my hand in case anyone
wanted to chat afterwards. wanted to chat afterwards.
<figure> <figure>
<img src="/images/2019/badge-edunham-talk_thumb.jpg" width="600" alt="Photo of E. Dunham's slide with a link to my git repo." /> <a href="/images/2019/badge-edunham-talk.jpg"><img src="/images/2019/badge-edunham-talk_thumb.jpg" width="600" alt="Photo of E. Dunham's slide with a link to my git repo." /></a>
<figcaption>Photo of E. Dunham's slide with a link to my git repo</figcaption> <figcaption>Photo of E. Dunham's slide with a link to my git repo</figcaption>
</figure> </figure>
At the end of the talk the audience was asked to talk about a Rust project they At the end of the talk the audience was encouraged to tell the rest of the room
were working on. Each person to do so got a little plush Ferris. I spoke about about a Rust project they were working on. Each person that did so got a little
[Read Rust] and am now the proud owner of a litle Ferris. plush [Ferris]. I spoke about [Read Rust].
[Insert Ferris here] <figure>
<a href="/images/2019/badge-plush-ferris.jpg"><img src="/images/2019/badge-plush-ferris_thumb.jpg" width="600" alt="Photo of a small orange plush crab." /></a>
<figcaption>Plush Ferris</figcaption>
</figure>
### CHANGEME What did I learn? ## Conclusion
By the end of the conference the badge showed a count of 12. It had worked By the end of the conference the badge showed a count of 12. It had worked
flawlessly over the five days. flawlessly over the five days.
@ -214,35 +271,54 @@ Small projects with a fairly hard deadline are a good way to ensure it's seen
through to completion. Also a great motivator to publish some open source code. through to completion. Also a great motivator to publish some open source code.
I think I greatly overestimated the number of people that would interact with I think I greatly overestimated the number of people that would interact with
the badge. Of those that did I think most tapped the button to increase the the badge. Of those that did, I think most tapped the button to increase the
counter and didn't read much else on the page. For example no one commented on counter and didn't read much else on the page. For example no one commented on
the system stats at the bottom of the page. I had imagined the badge as a sort the system stats at the bottom. I had imagined the badge as a sort of digital
of digital business card but this did not really eventuate in practice. business card but this did not really eventuate in practice.
Attaching the Pi and display to my bag worked out pretty well although I did Attaching the Pi and display to my bag worked out pretty well. I did have to be
have to be careful when putting my bag on and it was easy to catch on my careful when putting my bag on as it was easy to catch on my clothes. Also one
clothes. Also one day it started raining on the way back to the accommodation. day it started raining on the walk back to the accommodation. I had not
I had not factored that in at all and given it wasn't super easy to take on and factored that in at all and given it wasn't super easy to take on and off I
off I ended up shielding it with my hand all the way back. ended up shielding it with my hand all the way back.
TODO: Link to code ### Would I Do It Again?
TODO: Add images
### Would I do it again? Maybe. If I were to do it again I might do something less interactive and
perhaps more informational but updated more regularly. I might try to tie the
project into a talk submission too. For example, I could have submitted a talk
about using the embedded Rust ecosystem on a Raspberry Pi and made reference to
the badge in the talk or used it for examples. I think this would give more
info about the project to a bunch of people at once and also potentially teach
them something at the same time.
If I were to do it again I might do something less interactive and perhaps more All in all it was a fun project and excellent conference. If you're interested,
informational but updated more regularly. For example showing the previous and [the Rust source for the badge is on GitHub][source].
next talks to attend. Perhaps even allowing free text.
Maybe. I think if I were to do something along these lines again I might try to tie into a talk submission.
For example I could have submitted a talk about using the embedded Rust ecosystem on a Rasperry Pi and made
reference to the badge in the talk or used it for examples. I think this would give more info about the project
to a bunch of people at once and also potentially teach them something at the same time.
[BADGEr]: https://wyolum.com/projects/badger/ [BADGEr]: https://wyolum.com/projects/badger/
[HINK-E0213A07]: https://www.unisystem-displays.com/en/fileuploader/download/download/?d=0&file=custom%2Fupload%2Ffile%2F6f3084488018ca68c5bf0a26460e7c57%2FHINK-E0213A07-V1.1-Spec.pdf
[SSD1675]: http://www.solomon-systech.com/en/product/advanced-display/bistable-display-driver-ic/SSD1675/
[SSD1675 datasheet]: https://www.buydisplay.com/download/ic/SSD1675A.pdf
[edunham-talk]: https://youtu.be/uCnnhMleoKA?t=530 [edunham-talk]: https://youtu.be/uCnnhMleoKA?t=530
[edunham]: http://edunham.net/ [edunham]: http://edunham.net/
[embedded-graphics]: https://crates.io/crates/embedded-graphics
[embedded-hal]: https://crates.io/crates/embedded-hal
[Ferris]: http://rustacean.net/
[GPIO]: https://en.wikipedia.org/wiki/General-purpose_input/output
[HINK-E0213A07]: https://www.unisystem-displays.com/en/fileuploader/download/download/?d=0&file=custom%2Fupload%2Ffile%2F6f3084488018ca68c5bf0a26460e7c57%2FHINK-E0213A07-V1.1-Spec.pdf
[hyper]: https://hyper.rs/
[inky]: https://github.com/pimoroni/inky
[IoT]: https://en.m.wikipedia.org/wiki/Internet_of_things
[linux-embedded-hal]: https://crates.io/crates/linux-embedded-hal
[linux.conf.au]: https://2019.linux.conf.au/
[Pimoroni Inky pHAT]: https://shop.pimoroni.com/products/inky-phat
[ProFont font]: https://web.archive.org/web/20180412214402/http://tobiasjung.name/profont/
[profont]: https://crates.io/crates/profont
[Raspberry Pi Zero W]: https://www.raspberrypi.org/products/raspberry-pi-zero-w/
[Raspbian]: https://raspbian.org/
[Read Rust]: https://readrust.net/
[source]: https://github.com/wezm/linux-conf-au-2019-epaper-badge
[SPI]: https://en.wikipedia.org/wiki/Serial_Peripheral_Interface
[ssd1675 crate]: https://crates.io/crates/ssd1675
[SSD1675 datasheet]: https://www.buydisplay.com/download/ic/SSD1675A.pdf
[SSD1675]: http://www.solomon-systech.com/en/product/advanced-display/bistable-display-driver-ic/SSD1675/
[stm32f30x-hal]: https://crates.io/crates/stm32f30x-hal
[systemd unit]: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
[wrk]: https://github.com/wg/wrk

View file

@ -1,9 +1,9 @@
--- ---
title: Rust powered linux.conf.au e-Paper badge title: My Rust Powered linux.conf.au E-Paper Badge
extra: TODO extra: For linux.conf.au 2019 I built a digital conference badge using a Raspberry Pi Zero, tri color e-Paper display and a custom Rust program.
kind: article kind: article
section: technical section: technical
created_at: 2019-01-26 16:17:00.000000000 +10:00 created_at: 2019-01-27 11:00:00.000000000 +11:00
keywords: keywords:
- rust - rust
- linux - linux

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB