You are on page 1of 9

technology

workshop

craft

home

food

play

outside

costumes

Practical Guide to LEDs 4 - Matrix & Multiplexing


by nqtronix on September 26, 2016

Table of Contents
Practical Guide to LEDs 4 - Matrix & Multiplexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Intro: Practical Guide to LEDs 4 - Matrix & Multiplexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Step 1: Multiplexing I - Circuit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Step 2: Multiplexing II - Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Step 3: Increasing Brightness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Step 4: Adjusting Brightness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Step 5: Growing Huge With Shift Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Step 6: Charlieplexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Related Instructables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Advertisements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

Intro: Practical Guide to LEDs 4 - Matrix & Multiplexing


You've heard about LEDs. Chances are you've already tinkered with them. But there are so much details you probably don't know about. Sadly the resources available
are often incomplete or just unpractical. This guide takes you all the way from a beginner level to adept skills!
This is chapter 4 of a short series. Use the table of contents below to browse the content I've published yet. New chapters are added every sunday!
As your projects grow in size (and the amount of LEDs) you'll soon run out of I/Os to use. In this chapter we'll discover how to use a few I/Os to drive a whole bunch of
LEDs, such as an 7 segment display or a huge LED dot matrix display!
Chapters:
Pick your LED!
Essential Circuits
Switching & Dimming
Matrix & Multiplexing
1. Multiplexing I - Circuit
2. Multiplexing II - Code
3. Increasing Brightness
4. Adjusting Brightness
5. Growing Huge With Shift Registers
6. Charlieplexing
5. High Power & Lighting
1.
2.
3.
4.

Sorry for being a day late, all the schematics and code were a lot more effort than estimated and took longer than any of the previous chapters. I hope the outcome is
worth it.
New instructables are scheduled every 2nd and 4th sunday each month. The new Semester is ahead and I won't have the time for more frequent uploads. I may take a
break for a study-headstart, but I'll surely be back on Oct 23rd with the last chapter!

Step 1: Multiplexing I - Circuit


In the last chapter we've learned that LEDs are visible to the human eye even if they are only powered for short periods. This does not only allow us to set the brightness,
but also to power LEDs sequentially. Only a part of all LEDs is driven by a few I/Os at once, additional I/Os select which part of the LEDs should be driven. I know this
may sound overly complicated at first, but let me show you that this isn't the case.
I'm very aware that there are ICs which are made specifically for LED multiplexing. Allthough they are quite expensive they can be very handy to drive huge amounts of
LEDs (64+). For smaller projects they are not required though, an ARDUINO can do the very same and it's likely you'd use one anyway. To better understand what's
going on inside the chip, we'll program the ATMEGA328P (the chip of the ARDUINO) in C and without fancy libraries. Take a deep breath, this will be quite a bit to digest.
It helps to understand the code from last chapter as we'll re-use quite a bit of it.
The example project: Driving a 4 digit 7 segment display (with decimal point)
The operating conditions:
The common power supply voltage is
USYS = 5V
The 7 segment displays have the following values
UF = 2.1V
IF = 20mA

The goal:
A display with 4x8 segments would require 32 I/Os to be driven traditionally. An ATMEGA328P has only 23 I/Os, and you'll need a few for other hardware as well. The
proposed solution will only require 12 I/Os, less than 40% of the original idea.

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

The idea:
Only one digit will be powered at a time, which is selected by one of 4 I/Os. This allows to share the same 8 I/Os to control the segments of all digits. The microcontroller
needs to cycle trough all digits fast enough that no flickering will be visible.
The circuit:
For this chapter we'll use common anode 7-segment displays as they are more commonly used. A common anode has certain benefits for advanced circuits, but
requires an odd circuit design. If you only have common cathode parts that's ok, too. You need to make a few minor changes to the circuit and code and it'll work as well.
In the last chapter the I/Os sourced current to the anode of the LEDs; the current was flowing out from the pin. A logic "1" corresponded with a lit LED. In this circuit the
cathode of the LED is driven, so the pin must sink the current to turn the LED on. This is done by setting the output to 0V - a logic "0". This is not a huge deal, but the
code needs to account for this.
To provide power to the LEDs P-Channel Mosfets are used. They behave similar to the N-Channel Mosfets used in previous chapter, except they require a negative
Gate-Source voltage VGS to turn on. The two possible cases are:
V = 0V Mosfetoff
1. logic "1" = 5V GS
V = -5V Mosfeton
2. logic "0" = 0V GS
Note that this only works when the signal voltage matches the supply voltage. If the supply voltage for the Mosfets is larger they will not switch off:
V = -7V Mosfeton
1. logic "1" = 5V GS
V = -12V Mosfeton
2. logic "0" = 0V GS

The resistors R1 -R8 are chosen according to chapter 2.


R = (USYS - UF) / IF = 145 150
For your own design check if the Mosfets (AO3401 in this case) are suitable for the current of all 8 segments (8*20mA = 160mA). Since they are only on for of the time
the total power dissipated is also :
P = RDS(ON) * IDS / 4 = 0.06 * (0.16A) = 384W

File Downloads

iG3.1 datasheet_AO3401.pdf (497 KB)


[NOTE: When saving, if you see .tmp as the file ext, rename it to 'iG3.1 datasheet_AO3401.pdf']

Step 2: Multiplexing II - Code


This time the all code can be downloaded as a .rar file. No need for copy &paste ;)
The ATMEGA328P does not have any build-in hardware to support multiplexing out-of-the-box. Instead we have to manually switch the outputs at the right time. Here is
the rough plan of events which should happen regularly:
1.
2.
3.
4.
5.
6.

Load segment data for digit N


Turn on digit N
Wait some time
Turn of all digits
Change N to the next digit
Repeat.

On run of the plan above will be called "phase". After 4 phases each digit has been active once, which equals a complete "cycle". The term "duty cycle" refers to the
relative on-time of a LED; with 4 phases the duty cycle is 1/4.
Activating the outputs:

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

Before we can run the plan above we need to enable the outputs, which can be easily forgotten. It is important to set the outputs to high beforeenabling them. If the
commands would be executed in reverse order, all segments would be on for a short time.In this case it wouldn't damage the chip, but should be avoided as a good
practice.
PORTB
PORTD
DDRB
DDRD

|=
=
|=
=

0x0F;
0xFF;
0x0F;
0xFF;

//
//
//
//

prepare off-state
prepare off-state
Enable the output
Enable the output

for
for
for
for

Mosfets
segments
the IO PB0 thru PB3
the the whole port

The purpose of interrups :


Although the plan above says "wait" it'd be incredible stupid to use a "delay" function as it causes 100% load. Instead we need to set up a timer, which runs
simultaneously to our main code, and notifies us as soon as the wait time is over. This is done by using an "interrupt". As soon as an interrupt happens the microcontroller
automatically does the following:
1. Stop the current code & save where to continue
2. Execute the specific "ISR" (Interrupt Service Routine) code
3. Continue from the previous saved spot
While an interrupt is running no other interrupt can be executed, so it's best to keep all ISRs as short as possible.
Configuration of the Timer0:
Every timer supports various interrupt sources. For this application we'll use the overflow interrupt of Timer0. At each interrupt the active digit will be changed. To archive
a flicker-less display at least 100 cycles per seconds are required. Each cycle consists of for phases so Timer0 must overflow at least 400 time per second. The prescaler
needs to be set to
prescaler
f / steps / fcycle = 8MHz / 256 / 400 78
clock
prescaler = 64
TCCR0A
TCCR0B

= 0x00;
= (1<<CS01)|(1<<CS00);

// Select normal mode without PWM channels


// Set the prescaler to /64 and start the timer

Remember to enable the interrupt:


TIMSK0
sei();

= (1<<TOIE0);

// Enable interrupts @ overflow


// Enable interrupts in general

Programming the ISR:


This is where all the magic happens. To work the code must know two things:
1. The current phase of the cycle, ie. which digit should be active
2. The data to display, ie. which segments should be driven
This information is stored in two global variables, one of which is an array with 4 elements:
volatile uint8_t digit[4]
= {0};
//
//
####
####
####
####
//
# #
# #
# #
# #
//
####
####
####
####
//
# #
# #
# #
# #
//
####
####
####
####
//
//digit NR: 3
2
1
0
volatile uint8_t current_phase = 0;

// stores the next output value

// current active digit

The plan laid out above is not suitable for an ISR, it needs to be re-ordered that the wait time is at the beginning or end:
1.
2.
3.
4.
5.

Turn of all digits


Change N to the next digit
Load segment data for digit N
Turn on digit N
Wait some time

The resulting code is the following:


ISR(TIMER0_OVF_vect)
{
PORTB
|= 0x0F;
// begin next phase
if(current_phase == 0)
current_phase = 3;
else
current_phase--;
PORTD
PORTB

= ~(digit[current_phase]);
& ~(1<<current_phase)|0xF0;

// This code will be executed every overflow!


// Turn all Mosfets off

// Counting down is faster

// Update segments
// Turn Mosfet for current digit on

As it does not matter in which order the digits are active, the phase number is counted down to benefit from the faster execution of if(current_phase == 0) instead
of if(current_phase == 3).
The ~ of PORTD = ~(digit[current_phase]); inverts all bits, a "1" in memory matches a active segment. ~(1<<current_phase) results in 7 "1"s and a "0" at
the position of current_phase. The operator &= copies only all "0"s and thus turns only one digit on.
Defining individual symbols:

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

Somehow we need to tell the program which segments should be on for any desired character. Typing it in manually is not an option for me, so I wrote a include file
(dispCodec.h) to do all the decoding for me. You only need to type in which I/O are tied to which segments and you can use any of the symbols defined below.
The example on the cover image is generated by the code:
digit[3]
digit[2]
digit[1]
digit[0]

=
=
=
=

DP_L;
DP_E;
DP_d;
DP_4;

In this example the display is static, but you can change all characters at any time in the main loop or in additional ISRs. Have fun experimenting!

Image Notes
1. Drive signal of mosfet nr. 1. It is on during the low period and of during the highs.
2. One complete cycle: No two digits are on at the same time. The total cycle duration is about 8ms
3. The width of one of the squares in the background is equal to 2ms
4. Display refresh rate (= FPS)

File Downloads

iG3.2 - LED Matrix Code.rar (27 KB)


[NOTE: When saving, if you see .tmp as the file ext, rename it to 'iG3.2 - LED Matrix Code.rar']

Step 3: Increasing Brightness


You may notice that the LEDs are dimmer when driven multiplexed. This shouldn't be a huge surprise: Each LED is driven with a PWM signal, the same you've used
before to control the brightness. This isn't much of an issue for indoor use, at least with the example above. If you plan on adding more phases per cycle (to control more
digits) or using the device outdoors you may want to increase the brightness.
There are two ways to do this.
1. Increase the amount of segment drivers:
Instead of doubling the phase count it is also possible to increase the amount of pins to drive the segments. However this conflicts with the goal to use the least amount
of I/Os possible, so it should be your last choice.
2. Increase the current of the LEDs:
For short times LEDs tolerate a multiple of their rated current, provided they have enough time in between to cool down. This is such a common practice that
manufactures specifically include information about "peak forward current" into their datasheets.
To demonstrate the second method we'll upgrade the previous example.
The 7-segment displays used before were salvaged parts and the Chinese datasheet contains only basic information. Instead we'll design the circuit for a similar part
from Kingbright.
Peak forward current:
First we need to decide how much current the LEDs can handle. The peak forward current from the datasheet (160mA) is only valid if the duty cycle is 1/10 and the pulse
width is 0.1ms. To adopt for our duty cycle of 1/4 the maximum given value need to be reduced. The new duty cycle is 2.5 times larger, the given peak current needs to
be divided by that:
ILED = IPEAK / 2.5 = 160mA / 2.5 = 64mA
At 64mA the forward voltage is about 2.2V as the diagram shows. This results in a new resistor value of
R = (USYS - UF) / IF = (5V - 2.2V) / 64mA = 43.75 47

New driver circuitry:


The increased current requires stronger drivers for the digits and segments. A quick check revels that the current Mosfets are sufficient:
P = RDS(ON) * IDS / 4 = 0.06 * (8 * 0.064A) /4 = 3.93mW

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

The ATEMEGA328P on the other hand can only handle 20mA (40mA if you push it) so additional transistors for the segments are required. The updated schematic is
shown above. Resister values were calculated with the formula from last chapter:
R = (5V - 0.7V) * 100 / 0.064A = 6.72k 5.6k

Adopting the code:


The code stays almost identical, except now segments are driven with a high level signal - a logic "1". Therefore we need to alter the following lines:
PORTD = 0xFF; // prepare off-state for segments
PORTD = 0x00;
PORTD = ~(digit[current_phase]); // Update segments
PORTD = digit[current_phase];
Frequency adjustment:
The main reason to limit the current of LEDs is to prevent them from overheating. Pulsed current heats the LED only momentary, the shorter the pulse the better can the
head be absorbed by the case. This is why the pulse width is given in the datasheet.
It is possible to decrease the pulse width by increasing the cycle frequency. As all switching is done manually within the code, it increases processor load significantly and
should be therefore avoided. In my experience it will not effect the LEDs noticeably.

File Downloads

iG3.3 datasheet_kingbright_7segment_example.pdf (96 KB)


[NOTE: When saving, if you see .tmp as the file ext, rename it to 'iG3.3 datasheet_kingbright_7segment_example.pdf']

Step 4: Adjusting Brightness


Sometimes projects with a 7-segment display require at times a different brightness level. The most common application are clocks which need to be readable at daytime
and dim enough to let you sleep at night.
Now it's the time to take advantage of the fact that multiplexing is some kind of PWM!
To change the brightness of all LEDs simply turn of the digits before the end of the phase is reached. We use the same output compare register OCR0B as last chapter,
but this time not to generate a PWM signal, but an interrupt instead. The interrupt is enabled with:
TIMSK0

= (1<<TOIE0)|(1<<OCIE0B);

// Enable interrupts @ overflow & Compare Match B

All left to do is to move the "Turn all mosfets off" line into the new ISR:
ISR(TIMER0_COMPB_vect)
{
PORTB
|= 0x0F;
}

// This code will be executed at a compare match


// Turn all Mosfets off

The register OCR0B stores the current brightness value.


Tweaking the brightness of individual segments is done in a similar fashion. For each segment an individual interrupt is needed. To get along with only two output
compare channels, the brightness value needs to be updated within every phase once per segment.
Unfortunately I don't have any example code at hand; none of my projects required individual segment dimming. This chapter has been very code-heavy without this
already, so I decided to skip any further details and let you do your own research, if you want to.

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

Image Notes
1. Compared to Step#2 the on time is much shorter - the brightness of the digit is reduced
2. The display update frequency stays the same as in Step#2

File Downloads

iG3.4 - LED Matrix Dimming Code.rar (21 KB)


[NOTE: When saving, if you see .tmp as the file ext, rename it to 'iG3.4 - LED Matrix Dimming Code.rar']

Step 5: Growing Huge With Shift Registers


No matter how fancy your multiplexing technique is, you'll run eventually out of I/Os to control all the LEDs. Of course, you could just pick a larger microcontroller, but
they can be super expensive and usually don't come in handy DIP packages. There are several ICs which provide additional I/Os, the most common and perfectly suited
part for LEDs is the 74HC595 8-bit shift register. They are available in a variety of cases, including the popular DIP-16 and SOIC-16, way cheaper than any larger
microcontroller. For this step you'll need the datasheet to follow along, get it here if you don't have it.
So what are shift registers excatly?
Shift registers load and store one bit of data at a time. As the name suggests the data is "shifted" trough the memory: When the second bit is to be stored the previous
value is moved to the next memory cell. NXP calls the data input DS (pin 14) and the signal to store the next bit SHCP (pin 11).
The beauty about this design is that you can "chain" as many shift registers together as you want. As soon as one is full, the last bit is pushed out of the Q7S (pin 9)
output and can be fed into the next register. All other control signals can be shared across all ICs.
74HC595 do not directly put out the stored data to their outputs. Instead they have a second memory which is directly tied to the outputs. A signal on the STCP (pin 12)
input will load the data from the shift memory into it. Without this feature you would unintentionally control the outputs while shifting the data through all components. In
addition it has a OE (pin 13) input which disconnects all outputs (called Hi-Z state) if a logic "1" is applied. The last remaining input, MR (pin 10), resets the shift memory
back to zeros whenever the input is logic "0".
Once again the first example will be modified to explain how it works in practice, even though there is no need for such a low LED count.
The circuit:
The segments are now connected to the 74HC595 instead of the microcontroller. I'd be also possible to control the mosfets through a second shift register, but to keep it
simple they are connected traditionally. A small 100nF capacitor should be physically placed closed to the power inputs of the chip to provide power while switching. The
10k resistor R14 clears the contents of the shift registers whenever the ATMEGA is retested, R13 ensures the outputs are disabled during this time.
The names of the pins in the drawing of the shift register do not match up with the names above. It has been drawn according to IEC logic symbol convention which
makes reading any schematic easier, if you know how. For now I recommend to just compare the pin numbers.
The SPI interface:
The ATMEGA328P features a Serial Peripheral Interface - SPI for short - which allows to send out a byte of data at once. The data output MOSI (Master Out Slave In) of
the SPI module is connected to DS, the clock output SCK is connected to SHCP. In SPI master mode the SS pin can only be configured as an output, so it is tied to
STCP. The remaining OE input can be connected to any pin you wish.
The Code:
To reduce the amount of work I need to put into this (I'd says it has been plenty already) I re-used some of my personal code-base. There are plenty of comments within
the source code to explain what is going on. Do not this example has not been tested on hardware as a whole, but I can assure you all SPI related code works flawlessly.
Here's a short overview over the individual files and their purpose:
Config: Contains hardware specific information, in this case the pinout of the chip
HC595_config.h: Contains all non-SPI pinout information
SPI_config.h: Contains all SPI related pinout information
Driver: Contains files to control external hardware
HC595.c: Application code related to the shift register
HC595.h: List of all commands
HAL: (Hardware Abstration Layer) Contains files to control internal Hardware easily
SPI.c: Application code related to the SPI module
SPI.h: List of all commands
Utility: Contains files to ease programming
dispCodec.h: Assigns segment data to real expressions
macros.h: Allows to specify any I/O as ,
main.c: contains the application

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

The main.c code is very similar to the previous example. The code to define the outputs as been updated to:
PORTD
DDRD

|= 0x0F;
|= 0x0F;

// prepare off-state for Mosfets


// Enable the output for the IO PB0 thru PB3

The driver for the shift registers is enabled by HC595_initialize();, it sets up the SPI module and enables the outputs as defined in the Config folder.
The overflow ISR is change to:
ISR(TIMER0_OVF_vect)
{
// begin next phase
if(current_phase == 0)
current_phase = 3;
else
current_phase--;

// This code will be executed every overflow!

// Counting down is faster

HC595_loadData(1, &igit[current_phase]);
HC595_updateDriver();

// Shift the right values into the registers


// Load the values to the output memory

PORTD

// Turn Mosfet for current digit on

& ~(1<<current_phase);

HC595_loadData(1, &igit[current_phase]); starts the process of sending 1 byte of data. The & is required as the command requires a position of where to find
the data within the memory instead of the actual data itself. Finally HC595_updateDriver(); toggles the STCP pin to output the data after the shifting has been
completed.
Adding more shift registers:
For large dot-matrix displays you can use nearly infinite 74HC595 chained together. However the shifting process takes some time. I don't remember the exact speed of
the code, but it was about 1us at a 16MHz clock and as fast as possible. The code supports sending out multiple bytes at once to improve speed even further. To send
out an array called data with 4 elements you'd type:
data [4] = {0, 1, 2, 3};
HC595_loadData(4, data);
HC595_updateDriver();

// Assign any values to an array


// Shift out the first 4 elements of data
// Load the values to the output memory

Image Notes
1. Connect the DS input of the next 74HC595 here

File Downloads

iG3.5 - LED Matrix with Shift Register.rar (53 KB)


[NOTE: When saving, if you see .tmp as the file ext, rename it to 'iG3.5 - LED Matrix with Shift Register.rar']

iG3.5 datasheet_nxp_74HC595.pdf (251 KB)


[NOTE: When saving, if you see .tmp as the file ext, rename it to 'iG3.5 datasheet_nxp_74HC595.pdf']

Step 6: Charlieplexing
No guide about multiplexing is complete without at least mentioning Charlieplexing. Charlieplexing takes advantage of the three states a I/O can have: High (logic "1"),
Low (logic "0") and Hi-Z (input). Compared to normal multiplexing this method can decrease the pin count, but at the same time code and layout complexity increases
significantly. Therefore I do not recommend this for most applications.
Still, there are a few project which are not possible without, such as the miniature LED cube (by HariFun).
So, how does it work exactly?
With Charlieplexing only one LED is driven at a time. To do so one of all I/Os is set to High, one to Low and the remaining to Hi-Z. In the schematic above LED D1 is
driven when PD0 is High, PD1 Low and PD2 Hi-Z. The code must cycle through all I/O combinations for lit LEDs. Obviously each LED will be only on for a short time,
resulting in dim LEDs, especially if many LEDs are driven.
There are no simple solutions to increase the current while maintaining 3-state capabilities. However you can safely use the maximum current per pin of 40mA as each
pin is only on for a short time.
Resistors are calculated as usual, except the the value is split in half. In any configuration two resistors will be in series, so their value adds up to the total, calculated

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

value. Often the required resistor values will be very small. In such a case it is possible to rely on the internal resistance of the outputs. An ATMEGA328P has a typical
output resistance of 25@5V or 35@3V. The total resistance in series to any LED is therfore 50@5V or 70@3V. The remaining calculations are identical to general
multiplexing.
For now I have to leave you without any example code on this. If things go according to plan (which they usually don't), I have completed a project requiring charlieplexing
by the beginning of 2017 and will share the code along with it.

Related Instructables

Practical Guide
to LEDs 1 - Pick
your LED! by
nqtronix

Practical Guide
to LEDs 2 Essential
Circuits by
nqtronix

Practical Guide
to LEDs 3 Switching &
Dimming by
nqtronix

Complete guide
to LEDs by
Satyam Shree
Mahanta

Solder Fume
Extractor With
Activated
Carbon Filter by
nqtronix

100W LED
flashlight by
vvrtlar

Advertisements

Comments
1 comments

Add Comment

St Stephen says:
Thank you for sharing, thanks for taking time to post, great info!

http://www.instructables.com/id/Practical-Guide-to-LEDs-4-Matrix-Multiplexing/

Sep 26, 2016. 5:55 PM REPLY

You might also like