From Badge team
Jump to navigation Jump to search

I. Welcome to Disobey badge![edit]

This documentation is the official description of the avaialble API, as well as tips for developing your own app.

Disobey badge runs MicroPython on ESP32, in version derrived from the one used at SHA-2017. This means that if you find this information lacking, you can also try to crawl the badge software documentation from SHA2017. Note that Disobey and SHA-2017 badges are not fully compatible hardware-wise.

If you want to see the source code or help develop this MicroPython version further, you can find it here: https://github.com/badgeteam/ESP32-Firmware

Badge hardware functionality[edit]

  • 6 RGB leds
  • 6 touch buttons
  • LCD screen with backlight
  • piezoelectric buzzer
  • WiFi (2.4 GHz)
  • I2C bus
  • serial via USB

You can use the above functionalities to write applications. There is an application distributing server, Hatchery, set up for this event. You can develop apps via MicroPython command line, and once your application is ready, you can upload it to Hatchery as an egg, and every badge will be able to download it and run!

II. Programming API[edit]

 import badge

Majority of the badge's functionality is available via the badge module. Import it, and you can use the following hardware elements.


To turn leds on you need to give it led number and 3 numbers 0-255, that describe the RGB color it will be turned on to.

 badge.led(LED_NR, R, G, B)

and to turn a led off, put 0 for all RGB's:

 badge.led(2, 0, 0, 0)

Here is a mapping of LED numbers to numbers on the back of the badge:

 D7 = 0
 D6 = 1
 D5 = 2
 D4 = 3
 D3 = 4
 D1 = 5


The recommended way to use buttons is to connect them with uGFX to functions that will get called on events. Not that the function will be called on both pressing and releasing. When button is pressed, it's status variable will be True, when button is released it will change to False. See code example:

 def function(button_status):
     print("Button pressed.", button_status)
 ugfx.input_attach(ugfx.BTN_START, button_status)

The accessible buttons have names:


all accessible via ugfx class, and can be attached like this:

 ugfx.input_attach(ugfx.JOY_UP, up)
 ugfx.input_attach(ugfx.JOY_DOWN, down)
 ugfx.input_attach(ugfx.JOY_LEFT, left)
 ugfx.input_attach(ugfx.JOY_RIGHT, right)
 ugfx.input_attach(ugfx.BTN_B, b)
 ugfx.input_attach(ugfx.BTN_START, start)

Note that the badge does not have button A, SELECT, or FLASH.


The badge softawre offers uGFX library for writing and drawing to the screen as well as button events. It is the recommended way of doing there things. Alternatively you can also access raw button event queue, and draw your own framebuffer via MicroPython's graphic handling functions. Note that it's better to use one method, as you are bound to encounter issues if you mix them up.


The uGFX offers automagical font handling for pretty text display. The fonts uploaded to the badge are:

 ['pixelade13', 'weather42', 'DejaVuSans20', 'Roboto_Regular22',
 'Roboto_Regular18', 'Roboto_Regular12', 'Roboto_BlackItalic24', 
 'Roboto_Black22', 'PermanentMarker36', 'PermanentMarker22']

Fonts can be also listed on the badge with ugfx.fonts_list() To use other fonts, you need to get them converted into uGFX-compatible format. Then you can add it to the badge via uploading to the Hatchery in an egg.

To print characters and strings on the badge, you should use ugfx functions:

 ugfx.char(x, y, char, font, colour)
 ugfx.string(x, y, char, font, colour)

Since the badge's screen is small, there's an auto-scrolling text function:

 easydraw.msg("This is a test", "Title", True)


It is possible to draw on the screen using uGFX's functions. For example:

 ugfx.pixel(x, y, colour)
 ugfx.line(xstart, ystart, xend, yend, colour)
 ugfx.box(x, y, length, height, colour)
 ugfx.circle(x, y, r, colour)

For more you can consult the SHA-2017 documentation at https://wiki.sha2017.org/w/Projects:Badge/MicroPython Remember to flush the screen with:



The badge can only display PNG files. The file needs to be saved as a byte array, or attached as a png to the egg you upload to Disobey Hatchery. Once you get the file on the badge, to display it call the following function:

 badge.png(x, y, filename)
 badge.png(x, y, framebuffer_object)

Where x and y are the position of top left corner of the image should be on the screen. For top left screen corner use x=0 and y=0. Other image formats do not work well, so please convert your images to png format.


Screen can be rotated. The default is to have it print upside-down, because it is mounted upside down. Note that writing to the screen without that flipping will be faster. Remember to flush the screen after changing the orientation.


where True means framebuffer written to the screen will be rotated, and False that it will not be rotated.


Screen has a backlight, whose brightness you can adjust:


where 0 is off, and 255 is brightest.


All badges run on two AAA alkaline 1.5V batteries. Internally their voltage is stepped up to make sure badge makes use of all the power in them. You can guess how much power is left in the batteries, but looking up the voltage . voltage = badge.battery_volt_sense()

If you find the badge power draining too fast, you can use the following function to turn off all power-hungry elements on the badge:


which will turn off all leds, buzzer, and screen backlight (SAMD peripherals).


Badge's piezobuzzer, placed on one eye, can be used to produce sound with following commands: badge.buzzer(frequency, duration) badge.buzzer(3000, 5) Note that the data transfer is limited to 1-2bps, and the buzzer can emit sound with frequency in range of 2kHz - 22.5kHz.


Badge offers a non-volatile memory for storing strings, 8bit and 16bit numbers. This is meant for storing small setting values (not long conriguration files). Once written it will persist through power loss and OTA software update. Value are located in the memory in groups, so to set and retrieve you need to provide a group name, and the variable name. If on setting group and/or variable do not exist, they will be created.

 badge.nvs_set_str(group, item, value)

Available are storage value types as follow:

 uint_8 = badge.nvs_get_u8()
 uint_16 = badge.nvs_get_u16()
 string = badge.nvs_get_str()

with matching set functions for each.

Every badge has an owner setting already existing. You can test this function by setting it with your own nick!

 string = badge.nvs_get_str('badge', 'owner', 'default')
 badge.nvs_set_str('badge', 'owner', 'Jukka')

When you fetch a setting, you can provide a "default" value, that will be returned if no other value has been found inside the memory.


Badge has a WiFi chip, but it is supposed to work in bursts, not to consume the batteries too fast, or crowd the network. Badge is pre-configured to use the event's wireless network, but that can be changed via software.

There are two ways to use the WiFi: the wifi module, and the easywifi module. Both require enabling/initing, and can be called to connect to either default, or specific wireless 2.4GHz network. Note that those modules just manage connection, not sending or receiving data.

Recommended way is to go with easywifi:

 import easywifi
 while not easywifi.status():

now it should be connected and you can use it. When you're done, remember to disable wifi with:


Using the wifi module:

 import wifi
 while not wifi.sta_if.connect(ssid, password):

now it should be connected and you can use it. No function in this module to disable wifi.

Sending data via WiFi can be done with the urequests module:

 import urequests
 data = urequests.get(url)

III. More on available functions:[edit]

Touch debugging[edit]


returns raw bit of the button being pressed


returns raw state of the badge also in a bit format, but needs a bitmap to decode Note that this functions will check the button event queue, which gets stacked with button-press events. However if you use also uGFX for handling button events, that event queue will be flushed by uGFX when it reads input queue.

Exit app[edit]

When you create an application, you should include an exit button:

 improt appglue


Badge uses official MicroPython i2c documented at http://docs.micropython.org/en/latest/pyboard/library/machine.I2C.html and it can be used to communicate with SAMD and the display directly. Address of SAMD is 0x30, and of Display is 0x38 and 0x39. There's a simplified set of functions provided via the badge object:


otherwise you can import

 from machine import I2C, Pin
 i2c = I2C(scl=Pin(22), sda=Pin(23))
 [] = i2c.scan()
 i2c.readfrom(48, 1) # Read one byte from SAMD


It is possible to run the application as a service:

 import virtualtimers
 def function():
   print("Hello World")
   return 1000
 virtualtimers.add(function, 500)