
The Raspberry Pico Badger is a consumer product by the Raspberry Pi company Pimorino. Advertised as a portable badge with a 2.9 inch e-ink display and a Pico W, its a portable, programmable microcomputer. This article investigates this unique product from its hardware side as well as the software, apptly named Badger OS.
The technical context of this article isMicroPython v1.21
andBadger OS v0.04
. All examples should work with newer releases too.
This article originally appeared at my blogadmantium.com.
Raspberry Pico Badger
The Pico Badger consumer product, advertised and offered for sale onpimoroni.com is a complete portable mini computer with these components:
- 2.9inch e-ink display with 296x128 pixels
- 5 onboard buttons
- JST-PH battery connector (e.g. for LiPo, max 5.5V)
- Qwiic/STEMMA QT connector
- Raspberry Pico W (133Mhz Dual Arm Cortex M0+, 264kB SRAM, 2MB Flash RAM, BLE and WiFi)
All components are soldered, the board is robust and a decent amount of varnish protects all surfaces. It can be powered with the battery connector, or the Micro-USB port of the Raspberry Pico W.
This is the frontside:
And this is the backside:
Badger OS
The Pico Badger comes with a preinstalled software called Bader OS. This software is completely written in Micropython, and its code can be accessed ongithub.com. When powered up, it boots into a main menu (or the last screen that was shown). By simultaneously pressing the buttons A and C, the main menu is shown, and the following applications are accessible:
- Badge: Show a customizable badge with different text fields and a rendered image
- Clock: A real-time clock that synchronizes via Wi-Fi
- eBook: A full-fledge eBook reader with a preinstalled project Gutenberg version of "The Wind in the Willows"
- Fonts: Showcasing how different fonts can be rendered on the screen
- Help: Manual showing how to navigate via the onboard buttons
- Image: Renders a provided image file
- Info: System and hardware information
- List: A todo app displaying items and enabling to mark them as done
- Net Info: Show connectivity information about the Wi-Fi connection
- News: An RSS reader showing headlines from BBC
- QRGen: A QR code generator
- Weather: Using your Wi-Fi hotspot geo information, show the current temperature, wind and rain status
Configuring Badger OS
All Badger OS functions and configuration are stored as Python and configuration files on the board itself. Like a normal Raspberry Pico, you need to keep pressing the bootsel button, then connect the device to a computer, and its internal file system becomes mountable as a USB drive.
The recommended way to program MicroPython on the Raspberry Pico is to use theThonny IDE. Accessing the Badger reveals the following file structure:
.├── WIFI_CONFIG.py├── badges│ ├── badge.jpg│ └── badge.txt├── books│ └── 289-0-wind-in-the-willows-abridged.txt├── checklist.txt├── examples│ ├── badge.py│ ├── clock.py│ ├── ebook.py│ ├── fonts.py│ ├── help.py│ ├── icon-badge.jpg│ ├── icon-clock.jpg│ ├── icon-ebook.jpg│ ├── icon-fonts.jpg│ ├── icon-help.jpg│ ├── icon-image.jpg│ ├── icon-info.jpg│ ├── icon-list.jpg│ ├── icon-net-info.jpg│ ├── icon-news.jpg│ ├── icon-qrgen.jpg│ ├── icon-weather.jpg│ ├── image.py│ ├── info.py│ ├── list.py│ ├── net_info.py│ ├── news.py│ ├── qrgen.py│ └── weather.py├── icon-cloud.jpg├── icon-rain.jpg├── icon-snow.jpg├── icon-storm.jpg├── icon-sun.jpg├── icons├── images│ └── badgerpunk.jpg├── launcher.py├── main.py└── state ├── ebook.json ├── image.json ├── launcher.json ├── list.json └── news.json6 directories, 42 files
The first thing that you will want to do is to configure access to a Wi-Fi hotspot:
- Open the file
WIFI_CONFIG.py
- Enter the Wi-Fi Credentials
- Reboot and try the builtin RSS reader
If you see the log messageConnecting...
, followed byConnected!
, the Badger is ready to access any website and other internet resources.
Exploring Badger OS: Main Program
Note: all of the following source code stems from theGithub repository pimoroni/badger2040
Lets investigate the Badger OSmain.py
program to understand how to add a new application.
First, several modules are imported, and global variables defined, for example for the display.
importgcimportosimporttimeimportmathimportbadger2040importbadger_osimportjpegdecAPP_DIR="/examples"FONT_SIZE=2display=badger2040.Badger2040()display.set_font("bitmap8")display.led(128)jpeg=jpegdec.JPEG(display.display)
Next, the available applications are determined by crawling the./examples
directory for every Python file.
examples=[x[:-3]forxinos.listdir("/examples")ifx.endswith(".py")]
Two methods for drawing the on-screen menu bars follow:
defdraw_disk_usage(x):defrender():display.set_pen(15)display.clear()display.set_pen(0)max_icons=min(3,len(examples[(state["page"]*3):]))...
Halfway through the example, we find the method that actually starts an app.
deflaunch_example(index):wait_for_user_to_release_buttons()file=examples[(state["page"]*3)+index]file=f"{APP_DIR}/{file}"forkinlocals().keys():ifknotin("gc","file","badger_os"):dellocals()[k]gc.collect()badger_os.launch(file)
Lets note this down:badger_os.launch(file)
. Continuing the main program to its end, several more methods define how to interpret pressed buttons:
defbutton(pin):globalchangedchanged=Trueifpin==badger2040.BUTTON_A:launch_example(0)ifpin==badger2040.BUTTON_B:launch_example(1)ifpin==badger2040.BUTTON_C:launch_example(2)ifpin==badger2040.BUTTON_UP:ifstate["page"]>0:state["page"]-=1render()ifpin==badger2040.BUTTON_DOWN:ifstate["page"]<MAX_PAGE-1:state["page"]+=1render()
And finally, a continuous runningwhile
loop that constantly monitors for pressed buttons:
whileTrue:# Sometimes a button press or hold will keep the system# powered *through* HALT, so latch the power back on.display.keepalive()ifdisplay.pressed(badger2040.BUTTON_A):button(badger2040.BUTTON_A)ifdisplay.pressed(badger2040.BUTTON_B):button(badger2040.BUTTON_B)ifdisplay.pressed(badger2040.BUTTON_C):button(badger2040.BUTTON_C)ifdisplay.pressed(badger2040.BUTTON_UP):button(badger2040.BUTTON_UP)ifdisplay.pressed(badger2040.BUTTON_DOWN):button(badger2040.BUTTON_DOWN)ifchanged:badger_os.state_save("launcher",state)changed=Falsedisplay.halt()
Now, lets check how an app is started, and how an app file actually looks like.
Exploring Badger OS: Badger OS Module an App File
Interestingly, the importedbadger_os
module is not part of the device files, but included in the Micropython distribution that is flashed onto the device. This module, and thebadger2040
andnetwork_manager.py
can be found in projects GitHub repository at pathmain/firmware/PIMORONI_BADGER2040W/lib.
The aforementionedbadger_os.launch()
function is this:
# Source: https://github.com/pimoroni/badger2040/blob/main/firmware/PIMORONI_BADGER2040W/lib/badger_os.pydeflaunch(file):state_set_running(file)gc.collect()button_a=machine.Pin(badger2040.BUTTON_A,machine.Pin.IN,machine.Pin.PULL_DOWN)button_c=machine.Pin(badger2040.BUTTON_C,machine.Pin.IN,machine.Pin.PULL_DOWN)defquit_to_launcher(pin):ifbutton_a.value()andbutton_c.value():machine.reset()button_a.irq(trigger=machine.Pin.IRQ_RISING,handler=quit_to_launcher)button_c.irq(trigger=machine.Pin.IRQ_RISING,handler=quit_to_launcher)try:__import__(file)exceptImportError:# If the app doesn't exist, notify the userwarning(None,f"Could not launch:{file}")time.sleep(4.0)exceptExceptionase:# If the app throws an error, catch it and display!print(e)warning(None,str(e))time.sleep(4.0)# If the app exits or errors, do not relaunch!state_clear_running()machine.reset()# Exit back to launcher
As you see, it will run a garbage collection routing to cleanup RAM resources, then define buttons, and simplyimports
the launched app file.
So, what inside this? Lets check the source code of theinfo
page.
importbadger2040frombadger2040importWIDTHTEXT_SIZE=1LINE_HEIGHT=15display=badger2040.Badger2040()display.led(128)# Clear to whitedisplay.set_pen(15)display.clear()display.set_font("bitmap8")display.set_pen(0)display.rectangle(0,0,WIDTH,16)display.set_pen(15)display.text("badgerOS",3,4,WIDTH,1)display.text("info",WIDTH-display.measure_text("help",0.4)-4,4,WIDTH,1)display.set_pen(0)y=16+int(LINE_HEIGHT/2)display.text("Made by Pimoroni, powered by MicroPython",5,y,WIDTH,TEXT_SIZE)y+=LINE_HEIGHTdisplay.text("Dual-core RP2040, 133MHz, 264KB RAM",5,y,WIDTH,TEXT_SIZE)y+=LINE_HEIGHTdisplay.text("2MB Flash (1MB OS, 1MB Storage)",5,y,WIDTH,TEXT_SIZE)y+=LINE_HEIGHTdisplay.text("296x128 pixel Black/White e-Ink",5,y,WIDTH,TEXT_SIZE)y+=LINE_HEIGHTy+=LINE_HEIGHTdisplay.text("For more info:",5,y,WIDTH,TEXT_SIZE)y+=LINE_HEIGHTdisplay.text("https://pimoroni.com/badger2040",5,y,WIDTH,TEXT_SIZE)display.update()# Call halt in a loop, on battery this switches off power.# On USB, the app will exit when A+C is pressed because the launcher picks that up.whileTrue:display.keepalive()display.halt()
This source code contains instructions how to draw shapes and texts on the screen. It starts by importing therp20240
library, then activates the onboard led withdisplay.led()
, and clears the screen withdisplay.clear()
. This is followed by a series of statements usingdisplay.pen()
, a method that defines a new origin, anddisplay.rectangle()
as well asdisplay.text()
to fill the screen. Finally, the screen is drawn on withdisplay.update()
and kept in this state forever withdisplay.update()
. Since this app is purely static, no additional code regarding button interactions is defined.
So, in essence an app files accesses help classes fromrp2040
to render text on the screen and, if required, define the behavior of the onboard buttons.
Other Use Cases
While Badger OS is the official MicroPython based library, it is not the only option you have. To give you some ideas what else can be accomplished:
- You can install a custom port ofCircuitPython
- TheBadOS project is a custom OS with Circuit Python, its GitHub repository shows how to develop different kind of apps too
- There is a programming course how to create aTic-Tac-Toe computer gameshowing the same capabilities as the official software
Conclusion
The Badger Pico W is a unique product. With its 2.9 inch e-ink display and access to Wi-Fi and Bluetooth, you can program stateless application that remain shown even when no power is provided. The aptly named Badger OS is a complete open-source MicroPython project that shows examples for all necessary interactions: Navigating menus by pressing a button, drawing text and images, connect to Wi-Fi, make HTTP request, parse the results and show them. You just need to add portable batteries and have a credit-card sized wearable computer. This board can be used for many projects, for example to build a small e-book reader, a portable RSS reader, a badge.
This article started to explore the Badger OS source code, which is written entirely in MicroPython. You learned that the programs main method imports required libraries, setups method for handling the buttons, defines a state and then display all installed apps. And these apps are single MicroPython files as well that access the builtin libraryrp2040
to draw text and shapes on the screen as well as to define button behavior.
Following this understanding, the next article will investigate how to program a custom app.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse