Post comments on this article and find any associated files and/or downloads at
www.nutsvolts.com/index.php?/magazine/article/august2015_SpinZone.
ITEM DESCRIPTION SOURCE/PART
BOM
Propeller Activity Board Parallax #32910
Circuit Overlay Board Parallax #32999
R1..R3 47 Ohm Mouser #299-47-RC
D1..D6 Green, 5mm Mouser #604-WP7113GD
This is pretty cool, right? It is, and yet I
know you're thinking, "Okay, Jon, that's
great, but what happens when I want to
have two LEDs on at the same time?" As my
friend John B. frequently quips ... no
problem, it's just a small matter of
programming (SMOP).
this allows us to control the designated LED. Yes, this
means that we can only activate one at a time, and for
many applications this is fine. For a 1-of-N project, we
don't need any special code, just a method to handle
which LED is active:
So far, we've only used Charlieplex wiring, but the
software process of Charlieplexing — like its cousin,
multiplexing — is more involved. What we're going to do is
loop through a control value that tells us which LEDs are
on. For those that are on, we will light them briefly, then
move to the next LED.
pub set_cp_led(n)
dira[CP2..CP0] := %000
If we do this fast enough (greater than 50 Hz), the
persistence of vision in our retinas will cause the LEDs to
appear to be on at the same time.
case n
0:
outa[CP2..CP0] := %001
dira[CP2..CP0] := %011
In most processors, this happens in an interrupt, and
for very simple Propeller programs we might even be able
to use the timer object to refresh the LEDs on a
reasonably fixed schedule. To be on the safe side,
however, and keep things general-purpose, I decided to
create a stand-alone object.
1:
outa[CP2..CP0] := %010
dira[CP2..CP0] := %011
For the object to work, the LEDs must be wired as in
Figure 3 and the pin passed to the start() method is the
2:
outa[CP2..CP0] := %001
dira[CP2..CP0] := %101
LSB pin of the three-pin group. After that, everything else
takes care of itself. Here are the start() and stop()
methods for the six LED Charlieplex object:
5:
outa[CP2..CP0] := %100
dira[CP2..CP0] := %110
pub start(cp0)
3:
outa[CP2..CP0] := %100
dira[CP2..CP0] := %101
stop
cycleticks := (clkfreq / 300) / 6
cog := cognew(charlie_6(cp0), @stack) + 1
4:
outa[CP2..CP0] := %010
dira[CP2..CP0] := %110
return cog
pub stop
if (cog)
cogstop(cog - 1)
The method counts on having pin constants CP0 and
CP2 defined; these are the LSB (Least Significant Bit) and
ledbits := %000000
MSB (Most Significant Bit) control pins of the three-pin
group. At the start of the method, we set the direction bits
for the group to %000 which disables all outputs. This
serves two purposes: 1) It clears the LEDs in the event we
pass an invalid LED number; and 2) It prevents ghosting of
LEDs when making changes from one to another.
It is convention for the start() method to call the
stop() method to ensure everything is clean before
launching a cog (as we do here). The stop() method will
kill the presently running cog, mark it as stopped, and
clear the control value (ledbits).
If you look carefully, you'll see that the code in the
case structure directly corresponds with the control table.
It's a good idea to create such a table when using
Charlieplex wiring, and structure the code to follow your
table.
The start() method sets the timing for LED updates in
the global (to the object) variable cycleticks. Remember
that all timing in the Propeller is done in system ticks. By
dividing clkfreq (system ticks in one second) by 300, we
set the update rate to 300 Hz. Why? In a world filled with
16 August 2015