To get set up, we will need CircuitPython, a few libraries and the Conference Badge Source Code and fonts downloaded from Github.

Required CircuitPython Libraries

First, make sure you are running the latest version of Adafruit CircuitPython for your board.

Next, you'll need to install the necessary libraries to use the hardware--carefully follow the steps to find and install these libraries from Adafruit's CircuitPython library bundle.  Our introduction guide has a great page on how to install the library bundle for both express and non-express boards.

Since the fonts take up a good deal of space, Adafruit recommends that you manually install only the necessary libraries from the bundle:

  • neopixel
  • adafruit_bitmap_font
  • adafruit_display_shapes
  • adafruit_display_text

Before continuing make sure your board's lib folder or root filesystem have the neopixel, adafruit_bitmap_font, adafruit_display_shapes, and adafruit_display_text files and folders copied over.

Conference Badge Source Code

Next, we'll continue by downloading the Source Code from Github.

The fonts go in a subdirectory of your PyBadge's main CIRCUITPY flash drive named /fonts

Here is the CircuitPython code in its entirety. If you click on Download Project Zip, it will download the fonts used in this tutorial also. 

"""
This is a Conference Badge type Name Tag that is intended to be displayed on
the PyBadge. Feel free to customize it to your heart's content.
"""

import time
from math import sqrt, cos, sin, radians
import board
from micropython import const
import displayio
import digitalio
import neopixel
from gamepadshift import GamePadShift
from adafruit_display_shapes.rect import Rect
from adafruit_display_text.label import Label
from adafruit_bitmap_font import bitmap_font

# Button Constants
BUTTON_LEFT = const(128)
BUTTON_UP = const(64)
BUTTON_DOWN = const(32)
BUTTON_RIGHT = const(16)
BUTTON_SEL = const(8)
BUTTON_START = const(4)
BUTTON_A = const(2)
BUTTON_B = const(1)

# Customizations
HELLO_STRING = "HELLO"
MY_NAME_STRING = "MY NAME IS"
NAME_STRING = "Blinka"
NAME_FONTNAME = "/fonts/Noto-18.bdf"
NEOPIXEL_COUNT = 5
BACKGROUND_COLOR = 0xFF0000
FOREGROUND_COLOR = 0xFFFFFF
BACKGROUND_TEXT_COLOR = 0xFFFFFF
FOREGROUND_TEXT_COLOR = 0x000000

# Default Values
brightness = 0.2
direction = 1
speed = 1

# Define the NeoPixel and Game Pad Objects
neopixels = neopixel.NeoPixel(board.NEOPIXEL, NEOPIXEL_COUNT, brightness=brightness,
                              auto_write=False, pixel_order=neopixel.GRB)

pad = GamePadShift(digitalio.DigitalInOut(board.BUTTON_CLOCK),
                   digitalio.DigitalInOut(board.BUTTON_OUT),
                   digitalio.DigitalInOut(board.BUTTON_LATCH))

# Make the Display Background
splash = displayio.Group()
board.DISPLAY.show(splash)

color_bitmap = displayio.Bitmap(160, 128, 1)
color_palette = displayio.Palette(1)
color_palette[0] = BACKGROUND_COLOR

bg_sprite = displayio.TileGrid(color_bitmap,
                               pixel_shader=color_palette,
                               x=0, y=0)
splash.append(bg_sprite)

# Draw a Foreground Rectangle where the name goes
rect = Rect(0, 50, 160, 70, fill=FOREGROUND_COLOR)
splash.append(rect)

# Load the Hello font
large_font_name = "/fonts/Verdana-Bold-18.bdf"
large_font = bitmap_font.load_font(large_font_name)
large_font.load_glyphs(HELLO_STRING.encode('utf-8'))

# Load the "My Name Is" font
small_font_name = "/fonts/Arial-12.bdf"
small_font = bitmap_font.load_font(small_font_name)
small_font.load_glyphs(MY_NAME_STRING.encode('utf-8'))

# Load the Name font
name_font_name = NAME_FONTNAME
name_font = bitmap_font.load_font(name_font_name)
name_font.load_glyphs(NAME_STRING.encode('utf-8'))

# Setup and Center the Hello Label
hello_label = Label(large_font, text=HELLO_STRING)
(x, y, w, h) = hello_label.bounding_box
hello_label.x = (80 - w // 2)
hello_label.y = 15
hello_label.color = BACKGROUND_TEXT_COLOR
splash.append(hello_label)

# Setup and Center the "My Name Is" Label
mni_label = Label(small_font, text=MY_NAME_STRING)
(x, y, w, h) = mni_label.bounding_box
mni_label.x = (80 - w // 2)
mni_label.y = 35
mni_label.color = BACKGROUND_TEXT_COLOR
splash.append(mni_label)

# Setup and Center the Name Label
name_label = Label(name_font, text=NAME_STRING, line_spacing=0.75)
(x, y, w, h) = name_label.bounding_box
name_label.x = (80 - w // 2)
name_label.y = 85
name_label.color = FOREGROUND_TEXT_COLOR
splash.append(name_label)

# Remap the calculated rotation to 0 - 255
def remap(vector):
    return int(((255 * vector + 85) * 0.75) + 0.5)

# Calculate the Hue rotation starting with Red as 0 degrees
def rotate(degrees):
    cosA = cos(radians(degrees))
    sinA = sin(radians(degrees))
    red = cosA + (1.0 - cosA) / 3.0
    green = 1./3. * (1.0 - cosA) + sqrt(1./3.) * sinA
    blue = 1./3. * (1.0 - cosA) - sqrt(1./3.) * sinA
    return (remap(red), remap(green), remap(blue))

palette = []
pixels = []

# Generate a rainbow palette
for degree in range(0, 360):
    color = rotate(degree)
    palette.append(color[0] << 16 | color[1] << 8 | color[2])

# Create the Pattern
for x in range(0, NEOPIXEL_COUNT):
    pixels.append(x * 360 // NEOPIXEL_COUNT)

# Main Loop
current_buttons = pad.get_pressed()
last_read = 0
while True:
    for color in range(0, 360, speed):
        for index in range(0, NEOPIXEL_COUNT):
            palette_index = pixels[index] + color * direction
            if palette_index >= 360:
                palette_index -= 360
            elif palette_index < 0:
                palette_index += 360
            neopixels[index] = palette[palette_index]
        neopixels.show()
        neopixels.brightness = brightness
        # Reading buttons too fast returns 0
        if (last_read + 0.1) < time.monotonic():
            buttons = pad.get_pressed()
            last_read = time.monotonic()
        if current_buttons != buttons:
            # Respond to the buttons
            if (buttons & BUTTON_RIGHT) > 0:
                direction = -1
            elif (buttons & BUTTON_LEFT) > 0:
                direction = 1
            elif (buttons & BUTTON_UP) > 0 and speed < 10:
                speed += 1
            elif (buttons & BUTTON_DOWN) > 0 and speed > 1:
                speed -= 1
            elif (buttons & BUTTON_A) > 0 and brightness < 0.5:
                brightness += 0.025
            elif (buttons & BUTTON_B) > 0 and brightness > 0.025:
                brightness -= 0.025
            current_buttons = buttons

After copying everything over, your PyBadge should display a Nametag with Blinka on it and the neopixels should animate. In the next few sections, we'll go over the Fonts and how to make changes.

This guide was first published on May 28, 2019. It was last updated on May 28, 2019.

This page (Setup) was last updated on Oct 12, 2021.

Text editor powered by tinymce.