From Badge team
Revision as of 08:58, 15 April 2020 by Karin (talk | contribs) (→‎Development option 2: offline coding via USB)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search


Welcome, and congratulations with your brand new CampZone 2019 "I-Pane" event badge! This year's badge features an eye-killing RGB LED matrix, an extended 8MB flash ESP32 WiFi/BL microcontroller, and the wonderful multi-badge firmware platform by

You can install apps from the (of course fully free) app store, and even write your own apps easily in Python that others can then install too!

CZ19 badge in full nyan cat glory, at Revspace.

The badge and it's firmware are located at:

Using your badge after CampZone[edit]

Getting started[edit]

Plug in your battery. The + and - are indicated on the circuit board. The positive terminal should point towards the USB connector. The badge has a protection circuit against reversing the battery, but it's best not to need it.

When you power the badge for the first time, it will first show a one-time intro screen. Afterwards, it will try to connect to WiFi. If connecting is successful, it will force a day-0 OTA update to get you the latest firmware. Otherwise, it will boot into a minimal firmware that allows you to setup WiFi and force OTA manually (and play snake!).

If the bottom entry in the launcher is 'Force OTA update', you're stuck in the initial firmware because the update failed. Keep running 'Force OTA update' until the update succeeds. Then, this entry will be replaced with the app 'Firmware update'.

After CampZone, you will need to update the WiFi settings to make the badge connect to your home network. This can be done with the "Set up WiFi" app on the home screen. If your badge still has the original firmware on it, it is easiest if you update it to the latest version first:

  • Create a mobile WiFi hotspot with your phone, with SSID 'CampZone-IoT', and password also 'CampZone-IoT'. Run the Firmware Update app, and the badge should connect to your network and download the latest firmware.

On a recent firmware, you have a few options for configuring WiFi:

  • Manually enter the login information through the Set up WiFi app. This will take a while.
  • Connect your badge to your computer via USB (see section "Development option 2: offline coding via USB"), and in the USB menu select Settings > Configure WiFi.

The battery should be protected by an undervoltage protection, shutting down the badge in case of an empty battery. Possibly this implementation needs some TLC. Meanwhile do be aware that, when blue colors start to fade, the battery probably should be recharged (plug in the micro-usb)


The badge boots into a launcher application, from which you can run all the apps you've installed.

You are able to remove apps which you install through the app store. System apps are non-removable. Source of these system apps can be found on the GitHub page: [1]

Brightness control[edit]

The left and right buttons in the launcher app control the badge's system brightness, which is persistent across reboots. You can save your eyes and also improve your charging time by lowering the brightness.

Writing your own apps[edit]


This section introduces both MicroPython and the development process for your CampZone 2019 badge. If you are an absolute beginner we have also produced a pair of step-by-step tutorials that cover the basics of writing a "Hello World" app and loading it onto a badge.

There are two different ways to write apps, which are explained in the next two sections.

Development option 1: online coding in your browser[edit]

The 'hatchery' website is the repository for all compatible badges and their apps. You can easily write your micropython code there online and publish it so badges have access to it. Be sure to select the proper compatibility when creating your project so it will appear on the badges in the 'installer'.

Visit the Hatchery on, sign up for an account and have a look around. You can look into all projects there and borrow code from them. Create an app of your own with the "Add" button in the top right!

Development option 2: offline coding via USB[edit]

Instead of working remotely via the Hatchery editor in your browser, you can also develop directly on your badge. This also allows you to tinker with your badge's internals. Detailed instructions per OS can be found below. Connect your badge to a computer using a Micro-USB cable, and connect over serial, 115200 baud. You should see a menu appear with various options. Select the Python Shell for now. You can type live python code here.


  • Install the CH340 driver mentioned here.
  • Check the address of your usb device by typing `ls /dev/` in your terminal, you'll get a list, one of the entries being your badge. It is probably something like `cu.wchusbserial1410`. To check which address belongs to your device, try disconnecting the badge and see which address is missing from the list after you run `ls /dev/` again.
  • Open a serial connection with from Terminal like this: `screen /dev/cu.wchusbserial1410 115200`, replacing the address with the address of your device.

(You can exit with ctrl+a followed by k)


  • Open a serial connection with from Terminal like this: `screen /dev/ttyUSB0 115200`.

(You can exit with ctrl+a followed by k)

For Windows you should be able to connect to the badge by using Putty:

  • Install CH340 driver.
  • Download a terminal emulator, for example PuTTY.
  • Lookup the badge's com-port number in device manager after connecting the badge over USB.
  • Connect to the serial port and set baud-rate to 115200.

Paste mode[edit]

Hit Control-E for paste mode, paste in your code, hit Control-D to exit paste mode.


Most Python builtins work on the badge, so things like file reading/writing works as you would normally use in Python.


Button clicks can be subscribed to with callbacks like this:

 import buttons, defines
 def my_callback(button_is_down):
   if button_is_down:
     # Do stuff
 buttons.register(defines.BTN_A, my_callback)

Valid buttons are BTN_A, BTN_B, BTN_UP, BTN_DOWN, BTN_LEFT, and BTN_RIGHT.

WiFi and web requests[edit]

The easiest and prettiest way to connect to WiFi is to run:

 import uinterface

This function draws animated connection icons to the display, and returns whether connecting was successful..

Once you have a WiFi connection, you can fetch the contents of a given URL with:

 import urequests
 result = urequests.get('')

If the page you fetched is in JSON format, you can parse it using:

 parsed_object = result.json()


Most current CZ apps still use the rgb module. For new code we recommend the more generic display API, see . You may or may not need to first disable the rgb module with `rgb.disablecomp()`.

All display features can be accessed through the rgb module.

First make the module available by adding to the top of your script:

 import rgb

After this, you will have access to the following functions:


Clears all the render tasks. Keeps the background .

 rgb.background((r, g, b))

(r, g, b) – RGB values for color. Each value should be between 0 and 255.

Sets the background color.


Gets the display brightness.


Sets the brightness to the specified value. Brightness ranges from 1 to 30.


Sets the framerate to the specified value. Framerate ranges from 1 to 30fps.

 rgb.pixel((r, g, b), (x, y))

(r, g, b) – RGB values for color. Each value should be between 0 and 255.

(x,y) – Coordinate of the display. 0,0 is in top left corner.

Places a pixel with the color rgb at x,y on the display.

 rgb.text(text, (r,g,b),  (x,y))

text – String to display on the display. Most ascii characters are supported.

(r, g, b) – RGB values for color. Each value should be between 0 and 255.

(x,y) – (optional, defaults to center left) Coordinate of the display. 0,0 is in top left corner.

Places the specified text on the display where the top left corner of the text block is at x,y.

 rgb.scrolltext(text, (r,g,b),  (x,y), width)

text – String to display on the display. Most ascii characters are supported.

(r, g, b) – RGB values for color. Each value should be between 0 and 255.

(x,y) – (optional, defaults to center left) Coordinate of the display. 0,0 is in top left corner.

width – (optional, defaults to whole screen) The width of the box in which to scroll the text.

Places the specified text on the display where the top left corner of the text block is at x,y. This text will scroll across the display. Specify the width if it shouldnt scroll across the whole screen.

 rgb.image(data, (x,y), (w,h)

data – image data in a list with the format 0xrrggbbaa (red, green, blue, alpha).

(x,y) – x,y coordinate of display where the top left corner of the image should be.

(w,h) – width and height of the image.

Renders an image on the display at the specified coordinate.


 rgb.image([0x00FF00FF, 0x0000FFFF, 0xFF0000FF], (0,0), (3,1))

 rgb.gif(data, (x,y), (w,h), frames)

data – image data in a list with the format 0xrrggbbaa (red, green, blue, alpha).

(x,y) – x,y coordinate of display where the top left corner of the image should be.

(w,h) – width and height of the image.

frames – number of frames in the gif.

Renders animated image on the display. The speed of the animation is locked to the framerate.


 rgb.gif([0x00FF00FF,0x00FF00FF,0x00FF00FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF], (0,0), (3,1), 2)


Change the font. Set to rgb.FONT_7x5 for the 7x5 monospace font and rgb.FONT_6x3 for 6x3 proportional font.


Gets the width of the supplied text in pixels, given the current font.


If the following commands dont provide a low enough level of access to the display. It is possible to disable the render engine and write directly to the framebuffer from python.


Disable the compositor. The compositor renders the text/images/etc to the framebuffer.


Enable the compositor.


data – frame data in a list with the format 0x00rrggbb.

Writes directly to the framebuffer of the display. Disable the compositor before doing this else it gets overwritten

File system and persistent data[edit]

Using the normal 'open()' function, you can read from and write to files on the badge's FAT filesystem.

The filesystem structure is as follows: /apps -> user-installed app store apps /cache -> temporary files used for caching data /lib -> reserved /config -> reserved

Additionally, you can store short strings and (integer) numbers like this:

 import machine
 machine.nvs_setstr('my_namespace', 'my_keyname', 'someStringValue')
 data = machine.nvs_getstr('my_namespace', 'my_keyname')
 machine.nvs_setint('my_namespace', 'my_keyname', 1337)
 data = machine.nvs_getint('my_namespace', 'my_keyname')

WiFi Settings[edit]

The badge is preconfigured for the Campzone WiFi, SSID 'CampZone-IoT' Pass 'CampZone-IoT'. If you want to use the badge at home, do the OverTheAir Update on the campsite so the WiFi settings app works without bugs ;)

To configure from the terminal, open a Serial terminal (115200) and choose 'python shell'.

import machine
machine.nvs_setstr("system", "wifi.ssid", "YOUR SSID HERE")
machine.nvs_setstr("system", "wifi.password", "YOUR PASSWORD HERE")

If you use a SSID without a password, then blank the wifi password setting:

import machine
machine.nvs_setstr("system", "wifi.password", "")

Reboot and it should 'just work' (if you have done the OTA). Else make an accesspoint with the CampZone-IoT as SSID and Password, do the OTA and THEN use your badge properly.

Hardware mods[edit]

Capacitor for operation without battery[edit]

Without battery, powered just by USB, the badge only work when the brightness is set to a low value. The badge is initially configured with high brightness.

In order to use the I-Pane badge at high brightness without the battery on just USB, you can solder in the capacitor that is included in your bag (470 Uf). Please note the capacitor is polarized, the negative terminal (short wire, white marking on capacitor) should point towards the Campzone/Deloitte logo.

  • Before you begin, unplug USB cable and remove battery.
  • Bend and cut the leads and solder in place.

IMG 3886.jpeg IMG 3887.jpeg

Ultra bright LEDs[edit]

Replace 6 resistors and burn your eyes even further. More details soon!

Tips & Tricks[edit]

App Store won't load[edit]

Cause: Possible corrupt App Store cache

Solution: force refresh cache

Open a python shell (see chapter 'coding via USB') and execute the following:

import uinterface, woezel, machine
machine.nvs_setint('system', 'lastUpdate', 0)
## Check if return is True!!


A diffuser for the CZ19 badge, that turns round pixels into pretty square ones.

You can 3d print your own diffuser that turns the round pixels into large and pretty square ones. Several diffuser designs were made, and are accessible on Thingiverse:

Power Switch[edit]

A power switch for the CZ19 Badge

Another mod is adding a power switch to your CZ19 badge. Details on the easy 3D print and installation can be found on Thingiverse:

The Coin[edit]

The coin used to acquire the campzone 2019 badge is also the pcb for an acceleratometer/gyro and temp sensor. For this the common MPU-6050 is used. If you were unable to solder said coin during Campzone the following parts are necessary:

  • 1x MPU-6050
  • 1x 2.2nF 0603 capacitor (C1)
  • 2x 100nf 0603 capacitor (C2 & C3)
  • 1x 2x3 pin header

A big warning should be give when trying to solder this PCB. Soldering QFN is very difficult and will require the use of a hot air station. Try on your own risk

When the text is oriented horizontally and upright pin 1 of the MPU can be found in the top left corner. This is also where the silkscreen slightly differs.

Schematic/layout can be found here


This badge was only possible because of the help of wonderful people. Thanks to:

  • for awesome base firmware
  • Renze specifically for very nice collaboration on the freshly written new base
  • Sebastius for being an enormous help with organising, promoting, packaging, and for helping staying sane
  • Anne Jan for help with the hatchery integration
  • The HackZone badge team
  • Joris specifically for immediately jumping onboard upon our cry for help with the HUB75 led driver
  • All the badge packaging sweatshop volunteers
  • Revspace for being a wonderful host during the sweatshops
  • Deloitte, Espressif, and AllNet for believing in the badge's beauty and coming up with the huge sponsoring we needed

Credits for the nyan cat animation go to Bertrik Sikken, and was based on the Revspace LED banner animation collection.