Raspberry Pi Pico
Unicorn HAT
The Unicorn HAT is a Raspberry Pi accessory made by the UK electronics company, Pimoroni. It has 64 WS2812 (Neopixel RGB) LEDs arranged in an 8x8 grid.
In this photograph, I have the Unicorn HAT connected to the Pico using a Waveshare Pico to HAT board.

Since the LEDs are Neopixels, there is a CircuitPython library that makes it easy to drive the LEDs. On the Unicorn HAT, the pixels are connected down,up,down,... in columns, making it a little awkward when you want to work with grid coordinates. I added a subroutine to do that. The other thing I wanted to do was to have text scrolling across the matrix.
You need a library for this project - get the latest .mpy one from here,
I started by taking the font I have used in various projects and making a separate file for it. I saved this as font.py. I can add other fonts to this file and import them when I need them.
font7x5 = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x5f\x00\x00\x00\x07\x00\x07\x00\x14\x7f\x14'
b'\x7f\x14\x24\x2a\x7f\x2a\x12\x23\x13\x08\x64\x62\x36\x49\x55\x22\x50\x00'
b'\x05\x03\x00\x00\x00\x1c\x22\x41\x00\x00\x41\x22\x1c\x00\x14\x08\x3e\x08'
b'\x14\x08\x08\x3e\x08\x08\x00\x50\x30\x00\x00\x08\x08\x08\x08\x08\x00\x60'
b'\x60\x00\x00\x20\x10\x08\x04\x02\x3e\x51\x49\x45\x3e\x00\x42\x7f\x40\x00'
b'\x42\x61\x51\x49\x46\x21\x41\x45\x4b\x31\x18\x14\x12\x7f\x10\x27\x45\x45'
b'\x45\x39\x3c\x4a\x49\x49\x30\x01\x71\x09\x05\x03\x36\x49\x49\x49\x36\x06'
b'\x49\x49\x29\x1e\x00\x36\x36\x00\x00\x00\x56\x36\x00\x00\x08\x14\x22\x41'
b'\x00\x14\x14\x14\x14\x14\x00\x41\x22\x14\x08\x02\x01\x51\x09\x06\x32\x49'
b'\x79\x41\x3e\x7e\x11\x11\x11\x7e\x7f\x49\x49\x49\x36\x3e\x41\x41\x41\x22'
b'\x7f\x41\x41\x22\x1c\x7f\x49\x49\x49\x41\x7f\x09\x09\x09\x01\x3e\x41\x49'
b'\x49\x7a\x7f\x08\x08\x08\x7f\x00\x41\x7f\x41\x00\x20\x40\x41\x3f\x01\x7f'
b'\x08\x14\x22\x41\x7f\x40\x40\x40\x40\x7f\x02\x0c\x02\x7f\x7f\x04\x08\x10'
b'\x7f\x3e\x41\x41\x41\x3e\x7f\x09\x09\x09\x06\x3e\x41\x51\x21\x5e\x7f\x09'
b'\x19\x29\x46\x46\x49\x49\x49\x31\x01\x01\x7f\x01\x01\x3f\x40\x40\x40\x3f'
b'\x1f\x20\x40\x20\x1f\x3f\x40\x38\x40\x3f\x63\x14\x08\x14\x63\x07\x08\x70'
b'\x08\x07\x61\x51\x49\x45\x43\x00\x7f\x41\x41\x00\x02\x04\x08\x10\x20\x00'
b'\x41\x41\x7f\x00\x04\x02\x01\x02\x04\x40\x40\x40\x40\x40\x00\x01\x02\x04'
b'\x00\x20\x54\x54\x54\x78\x7f\x48\x44\x44\x38\x38\x44\x44\x44\x20\x38\x44'
b'\x44\x48\x7f\x38\x54\x54\x54\x18\x08\x7e\x09\x01\x02\x0c\x52\x52\x52\x3e'
b'\x7f\x08\x04\x04\x78\x00\x44\x7d\x40\x00\x20\x40\x44\x3d\x00\x7f\x10\x28'
b'\x44\x00\x00\x41\x7f\x40\x00\x7c\x04\x18\x04\x78\x7c\x08\x04\x04\x78\x38'
b'\x44\x44\x44\x38\x7c\x14\x14\x14\x08\x08\x14\x14\x18\x7c\x7c\x08\x04\x04'
b'\x08\x48\x54\x54\x54\x20\x04\x3f\x44\x40\x20\x3c\x40\x40\x20\x7c\x1c\x20'
b'\x40\x20\x1c\x3c\x40\x30\x40\x3c\x44\x28\x10\x28\x44\x0c\x50\x50\x50\x3c'
b'\x44\x64\x54\x4c\x44\x00\x08\x36\x41\x00\x00\x00\x7f\x00\x00\x00\x41\x36'
b'\x08\x00\x10\x08\x08\x10\x08\x00\x00\x00\x00\x00')
Here is the program that I used to test things out.
from time import sleep
import board
import neopixel
from random import randint
from font import font7x5
def wax_on(rgb, delay):
for i in range(num_pixels):
pixels[i] = rgb
pixels.show()
sleep(delay)
def wax_off(rgb, delay):
for i in range(num_pixels-1, -1, -1):
pixels[i] = rgb
pixels.show()
sleep(delay)
def set_pixelxy(x, y, rgb):
if x % 2 == 0:
i = 8 * x + y
else:
i = x * 8 + 7 - y
pixels[i] = rgb
def scroll(txt, delay, rgb):
msg = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
for c in txt:
msg += bytearray(b'\x00')
msg += font7x5[(ord(c)-32)*5:(ord(c)-32)*5+5]
msg += bytearray(b'\x00')
msg += bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
for i in range(len(msg)- 8):
t = msg[i:i + 8]
for x in range(8):
for y in range(8):
if t[x] >> y & 1:
set_pixelxy(x, y, rgb)
else:
set_pixelxy(x, y, off)
pixels.show()
sleep(delay)
pixel_pin = board.GP18
num_pixels = 64
ORDER = neopixel.GRB
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.2, auto_write=False, pixel_order=ORDER)
off = (0, 0, 0)
pixels.fill(off)
pixels.show()
for y in range(8):
for x in range(8):
set_pixelxy(x, y, (255, 0, 0))
pixels.show()
sleep(0.1)
sleep(3)
pixels.fill(off)
pixels.show()
scroll("OMG. I can't believe that the scrolling works.", 0.05, (0,0,255))
sleep(3)
while True:
colour = (randint(0,255),randint(0,255), randint(0,255))
wax_on(colour, 0.1)
sleep(0.5)
wax_off(off, 0.1)
sleep(0.5)

