This time we have a sneak peak at the PI household to see their preparations for the BYOB Party
Mr PI, not to be outdone by the young whipper-snapper Mr UNO Mrs Yun decided to have a crack at driving a couple of those fancy LED matrix panels from Adafruit, the idea being that messages can be posted to the iot.eclipse.org MQTT Broker and mr PI would subscribe to them and display the data (Messages) on the matrix display in glorious colour
Having all that extra memory allows the PI to calculate the patterns for much bigger displays but I was concerned that the timing may be an issue, after all, PI struggles even with a simple WS2812B neopixel.
Well as it happens I need not have been concerned, the timing on these boards is pretty straight forward and really only affects the refresh rate, not the actual clocking of the data to the display
The boards work a bit like a TV, well not quite but you'll see what I mean
these particular boards have two sets of serial data inputs, consisting of an R, G, B data line for each serial channel, a clock line to control the data feed and an Output enable / Latch to lock in the data and display on the LEDs
you clock as many pixels as there are in a row (up to 3 bytes per pixel) so 32 pixels = 92, 184 if you count both panels as the serial out from one feeds into the serial in of the next. The boards can be extended as far as needed, the cpu just needs to be able to clock out the data fast enough to keep up a decent refresh rate
there are 3 address lines permitting sending the RGB data to one of 8 LED rows (Remember there are two channels of RGB so we cover the 16 rows with 8 addresses and two serial streams), so the best refresh rate of a line is one in 8
if your using more than one board daisy chained then you simply clock out more data before firing the latch line
that's all there is to it basically.
So Adafruit has done an awesome job of creating a library to support these boards and you can download it from their site ( here: https://learn.adafruit.com/connecting-a-16x32-rgb-led-matrix-panel-to-a-raspberry-pi/overview
and part two where the topic adds additional boards in cascade https://learn.adafruit.com/16x32-rgb-display-with-raspberry-pi-part-2
there is a nice set of instructions on how to wire up the PI to the panels and plenty of sample code that can run the boards
Code is a C module and there is also Python samples
additional help can be found here https://github.com/Boomerific/rpi-rgb-led-matrix
there are a lot of wires used to connect the matrix panels but this is no different no matter the controller your using.
for example this is an easy to follow Python sample
import RPi.GPIO as GPIO import time delay = 0.000001 GPIO.setmode(GPIO.BCM) red1_pin = 17 green1_pin = 18 blue1_pin = 22 red2_pin = 23 green2_pin = 24 blue2_pin = 25 clock_pin = 3 a_pin = 7 b_pin = 8 c_pin = 9 latch_pin = 4 oe_pin = 2 GPIO.setup(red1_pin, GPIO.OUT) GPIO.setup(green1_pin, GPIO.OUT) GPIO.setup(blue1_pin, GPIO.OUT) GPIO.setup(red2_pin, GPIO.OUT) GPIO.setup(green2_pin, GPIO.OUT) GPIO.setup(blue2_pin, GPIO.OUT) GPIO.setup(clock_pin, GPIO.OUT) GPIO.setup(a_pin, GPIO.OUT) GPIO.setup(b_pin, GPIO.OUT) GPIO.setup(c_pin, GPIO.OUT) GPIO.setup(latch_pin, GPIO.OUT) GPIO.setup(oe_pin, GPIO.OUT) screen = [[0 for x in xrange(32)] for x in xrange(16)] def clock(): GPIO.output(clock_pin, 1) GPIO.output(clock_pin, 0) def latch(): GPIO.output(latch_pin, 1) GPIO.output(latch_pin, 0) def bits_from_int(x): a_bit = x & 1 b_bit = x & 2 c_bit = x & 4 return (a_bit, b_bit, c_bit) def set_row(row): #time.sleep(delay) a_bit, b_bit, c_bit = bits_from_int(row) GPIO.output(a_pin, a_bit) GPIO.output(b_pin, b_bit) GPIO.output(c_pin, c_bit) #time.sleep(delay) def set_color_top(color): #time.sleep(delay) red, green, blue = bits_from_int(color) GPIO.output(red1_pin, red) GPIO.output(green1_pin, green) GPIO.output(blue1_pin, blue) #time.sleep(delay) def set_color_bottom(color): #time.sleep(delay) red, green, blue = bits_from_int(color) GPIO.output(red2_pin, red) GPIO.output(green2_pin, green) GPIO.output(blue2_pin, blue) #time.sleep(delay) def refresh(): for row in range(8): GPIO.output(oe_pin, 1) set_color_top(0) set_row(row) #time.sleep(delay) for col in range(32): set_color_top(screen[row][col]) set_color_bottom(screen[row+8][col]) clock() #GPIO.output(oe_pin, 0) latch() GPIO.output(oe_pin, 0) time.sleep(delay) def fill_rectangle(x1, y1, x2, y2, color): for x in range(x1, x2): for y in range(y1, y2): screen[y][x] = color def set_pixel(x, y, color): screen[y][x] = color fill_rectangle(0, 0, 12, 12, 1) fill_rectangle(20, 4, 30, 15, 2) fill_rectangle(15, 0, 19, 7, 7) while True: refresh()
if you have not already updated or installed Python, now would be a good time
this is the code I used finally for the messages, it is a relatively
import os from PIL import ImageFont from PIL import Image from PIL import ImageDraw text = (("Raspberry Pi ", (255, 0, 0)), ("and ", (0, 255, 0)), ("Adafruit", (0, 0, 255))) font = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeSans.ttf", 16) all_text = "" for text_color_pair in text: t = text_color_pair[0] all_text = all_text + t print(all_text) width, ignore = font.getsize(all_text) print(width) im = Image.new("RGB", (width + 30, 16), "black") draw = ImageDraw.Draw(im) x = 0; for text_color_pair in text: t = text_color_pair[0] c = text_color_pair[1] print("t=" + t + " " + str(c) + " " + str(x)) draw.text((x, 0), t, c, font=font) x = x + font.getsize(t)[0] im.save("test.ppm") os.system("./led-matrix 1 test.ppm")
easy task to change the message to one you like (Look for this line "text = (("Raspberry Pi ", (255, 0, 0)), ("and ", (0, 255, 0)), ("Adafruit", (0, 0, 255)))" )
What I am planning to do is to have the PI subscribe to the elcipse mqtt broker with a specific topic "BreadBoard_Messages" and as messages are published, a modified version of the code will create the required image and then render and scroll it across the panels.
This will allow party messages or tweets to be received and shown during the BYOB Party, My PI may not be able to interact too much but if he can pull this off it will be a great feat and useful in the future too
here is a short video demonstrating the PI driving a couple of the panels
in the next post I hope to have the code ready to read from the subscription data and render as an animated display in near real time
that's where I have challenged my son to help, integrate two sets of code into one great application
Ill be back with the results in a few days on this one
See you soon