The internet is littered with tutorials teaching how to use dot matrices or build them, so why add-in another one I hear you say? Simply because making LED displays is fun, the outcome is eye-pleasing and useful in every way you could imagine. And since we’re in the age of IoT, what a better way to interact with it than from your smartphone. I used the LED matrix I built as a scrolling ticker, just to showcase the versatility of such a device. In the following I’ll shed some light on the essential building blocks of this project.LED panel
Before getting to how to build an entire LED panel, here’s a quick reminder of the working principle of an LED.
For the LED to light up, electricity should flow from the positive side (anode) to the negative side (cathode). If the LED is wired the other way around, the current will not flow and the LED will be OFF.
When we connect in series the anodes of n LEDs, all is left to do for controlling them individually is to toggle their cathodes ON and OFF. Below is a common-anode LED column with n equal to 8. This way, instead of using 2*n pins, we drive them all using only n+1 pins.
In the same line of thought, by putting n LED columns one next to the other, and connecting the cathodes row-wise, you can control the whole grid one column at a time. As a matter of fact, in most (if not all) commercial LED displays, one column (or one row) of the display is switched on only a fraction of time in a round-robin fashion at such a high frequency that’s not noticeable by the human eye. We have the impression that all columns are powered on at the same time, but that’s not the case. This process is called time-multiplexing, and the process of displaying content column by column is called column-scanning (there's also row-scanning). One of the biggest advantages is, all we need is n+n pins to have individual control over n**2 LEDs. For instance, here's how the word "HI" is displayed on an 8x8 LED Matrix:Choice of LEDs
Seeing that dot matrices are made of what looks like through-hole LEDs, I naively thought at first that all it takes to go from a dot matrix to an LED display with big pixels like the one I made, is to encapsulate a regular 5mm LED in a cube (in other words, no need for SMD LED strips). However, as I went on with the implementation of this idea it became clear to me that it wasn’t as simple as that.
I experimented with 3 types of through-hole LEDs:
- Regular water-clear LEDs
- Diffused LEDs
- Straw Hat LEDs
My final decision was to use Straw Hat LEDs, since they offer a wide viewing angle (around 140°) thanks to a mirror inside the LED that reflects vertical light rays in horizontal directions. In contrast, a regular 5mm LED has a tight beam angle (60° at best). As a result, the light is focused head-on and creates a bright spot on the surface of the pixel. Between these two stand diffused LEDs. Their envelope comes with an opaque finish that disperses light around a greater angle, but at the expense of a dimmer light intensity.
In the picture below, you can see three "pixels", each using a different LED type.LED panel driver
The driver is the chip that performs the logic of the LED panel. At its most basic form, it is a component that would allow us to control 16 digital output pins in a microcontroller-independent manner (of course we’ll still have to write microcontroller-dependent code to program it). Here are some possible choices:
- Shift registers: 74HC595,...
- GPIO expanders: MCP23017, MCP23S17,...
- LED matrix drivers: manufactured LED displays use dedicated drivers. These chips are much more complex because they take many considerations into account: current value, power consumption, brightness control, color mixing (for RGB displays), smoothness of visual effects, ghost cancelling...
I drove mine with the MCP23017. I wish I could give you a fancy reason for this choice, but the truth is, that's all I was aware of at the time of the making, and given the weak timing constraints and the relatively small size of the LED matrix (380mm x 380mm x 47mm), I didn’t see any reason why the I²C bus would be slow, so I chose the MCP23017. This being said, I would recommend a dedicated LED matrix driver, for instance the MAX7219.
MCP23017 GPIO Expander
A GPIO expander is a device that provides more general purpose input/output ports to a micro-controller. It usually communicates through a synchronous serial communication interface with the microcontroller.
The MCP23017 provides 16 additional GPIO ports (through 2 registers: GPIOA and GPIOB) and interrupts too (INTA and INTB). It communicates using the I²C interface, which needs a clock line (the SCL pin) and a data line (the SDA pin), and is thus identified with an address (via pins A0, A1 and A2). It is powered through pin VDD (5V or 3.3V), and pin VSS (Ground).
The MCP23017 is able to operate with 3 different frequencies of the I²C bus: 100kHz, 400kHz and 1.7MHz. In this project 100kHz is enough. But surely, performing communications over longer distances (say meters) will require you to increase the I²C bus frequency in order to have decent response times, in which case I would recommend you give up on I²C and try out another communication protocol that's faster by design.
Programming the MCP23017 on Arduino
Adafruit wrote an open source library to program the MCP23017 on Arduino. It provides functions for setting the polarity of the GPIOA and GPIOB registers, reading and writing them, setting up and handling interrupts as well as setting the values of the integrated pull-up resistors.
One word of wisdom, make sure to set the bits of registers GPIOA and GPIOB all at once in one single instruction (there's a function in the library that does that). Otherwise, communication between Arduino and the LED matrix will be slow, and instead of a smooth scrolling, all you'll end up with is scintillating pixels.Bluetooth Connectivity
Who thinks about Bluetooth on Arduino thinks about the HC-05 Bluetooth module. This device adds Bluetooth with the serial port profile (SPP) to Arduino. Bluetooth SPP basically means that, once a Bluetooth enabled device is paired up with the HC-05 module, the 2 communicate in a way that emulates a serial cable. It's a serial communication.
The HC-05 has 2 functional modes: AT command mode for configuration, and data transparent transmission mode for data transmission. I didn't need to perform any extra configuration for this module, so I used it in data transparent transmission mode. It comes with a datasheet that is comprehensive enough in terms of how to pair it up, how to wire it and how to find extra documentation on the internet.
In this project I used the HC-05 module solely to receive text strings from a smartphone via Bluetooth. The received text string is then scrolled on the LED Matrix.
Programming the HC-05 Bluetooth module
Since this device emulates a serial interface, it is programmable using the SoftwareSerial Arduino library. Data is received in series, one character at a time, so writing post-processing code is necessary.
Another word of wisdom (that would have saved me a couple of days of work), before uploading code to Arduino, disconnect transmission and reception pins of the HC-05 from Arduino, otherwise the upload will fail.
Pairing up a smartphone with the HC-05 Bluetooth module
HC-05 is compatible with Android but not with iOS. All you need to do is to install the Bluetooth Terminal App on your Android device (phone, tablet,...). Once you launch the app, the rest is self-explanatory.Packaging it all
I built the case of the LED Matrix from plain cardboard. I separated the LEDs using white foam sheets (I used black foam sheets initially, but then substituted as much as I could with white foam, as white reflects light better). The plastic sheet that covers the front of the LED matrix is 0.5 mm thick, and has a thin sheet of white nylon silk attached to it at the back side for a better light diffusion.
The outer box of the LED matrix is 380mm x 380mm x 47mm in size. Each pixel is 40mm x 40mm x 30mm big.