Raspberry Pi Pico
5x5 RGB Matrix Breakout
The 5x5 RGB Matrix Breakout is another Pimoroni board from the breakout garden range. The LEDs are connected to the driver in a very similar way to the LED Shim. That made it a quick tweak to get library code running on it. Like the 11x7 matrix, it is a no-solder solution and can be quickly connected to a breadboard.

For the library, I just removed a few entries in the table and added a method to address pixels by coordinates. I saved this as scrollrgb.py.
from time import sleep_ms
_f = 0
_b = bytearray(145)
class SCROLLRGB:
def __init__(self, i2c):
self.i2c = i2c
self._w(253, 11)
sleep_ms(100)
self._w(10, 0)
sleep_ms(100)
self._w(10, 1)
sleep_ms(100)
self._w(0, 0)
self._w(6, 0)
for bank in [1,0]:
self._w(253, bank)
self._w([0] + [255] * 17)
self.clear()
self.show()
def _w(self, *args):
if len(args) == 1: args = args[0]
self.i2c.writeto(116, bytes(args))
def clear(self):
global _b
del _b
_b = bytearray(145)
def fill(self, r, g, b):
for i in range(25):
self.set_pixel(i, r, g, b)
def show(self):
global _f
_f = not _f
self._w(253, _f)
_b[0] = 36
self._w(_b)
self._w(253, 11)
self._w(1, _f)
def set_pixelxy(self, x, y, r, g, b):
self.set_pixel(x + y * 5, r, g, b)
def set_pixel(self, n, r, g, b):
global _b
tbl = [118,69,85,
117,68,101,
116,84,100,
115,83,99,
114,82,98,
132,19,35,
133,20,36,
134,21,37,
112,80,96,
113,81,97,
131,18,34,
130,17,50,
129,33,49,
128,32,48,
127,47,63,
125,28,44,
124,27,43,
123,26,42,
122,25,58,
121,41,57,
126,29,45,
15,95,111,
8,89,105,
9,90,106,
10,91,107]
x = n * 3
_b[tbl[x]+1]=r
_b[tbl[x+1]+1]=g
_b[tbl[x+2]+1]=b
Here was some basic test code to get you started,
from machine import Pin, I2C
from time import sleep
from scrollrgb import SCROLLRGB
i2c=I2C(0,sda=Pin(4), scl=Pin(5))
display = SCROLLRGB(i2c)
# test pixel writing
for i in range(25):
display.set_pixel(i, 0, 0, 255)
display.show()
sleep(0.1)
# filling
sleep(1)
display.fill(0, 0, 0)
display.show()
sleep(1)
display.fill(255,0,0)
display.show()
sleep(1)
display.fill(0,255,0)
display.show()
sleep(1)
display.fill(0,0,255)
display.show()
sleep(1)
# pixel writing by xy
for y in range(5):
for x in range(5):
display.set_pixelxy(x, y, 255, 0, 0)
display.show()
sleep(0.1)
Update
When I first put together the code on this page, I didn't quite manage to get text scrolling working. I have now corrected the situation. I copied the numbers for the 5x5 font used for the BBC micro:bit. It is called pendolino. I then transposed it so that the binary values represented columns instead of rows. I used Python to do all of the processing of the numbers.
The photograph shows the Pimoroni Pico Lipo. This is a pin-for-pin equivalent to the Pico with pin labels, LIPO charging, RGB LED, reset button.

The updated library,
from time import sleep_ms
_f = 0
_b = bytearray(145)
fnt = [0, 0, 0, 0, 0,
0, 29, 0, 0, 0,
0, 24, 0, 24, 0,
10, 31, 10, 31, 10,
10, 29, 21, 23, 10,
25, 18, 4, 9, 19,
10, 21, 21, 10, 1,
0, 24, 0, 0, 0,
0, 14, 17, 0, 0,
0, 17, 14, 0, 0,
0, 10, 4, 10, 0,
0, 4, 14, 4, 0,
0, 1, 2, 0, 0,
0, 4, 4, 4, 0,
0, 2, 0, 0, 0,
1, 2, 4, 8, 16,
14, 17, 17, 14, 0,
0, 9, 31, 1, 0,
19, 21, 21, 9, 0,
18, 17, 21, 26, 0,
6, 10, 18, 31, 2,
29, 21, 21, 21, 18,
2, 5, 13, 21, 2,
17, 18, 20, 24, 16,
10, 21, 21, 21, 10,
8, 21, 22, 20, 8,
0, 10, 0, 0, 0,
0, 1, 10, 0, 0,
0, 4, 10, 17, 0,
0, 10, 10, 10, 0,
0, 17, 10, 4, 0,
8, 16, 21, 20, 8,
14, 17, 21, 18, 14,
15, 20, 20, 15, 0,
31, 21, 21, 10, 0,
14, 17, 17, 17, 0,
31, 17, 17, 14, 0,
31, 21, 21, 17, 0,
31, 20, 20, 16, 0,
14, 17, 17, 21, 6,
31, 4, 4, 31, 0,
17, 31, 17, 0, 0,
18, 17, 17, 30, 16,
31, 4, 10, 17, 0,
31, 1, 1, 1, 0,
31, 8, 4, 8, 31,
31, 8, 4, 2, 31,
14, 17, 17, 14, 0,
31, 20, 20, 8, 0,
12, 18, 19, 13, 0,
31, 20, 20, 10, 1,
9, 21, 21, 18, 0,
16, 16, 31, 16, 16,
30, 1, 1, 30, 0,
28, 2, 1, 2, 28,
31, 2, 4, 2, 31,
27, 4, 4, 27, 0,
16, 8, 7, 8, 16,
19, 21, 25, 17, 0,
0, 31, 17, 17, 0,
16, 8, 4, 2, 1,
0, 17, 17, 31, 0,
0, 8, 16, 8, 0,
1, 1, 1, 1, 1,
0, 16, 8, 0, 0,
6, 9, 9, 15, 1,
31, 5, 5, 2, 0,
6, 9, 9, 9, 0,
2, 5, 5, 31, 0,
14, 21, 21, 9, 0,
4, 15, 20, 16, 0,
8, 21, 21, 30, 0,
31, 4, 4, 3, 0,
0, 23, 0, 0, 0,
0, 1, 1, 22, 0,
31, 4, 10, 1, 0,
0, 30, 1, 1, 0,
15, 8, 4, 8, 15,
15, 8, 8, 7, 0,
6, 9, 9, 6, 0,
15, 10, 10, 4, 0,
4, 10, 10, 15, 0,
7, 8, 8, 8, 0,
1, 5, 10, 8, 0,
0, 30, 5, 5, 1,
14, 1, 1, 15, 1,
12, 2, 1, 2, 12,
15, 1, 2, 1, 15,
9, 6, 6, 9, 0,
9, 5, 2, 4, 8,
9, 11, 13, 9, 0,
0, 4, 31, 17, 0,
0, 31, 0, 0, 0,
17, 31, 4, 0, 0,
0, 4, 4, 2, 2]
class SCROLLRGB:
def __init__(self, i2c):
self.i2c = i2c
self._w(253, 11)
sleep_ms(100)
self._w(10, 0)
sleep_ms(100)
self._w(10, 1)
sleep_ms(100)
self._w(0, 0)
self._w(6, 0)
for bank in [1,0]:
self._w(253, bank)
self._w([0] + [255] * 17)
self.clear()
self.show()
def _w(self, *args):
if len(args) == 1: args = args[0]
self.i2c.writeto(116, bytes(args))
def clear(self):
global _b
del _b
_b = bytearray(145)
def fill(self, r, g, b):
for i in range(25):
self.set_pixel(i, r, g, b)
def show(self):
global _f
_f = not _f
self._w(253, _f)
_b[0] = 36
self._w(_b)
self._w(253, 11)
self._w(1, _f)
def set_pixelxy(self, x, y, r, g, b):
self.set_pixel(x + y * 5, r, g, b)
def set_pixel(self, n, r, g, b):
global _b
tbl = [118,69,85,
117,68,101,
116,84,100,
115,83,99,
114,82,98,
132,19,35,
133,20,36,
134,21,37,
112,80,96,
113,81,97,
131,18,34,
130,17,50,
129,33,49,
128,32,48,
127,47,63,
125,28,44,
124,27,43,
123,26,42,
122,25,58,
121,41,57,
126,29,45,
15,95,111,
8,89,105,
9,90,106,
10,91,107]
x = n * 3
_b[tbl[x]+1]=r
_b[tbl[x+1]+1]=g
_b[tbl[x+2]+1]=b
def scroll_msg(self, msg, delay, r, g, b):
txt = [0,0,0,0,0]
for c in msg:
if ord(c)<32 or ord(c)>126:
txt += [0,0,0,0,0]
else:
txt += [0] + fnt[(ord(c)-32)*5:(ord(c)-32)*5+5]
txt += [0,0,0,0,0,0]
for i in range(0, len(txt)-5):
for x in range(5):
for y in range(5):
n = txt[i+x]>>(4-y)& 1
self.set_pixelxy(x, y, n * r, n* g, n * b)
self.show()
sleep_ms(delay)
And the test code,
from machine import Pin, I2C
from time import sleep
from scrollrgb import SCROLLRGB
i2c=I2C(0,sda=Pin(4), scl=Pin(5))
display = SCROLLRGB(i2c)
display.scroll_msg("OMG! The scrolling works.", 100, 255, 0, 0)

