Introduction: How to Use an LED Array Module

With a single LED you can indicate the state of something: on or off. That might be a little boring. With an array of LEDs you can display characters or even some simple blocky graphics. That might add a little pizzaz to a small microcontroller project.

You could use individual LEDs wired into a grid of rows and columns, or you can make use of a module that has the LEDs conveniently placed into a single package. Who wants to wrangle with a pile of LEDs? That is a LOT of leads to solder...

Remember the old dot-matrix printers? CGA displays? No? Well old dudes like myself sure do. Many devices like those displayed or printed their characters as an array of 7 rows of 5 pixels/dots. This project will help you learn how to use a 5 by 7 LED array.

As an alternate you can make use of an 8 by 8 LED array.

This Instructable will cover how the LED Array Module works and how to design a character set to display. I will put together a very simple microcontroller circuit to drive the display, and list the development environment and some of the firmware needed to do the task.

Step 1: An Array of LEDs

You may already likely be familiar with how you use an LED. They are dead simple to use. A microcontroller pin may output 5V that drives a single LED through a resistor and to ground.

The LED array arranges LEDs in rows and columns. The LEDs in the grid have their two connections, their cathodes and their anodes, connected to the other LEDs. By making these connections correctly, a microcontroller can drive any one LED on while leaving others off.

In the diagram below the LED at column 1 row 1 would be turned on if positive voltage is applied at C1 while ground is applied to R1. That single LED (C1 R1) would light up.

If, in addition to that, R3 was also at ground potential then the C1 R3 LED would also light.

You might work out that if we were to also light up the C3 R1 LED, that the C3 R3 will also light up, even if we do not wish to see it. There is voltage on C3 and ground on R3, so the LED is going to light itself.

To avoid that problem we can pick either a row or a column to light at a time. In this Instructable I control one column at a time. The microcontroller displays a pattern on column 1, then quickly moves to column 2 with a different pattern. The firmware moves through all five columns and then continues to cycle over and over. Done slowly this is rather odd looking as only one column is displayed at a time.

But if the cycling happens quickly, then it appears to the human eye that the entire display correctly displays a character.

The software will set column 1 to a positive voltage while setting 2-5 to ground. Then a pattern that results in row pins set to a positive voltage or ground is set on the row pins. After a delay, column 1 is set to ground and column 2 is set to a positive voltage. A new pattern is sent to the rows.

As each column is individually set to a positive voltage, each row gets a pattern of the LEDs to light up. When this is quickly cycled over and over the LED Array Module displays a single character.

Step 2: Encoding Column Patterns

"Encoding column patterns" sounds like something an android would do as a leisure activity. For this Instructable it is converting a pattern of illuminated LEDs into a hex value that can be used in the microcontroller source code.

The microcontroller will connect to the LED Array Module using two eight-bit ports. The 5 columns are connected to 5 lines from port A of the microcontroller. The 7 rows will be connected to 7 lines from port C.

The 5 column lines correspond to port A bits b0 to b4. Bit b0 is column 1, b4 is column 5. The microcontroller firmware turns on one column at a time, cycling through this hex pattern over and over:

The 7 row lines correspond to port C bits b0 to b6. Port C bit b0 is row 1 while b6 is row 7. The microcontroller firmware sends a pattern to the row unique to each column.

To encode the pattern for a column, the character pattern - font if you want to call it that - was drawn out for each ASCII character. Then each column was converted into a hex byte.

Rows 1-4 are b0-b3. This is the lower nibble of the column pattern. Rows 5-7 are b6-b4 - the upper nibble. If you want LED C1 R1 to be on, then the encoded value for the first byte of the character becomes 0x01.

You might note that sending a 0x01 to port C would turn on all of the LEDs in the row except for C1 R1. This is because an on led is encoded as a 1 bit, while the off LEDs are encoded as 0 bits. The firmware simply inverts the encoded patterns before sending them to Port C.

It is simpler to understand the patterns when 1 = on.

Step 3: Pattern Guide

This is a page from my notes. It shows a column from the LED Array Module. A penciled-in square represents an LED that is on. Immediately under it is the hex value for that nibble.

If these LEDs are on:
C1 R1
C1 R3
C1 R5
C1 R7

Then the lower nibble and the upper nibble pattern would translate into the hex value of 0x55.

Each character has 5 columns, so there would be 5 bytes of data needed to display any one character.

Since we are talking about 5 here, the bytes needed to display the 5 character are:

This was determined by drawing out the five in a 5 by 7 grid of boxes and encoding each column into a number.

See for a copy of the notes.

Step 4: Creating a Font for the Display

To make a font for the 5 by 7 characters, I filled in a 5 by 7 grid in my notes. 

After a while - about the time I got to the ampersand - my hand cramped up from coloring in little boxes. Coloring is the type of thing you want to have a kid do.

Luckily for me about a decade and a half ago I decided to have a kid just to do things like this for me.

So I had my son create this font. In the pictures below are my notes - and by "my" I mean his - that show all of the character patterns as well as the encoded bytes needed to display each column of the character.

See for a copy of the notes.

Step 5: Hardware

This is a list of parts:
  • LED Array Module
  • ATmel AVR ATmega644P
  • 40-pin DIP socket
  • 2 28 pin DIP sockets
  • Prototype PCB
  • 10k ohm resistor
  • .1 uF capacitor
  • strip pin header - 12 pins total
  • misc wire

This all came from my parts bin. The LED Array Modules were purchased surplus. All of these parts are commonly available via Digikey.

It should be noted that the copper side of the PCB should be cleaned well and then coated with flux. Then slide solder around on the back with the tip of a hot soldering iron as per this advice: It really makes working with these PCBs a lot easier when they are tinned like this.

Step 6: Schematic - Kinda

Well OK. It isn't a schematic, but a pin-out that you can follow to assemble the circuit.

See for a copy of this notebook page.

What should be noted here is that the pins of the AVR connect directly to the LED Array Module. I didn't use drivers and current limiting resistors. The reason for this? Simplicity. And because I can get away with it.

Normally you would use a current limiting resistor to limit the current going in to an LED. But this direct connection works. The output pin of the AVR only passes a limited amount of current, anyway, so there is no need for limiting resistors.

Step 7: Assembly

Not gonna say a whole lot here. Solder it. The placement isn't critical. The wires used were 28 gauge wire-wrap wire.

Follow the notes on the pics for a little additional information.

Certainly if you use an 8 by 8 module, or if the 5 by 7 module has a different pin-out from the one that I used, you can just copy the assembly without using your noggin to determine what needs to change.

Or you can and then suffer the consequences. Which may be that you let the smoke out of the electronics.

Step 8: Firmware

I used Atmel AVR Studio to set the fuses correctly on the ATmega644. First off, turn off the JTAG port (JTAGEN) - I always forget this little gem. I mean I never forget it because I'm really smart. Yeah, that.

And CKDIV8 is also off. That means the processor isn't slowed down by a factor of 8.

I used Imagecraft as a tool set for compiling code. Another excellent compiler is the Crossworks IDE made by Rowley

Here is a chunk of the character table:

unsigned char pattern[ 128 ][ 5 ] = {
0x00, 0x00, 0x00, 0x00, 0x00, // 0 - 00
0x00, 0x00, 0x00, 0x00, 0x00, // 1 - 01
0x00, 0x00, 0x00, 0x00, 0x00, // 2 - 02
0x00, 0x00, 0x00, 0x00, 0x00, // 3 - 03

It goes on and on...

Ugly, right? The first 32 ASCII characters are control characters. So I left them as 0x00 to display blanks. I told my son that he could make up some characters and put them in there. That was hours ago. I have a feeling it's not gonna happen.

Here is where the fun starts:

0x00, 0x00, 0x2F, 0x00, 0x00, // 33 - 21 !
0x00, 0x07, 0x00, 0x07, 0x00, // 34 - 22 "
0x14, 0x7F, 0x14, 0x7F, 0x14, // 35 - 23 #

Go look at the notes - you will see these are values taken from the notes.

I made some rough code to quickly show all of the characters. The exciting movie is fullset2.MOV below. The code comes with an apology: it is only rough just to prove that this works. No finesse was expended making the code.

Step 9: Thanks!

Thanks for reading!

Feel free to post if you have any questions!

LED Contest

Participated in the
LED Contest