Badger 2040

A nearly-3 inch E-Ink display bolted onto a Raspberry Pi 2040 with 5 buttons, a LED, and 2 MB of RAM, made by Pimoroni. It can run on battery or USB power, and has ports and pads you can attach things to.

Where to get it

Alternatives

Useful Docs

Cases

Command line access

Use MicroPython's mpremote: https://pypi.org/project/mpremote/

  • Note that you can't use this and Thonny at the same time.
  • There doesn't seem to be a way to mount a folder on the Badger and edit/copy things on it, but you can do the reverse. So the workflow is going to have to be:
    • Write code
    • Run build script
      • Script copies files to Badger and resets it, then opens console
snippet.bash
# get a console on the device
mpremote
 
# list files at the root folder
mpremote ls

TODO:

  • [ ] Use mpremote to construct a Makefile or Rakefile deploy toolchain to the Badger.

Using Thonny

Ubuntu Setup

I used pipx to install Thonny locally, and I had to add my user to the dialout group since Badger 2040 was mounting on /dev/ttyACM.

First steps

Turn off the simplified interface. You can barely do anything in this interface beyond the basics.

File Management

There's no rename on the Badger 2040. Name your file correctly, go into the directory in Thonny's file browser (don't just flip it open), and Upload the file from your computer.

While Badger 2040 is plugged in

The dev cycle I've been using is:

  • Reset connection to Badger 2040 using Thonny Stop/Restart.
  • In the console, run import launcher.
  • Do stuff until it crashes. You can get print statements and exceptions in the console.

If you're not using the default launcher, use import <filename minus .py>.

Targeting a single file

This seems to be a smoother approach:

snippet.python
import sys
del sys.modules['<filename minus .py>']
import <filename minus .py>

This means you can skip import launcher and target just your program.

JPEG

Badger 2040 has its own version of JPEGDEC for decoding JPEGs on Pi 2040 devices:

Decoding

Decoding goes directly to the display:

snippet.python
import jpegdec
import badger2040
 
display = badger2040.Badger2040()
jpeg = jpegdec.JPEG(display.display)
 
jpeg.open_file("/my/image.jpg")
jpeg.decode(x_target, y_target)

Saving compatible JPEG graphics

GIMP on Linux by default will not make graphics the JPEG parser MicroPython on the badge likes. Run them through ImageMagick, then upload them to the badge. No other conversion needed, just in and out:

convert image-orig.jpg image.jpg

Activity LED

All the docs say you can change the Activity LED's state but neither the REPL nor the actual code that ships with the Badger 2040 seem to be able to do that:

BadgerOS

You're very likely going to be modifying the files in examples to start. This means you'll be using the Launcher that comes with the Badger 2040 firmware.

Data Formats

You get JSON reading, no YAML.

JSON

You can't use the streaming JSON interface since opened files in MicroPython aren't streamable. Read the file into memory, then parse it:

snippet.python
with open("my_file.json", "r") as file:
  data = json.loads(file.read())

Where is "Push A and C to Exit Launcher" controlled?

This is in badger_os.py (https://github.com/pimoroni/badger2040/blob/main/firmware/PIMORONI_BADGER2040/lib/badger_os.py#L112-L142):

Running a timer or a clock

Extracted from clock.py:

snippet.python
import time
import machine
import badger2040
 
try:
    badger2040.pcf_to_pico_rtc()
except RuntimeError:
    pass
 
rtc = machine.RTC()
 
# set the clock to a reasonable default value
year, month, day, wd, hour, minute, second, _ = rtc.datetime()
if (year, month, day) == (2021, 1, 1):
    rtc.datetime((2022, 2, 28, 0, 12, 0, 0, 0))
 
while True:
    # get the clock value
    year, month, day, wd, hour, minute, second, _ = rtc.datetime()
 
    # do stuff here
    # avoid updating the display unless you absolutely have to!
    # even fast updates are costly
 
    time.sleep(0.01)