Controlling LED arrays with pyMCU microcontroller

Check out the new site at https://rkblog.dev.

LED arrays are quite popular and handy. You can make animated banners, panels displaying text or basic graphics. For a microcontroller turning a LED on and off isn't a problem. However if you would have 64 or more LEDs then it's not that easy. A solution for this problem are LED controllers. They reduce the number of pins needed to manage all the LEDs. Some of those controllers may also implement other features handy for text scrolling etc. In this article I'll showcase 8x8 LED array with MAX7219 controller.

8x8 LED array with MAX7219 controller

Described module can bought from dx.com and other Chinese sites, or from hobbycomponents.com and some other shops importing such electronics.

This module can be connected with each other to create longer panels. The communication is done via SPI - Serial Peripheral Interface Bus. This allows us to control the whole LED array with just 3 pins (plus two for power). You can find Arduino or Raspberry code as well as various examples for this board or for the controller itself. There are also other boards using MAX7219 controller - it's quite popular.

Connecting to microcontroller

To connect this board to a microcontroller board we need to know which pins can handle SPI communication. For pyMCU the clock (SCK, SCLK) is digital pin 11, input (SDI/MISO) is pin 4, output (SDO, MOSI) is pin 5. The MAX7219 board has five pins: VCC (+), GND (-), DIN (to pin 5), CS (to pin 4) and CLK (to pin 11). One board can be powered by pyMCU. Multiple boards will have to use their own power supply (5V, few amps).

This board has also five upper pins for connecting multiple panels in longer chains. If we connect another board to the five top pins we will get two boards displaying the same thing. If we want to get a longer line then we have to connect all the SPI pins to the microcontroller except DIN pin. First board DIN pin goes to microcontroller, while next board DIN pin goes to DOUT pin (opposite pin on top of the board). There is an example on arduinobymyself.blogspot.com.br.

LED panel board connected to pyMCU
SPI and power pins on pyMCU

Scripting the LED array

There is a driver that can be used for that computer. For pyMCU I've forked it and modified to use pyMCU instead of Raspberry Pi SPI interface.

The code works but it creates its own pyMCU instance, which may clash if you would want to control multiple devices at the same time. I'll try to refactor the code later to a class that can take a pyMCU instance as an argument.

But now it's time to have some fun and display some text on the LED array:

import max7219.led as led
import max7219.transitions as transitions

led.init()
led.show_message("Hello world!", transition = transitions.left_scroll)

Few notes about SPI

If you have a board that uses SPI or I2C you must get a documentation for it - it will contain register numbers and values they accept to perform given task. Most of them will be given as hexadecimal values. In case of pyMCU it's easy to do SPI connections. At start we activate it:

mb = pymcu.mcuModule()
mb.spiEnable(1, 1000, 0, 0)
The arguments describe clock polarity, frequency as well as settings for data upload and download (check pyMCU module description for more details).

To send data just use mb.spiTransfer(DATA), where DATA is either string, integer or a list of integers. The board documentation will describe what and how to send. For MAX7219 we sent a two integer list - firs value is the register and the second is the value for the register. Raspberry Pi doesn't do anything more (explicitly in the code), but to make this working we have to fulfill a requirement from MAX7219 documentation:

Serial data is loaded into the shift register while CS is low. The last 16 bits of serial data are latched on CS’s rising edge.
So to send data to MAX7219 we have to se CS low, and to "execute" them we have to set it from low to high. For pyMCU this will look like:
def send_byte(register, data):
    mb.pinLow(4)
    mb.spiTransfer([register, data])
    mb.pinHigh(4)

Different boards can have various variations of SPI and I2C communications. This sometimes makes scripting such boards hard and annoying if no clear examples are given. Either so this board works and it's quite fun.

RkBlog

Check out the new site at https://rkblog.dev.
Comment article
Comment article RkBlog main page Search RSS Contact