This is only a preview of the January 2021 issue of Practical Electronics. You can view 0 of the 72 pages in the full issue. Articles in this series:
|
Max’s Cool Beans
By Max the Magnificent
Flashing LEDs and drooling engineers – Part 11
G
ood grief! I am bubbling over with excitement.
I have so many things I want to talk about that I don’t
have a clue where to begin. I know, I know... I need
to sit down, take a deep breath, start at the beginning, work
my way through the middle, and eventually stagger my way
to the end. The problem is deciding what to talk about first.
Ah, I can see in your eyes that you are desperate for me
to commence with gamma correction. Well, if you insist...
0 ° P rim ary
330 ° T ertiary
F F
F F
R ose
30 ° T ertiary
0 0 0 0
F lush O range
0 0 8 0
F F
30 0 ° S econdary
F F
8 0 0 0
6 0 ° S econdary
Magenta
0 0 F F
11
10
27 0 ° T ertiary
Electric
I ndigo
Feeling off-colour
R ed
9
0
Y ellow
F F
1
2
F F
0 0
9 0 ° T ertiary
C hartreuse
3
58
B rightness
B rightness
B rightness
8 0 F F 0 0
Way back in the mists of time when we started this mega-mini4
8
8 0 0 0 F F
series (PE, March 2020), we introduced the concept of pulse7
5
6
width modulation (PWM). Since we can turn an LED on and
24 0 ° P rim ary
120 ° P rim ary
off very quickly, the way we control its brightness is to vary
B lue
Green
the proportion of on time to its off time. We refer to this as the
0 0 0 0 F F
0 0 F F 0 0
‘duty cycle.’ A 20% duty cycle means the LED is on 20% of
210 ° T ertiary
150 ° T ertiary
the time and off for the other 80%, while an 80% duty cycle
A z ure
18 0 ° S econdary S pring Green
means the LED is on 80% of the time and off the other 20%.
0 0 8 0 F F
0 0 F F 8 0
C yan
0 0 F F F F
In the case of the microcontroller unit (MCU) we are working
with – the Seeedunio XIAO – we can use values from 0 (0x00
Fig.1. The colour wheel we’ve been using in our experiments.
in hexadecimal) being fully off (0% brightness) to 255 (0xFF
in hexadecimal) being fully on (100% brightness). Using this
I created a quick test sketch (program) to see how this would
PWM technique, a value of 128 (0x80 in hexadecimal) means
affect the colours on my 12×12 array (the full sketch is presented
the LED will be on half of the time and off the other half, rein file CB-Jan21-01.txt – it and the other files associated with this
sulting in 50% brightness.
article, are available on the January 2021 page of the PE website).
In a later column (PE, September 2020), we introduced the
Since the folks at Adafruit were conscious that some of their users
colour wheel (Fig.1) that we decided to use for our 12×12 pingwould be using low-end Arduinos with limited SRAM, they store
pong array experiments (Fig.2). If you have built one of these
their table in PROGMEM (the Flash program memory). By comarrays yourself, or if you are playing with tricolour LEDs in
parison, my Seeedunio XIAO has so much memory that I can
general, you may have noticed that some of the colours seem
afford to flaunt it, so I dispatched the butler to fetch my flauntto be a tad ‘off’. For example, the rose may appear very close
ing trousers and stored my table in SRAM (Fig.3.).
to magenta, while the flush orange may appear more yellow
Previously (PE, October 2020), we met the GetRed(), Getthat one might expect.
Green(), and GetBlue() functions that extract and return the
On the bright side (no pun intended), the red, green, and
8-bit red, green, and blue components from a 32-bit colour value.
blue elements in our tricolour LEDs work as expected and
Also, we introduced the BuildColor() function that accepts 8-bit
provide a linear response such that a 50% duty cycle does
red, green, and blue components and returns a 32-bit colour value.
indeed result in 50% brightness (Fig.2a). The problem is that
The thing is, we have to apply our gamma correction to each
our eyes have evolved to accommodate a huge dynamic range,
of the colour channels individually. Thus, in our new sketch,
from moonlight to sunlight and – as part of this – they have a
we’ve added a GetGammaCorrectedColor() function that
sort of built-in non-linearity (Fig.2b).
accepts a 32-bit colour value, splits it into its red, green and
Although not immediately obvious from my diagram, the
blue components, uses our GammaXref[] look-up-table to
curve of this non-linearity is defined by a somewhat tricky
apply gamma correction to each component, and then returns
power-law function. In order to address this, we need to drive
the gamma-corrected 32-bit result.
the red, green, and blue LEDs using the inverse
of this function, which results in our eyes per10 0 %
ceiving what we were hoping for in the first
W hat our
eyes perceiv e
T he LED
place (Fig.2c). We call the process of applying
W hat our
work s as
eyes perceiv e
ex pected
this inverse function, ‘gamma correction.’
50 %
There’s a great article on Adafruit’s website covering all of this in depth (https://bit.ly/31zaSLK).
H ow the LED
H ow the LED
is driv en
is driv en
As part of this, they provide what they call ‘The
H ow the LED
is driv en
Quick Fix’ in the form of a cross-reference lookP W M
P W M
P W M
0 %
up table that we can use to remap the linear
0 x 0 0
0 x 8 0
0 x F F
0 x 0 0
0 x 8 0
0 x F F
0 x 0 0
0 x 8 0
0 x F F
values we would like to use into their gamma( a) W hat we ex pect to see
( b ) W hat we actually see
( c) A pplying gam m a correction
corrected counterparts that will provide us with
the colours we want to see.
Fig.2. Gamma correction.
Practical Electronics | January | 2021
gammaCorrectedColor = BuildColor(tmpRed,
tmpGreen, tmpBlue);
The idea is that you have two programs fighting each other in
a virtual machine known as the Memory Array Redcode Simulator (MARS). The objective is to be the last program standing. To that end, each program can try to sabotage the other
one and/or try to defend itself by self-repairing. You can get a
really good feel as to what this is all about by reading the Beginner’s Guide to the Redcode pseudo assembly language that
is used to create the warrior programs (https://bit.ly/34m5YUo).
As Ken said in his email, ‘I figure this can be made visually appealing by presenting the memory array on a screen (or
ping-pong ball array) and colour-coding each cell either ‘Neutral,’ ‘Last written for or by Program A,’ or ‘Last written for or
by Program B’ — using green, blue, and red respectively, for
example — and running the programs at only a few steps per
second so progress can be followed.’
Initially, I was a tad skeptical that a 144-element MARS
would suffice but – having looked at the Redcode Beginner’s
Guide – I’ve changed my mind. Now I’m thinking about creating a MARS simulator to run on the Seeeduino XIAO that I’m
using to power my 12×12 array. I’m also thinking about creating a Redcode assembler utility that can generate the warrior
programs to run on the simulator.
But wait, there’s more! Do you remember me talking about
the NeoPixel Simulator that you can use to test your own programs to run on my 12×12 array (PE, November 2020)? Well, if
I manage to find the time to get a MARS simulator up and running, we could combine it with our NeoPixel Simulator, thereby allowing you to create and test your own Code War warrior
programs and then send them to me to be run on the real array.
return gammaCorrectedColor;
Keep your balance
const uint8_t GammaXref[] =
{
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
2,
2,
2,
2,
2,
2,
2,
2,
3,
3,
3,
3,
3,
3,
3,
4,
4,
4,
4,
4,
5,
5,
5,
7,
7,
8,
8,
8,
9,
9,
9, 10,
5,
6,
6,
6,
6,
7,
7,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255
};
Fig.3. Gamma-correction cross-reference look-up table.
uint32_t GetGammaCorrectedColor
(uint32_t uncorrectedColor)
{
uint8_t tmpRed;
uint8_t tmpGreen;
uint8_t tmpBlue;
uint32_t gammaCorrectedColor;
tmpRed = GammaXref[ GetRed(uncorrectedColor) ];
tmpGreen = GammaXref[ GetGreen(uncorrectedColor) ];
tmpBlue = GammaXref[ GetBlue(uncorrectedColor) ];
}
The rest of the sketch is used to load the left-hand side of the array
with uncorrected colours directly from our colour wheel and the
right-hand side with their gamma-corrected counterparts, starting with red at the bottom and ending with rose at the top (Fig.4).
Although it’s not easy to see from this image, in the real
world the gamma-corrected values do present what appears to
be a richer colour palette. For example, the gamma-corrected
orange (second row from the bottom) looks more orange and
the gamma-corrected rose (top row) appears more vibrant.
War, what is it good for?
According to Edwin Starr in his 1970 hit single ‘War’ – and
Frankie Goes to Hollywood more than a decade later – the
answer is ‘Absolutely nothing.’ Of course, it may be that neither
of these luminaries were familiar with the concept of ‘Code War’.
Actually, if the truth be told, neither was I until my chum, Ken
Wood, who has been following these columns, sent me an email
telling me all about this idea. In 1984, Alexander Dewdney wrote
a column in Scientific American magazine about a programming
game called Core War that he had created with DG Jones. A scan
of this original article, along with a lot of supporting material, can
be found on the CoreWars.org website and Wikipedia.
Fig.4. Uncorrected colours
(left) vs. gamma-corrected
colours (right).
Fig.5. 9DOF BoB (Image source:
Adafruit.com)
Practical Electronics | January | 2021
When I was a kid, my parents bought me a wooden marble
maze toy. I just found something quite similar on Amazon
(https://amzn.to/2HwZg4M), although the one I owned had
larger mazes and used smaller ball bearings.
The reason I mention this here is that a reader emailed me
to suggest I attach a sensor to my 12×12 array such that, if the
array is held in a horizontal plane, I could control the ‘rolling’
of a lit pixel by detecting the tilt of the array.
By some strange quirk of fate, I just happened to have one
of Adafruit’s BNO055-based 9DOF (nine degrees of freedom)
Fusion breakout boards (BOBs) in my treasure chest (junk box)
of spare parts (Fig.5) (https://bit.ly/3dP8EwU).
This little beauty is based on a BNO055 microelectromechanical system (MEMS) sensor from Bosch. In turn, the BNO055
contains a 3-axis accelerometer, a 3-axis gyroscope, and a
3-axis magnetometer (they also throw in a temperature sensor
for good measure). The really cool thing about this device is
that it also contains a 32-bit Arm Cortex M0+ processor, which
performs all sorts of mindbogglingly complicated sensor algorithms for you and provides you with data in a form you can
use without your brains leaking out of your ears.
As usual, the folks at Adafruit provide a wealth of information
on this sensor, including pinouts, wiring, and how to download
the required libraries (https://bit.ly/35sVvpz). Also included is
some sample Arduino Code, which I used to create my first test
program. The purpose of this initial sketch was to make sure I
could get my XAIO microcontroller to talk to the BNO055. All
we do is loop around reading the x, y, and z orientation values
from the BNO055 and display them as floating-point values on
the Arduino’s Serial Monitor. Note that the XIAO communicates
with the BNO055 via an I2C bus, which uses pins 5 and 6 on the
XIAO, but we don’t declare these pins in our sketch because
Adafruit’s libraries handle all of this for us (file CB-Jan21-02.txt).
The next step involved some mental gymnastics to visualize
how I was going to mount my breadboard in the 12×12 array
case, and which (sensor) values corresponded to what (left-right
and forward-backward) tilts. Eventually, I determined that the
59
Size does matter!
y values from the sensor would reflect
To paraphrase an old saying, ‘It’s not
tilting the array to the left or right, while
the size of your array, it’s what you do
the z values from the sensor would rewith it that counts.’ In reality, of course,
flect tilting the array to the front or back.
we all know in our heart of hearts that
Thus, my second test program involved
size does indeed matter. If you have two
my taking the floating-point y and z values
people standing next to each other, one
from the sensor and converting them into
clutching a paltry array and the other
integer tilt values for use in my sketch.
staggering under the weight of a garganWith a little manipulation, I ended up
tuan offering, which one do you think
with an integer tiltLeftRight value
the punters are going to be looking at?
that ranges from −90 (tilted left so much
‘Great minds think alike,’ as they say. Of
as to be vertical), through 0 (horizontal),
course, they also say that ‘Fools seldom
to +90 (tilted right so much as to be verdiffer,’ but I’m sure that doesn’t apply to
tical). Similarly, I ended up with an inus. For example, a guy who goes under
teger tiltFrontBack value that ranges
the moniker ‘Bitluni’ created a 20×15 =
from −90 (tilted down to the front – that
Fig.6. The Prognostication Engine’s main
300 ping-pong ball display using tricois, to the user – so much as to be verticontrol panel.
lour LEDs (https://bit.ly/3jmltjj). Somecal), through 0 (horizontal), to +90 (tilted
time later, the attention-grabbing Bitluni
to the back so much as to be vertical). In
We’ve discussed some of the effects
followed up with a 40×30 = 1200 ball
this case, all we do is loop around readwe could employ with the switches and
array (https://bit.ly/31Bv8g0).
ing the y and z orientation values from
pushbuttons in previous columns, so
In an earlier column, when I was buildthe BNO055 and display them as my malet’s now turn our attention to the LEDs
ing my 12×12 array, I noted that if I ever
nipulated integer values on the Arduino’s
associated with the pots.
did this again, I would build 8×8 sub-arSerial Monitor (file CB-Jan21-03.txt).
As an aside, the pots are motorised,
rays and then link them together to form a
Now things start to get more interestso if some unauthorised person were to
larger array. Well, the over-achieving Biting. In our next sketch, we commence
attempt to change the engine’s settings,
luni is of like mind, because he recently
by setting one of the pixels – our ‘ball’
as soon as they go ‘hands-off,’ the pots
created a 48×40 = 1920 ball array using this
– in the center of the array to white. We
will automatically return to their offivery technique (https://bit.ly/3jrwKyV).
then loop around using the readings
cially designated positions under proI can think of so many things we could
from the sensor to make this pixel ‘roll
gram control.
do with such an array. For example, can
around’ in response to tilting the array.
Remember that we are using 16-element
you imagine using a machine vision system
The ‘ball’ stops ‘rolling’ when it hits one
NeoPixel rings from Adafruit (https://bit.
based on artificial intelligence (AI) to
of the sides or gets trapped in one of the
ly/37RtFpQ). In front of each ring (Fig.7a)
detect and recognize gestures as we wave
corners until we tilt the array in the opwe have a brass bezel and an antique
our arms around controlling a wall-size
posite direction (file CB-Jan21-04.txt).
Bakelite knob (Fig.7b). Mounted in the
version of the game Tetris? All I can say
For your delectation and delight, I just
bezel, in front of each pixel, we have a
is that I hope to meet up with the nefaricaptured a short video showing this prosmall pseudo-mother-of-pearl ‘dot’ which
ous Bitluni one day (and appropriate his
gram in action (https://bit.ly/3mXHZS3).
adds to the steampunk look-and-feel.
wall-sized array while he’s not looking).
Of course, this is only the beginning.
Since we have 16 pixels, we can considCurrently, the ‘ball’ simply ‘rolls’ at a coner each as spanning (or representing) an
stant rate once the tilt has passed a certain
arc of 360°/16 = 22.5°. Now, different pots
Prognostication revisited
threshold. The next step will be to add
have different physical ranges for how far
I don’t know if you recall (I can barely
some physics into the mix such that the
they can rotate. The ones I’m using support
remember myself), but this entire saga
speed of the ‘roll’ varies as a function of
rotations of 290°, which means there are
commenced with my wishing to illuthe angle of the tilt.
three pixels to which the pointer on the
minate the controls on my PedagogiAfter that, we are limited, as usual, only
knob cannot, in fact, point (Fig.8).
cal and Phantasmagorical Inamorata
by our own imaginations. For example, we
Of course, although these pixels are
Prognostication Engine. In addition to
could make green ‘food’ pixels randomly
shown as being dark gray in the figure, the
lighting the furnace in the upper conappear on the array and then try to guide
fact that we can’t point to them doesn’t
trol panel and the ginormous vacuum
our rolling pixel to hit them and ‘eat’ them
mean we can’t light them up. One option
tubes sitting on top of the engine, the
before they randomly disappear again. The
would be to simply paint the white line
main control panel features eight toggle
more you ‘eat,’ the more points you get.
and dot on the knob black, and then map
switches and six pushbuttons, each of
Also, we could add red ‘hole’ pixels into
(translate) the 290° rotation of the knob
which is accompanied by two tricolour
which our rolling pixel would ‘fall’ if they
into a 360° range on the ring.
LEDs. Also, there are five potentiometers
were to come into contact (these ‘hole’
However, I like the white line and dot
(pots), each surrounded by a ring of 16
pixels could be stationary, or we could
on the knob. We could just turn the three
tricolour LEDs (Fig.6).
make them randomly
appear and disappear
like the ‘food’ pixels).
We could come up
with all sorts of cool
games based on this
technology if we put out
heads together. Speaking of which, if you
think of anything, please
( a) Neopix el ring f rom A daf ruit
( b ) W ith b ez el and k nob
( a) K nob rotated f ully anticlock wise ( b ) K nob rotated f ully clock wise
drop me an email and
Fig.7. 16-pixel rings.
Fig.8. The rotation of the knob.
share the good word.
60
Practical Electronics | January | 2021
6
1
pixels at the bottom off, but where would
5
7
2
0
W hat we’ v e got
be the fun in that? My solution will be to
8
4
3
15
W hat we want
use a separate colour for these three pixels.
3
9
4
14
New P ix el O ld P ix el
C alculation
Initially this will just be a steady colour, but
0
4
(
0
+ 4 ) % 5= 4
it may be that later we use different colours,
13
2
10
5
1
0
(1+ 4 ) % 5= 1
fades, and flashes on these three pixels to
2
1
(2+ 4 ) % 5= 1
3
2
(3+ 4 ) % 5= 2
provide us with additional information
6
12
1
11
4
3
(4 + 4 ) % 5= 3
about the state of the machine.
11
0
12
7
W hat we’ v e got
The way I want to visualise things is
15
13
8
10
Num b er of pix els - 1
9
14
with pixels 0 and 12 corresponding to
Modulo operator
( a) W hat I want
( b ) W hat I got
the maximum anticlockwise and clockNum b er of pix els
wise rotations of the knob, respectively
Fig.9. You can’t always get what you want.
W hat we want
(Fig.9a). However, the way in which I creFig.10. Thought experiment with 5-pixel ring.
ated my prototype resulted in the pixels
being presented in a different manner (Fig.9b).
Still prognosticating furiously
To be honest, I don’t recall how the rings are oriented on
Although lighting the pixels the way we’ve just done won’t form
the main Prognostication Engine, but it really doesn’t matter
part of the Prognostication Engine’s primary function, it helps
because we are going to perform a simple cross-reference opus to wrap our brains around some of the nitty-gritty details,
eration, and we can easily modify the cross-reference values
and we will be able to use all of this stuff as part of a flamboylater. In the case of our prototype, we will declare our crossant power-up display.
reference values as follows:
In this vein, suppose we want to modify our previous program such that we have only a single pixel lit at any one time.
int RingXref[NUM_NEOS_RING] =
In this case, when we turn our new pixel on, we also want to
{7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8};
turn the previous pixel off. Remembering that we are cycling
the pointer to our pixels, iNeo, from 0 to 15, we would ideThe way this works is really simple, if we want to light what
ally like to modify our core for() loop do something like
we like to think of as pixel i in our imaginary world, we will
the following (the new code is shown in bold):
access RingXref[i], which will return the number of the corresponding pixel in the real world; for example, RingXref[0]
for (int iNeos = 0; iNeos < NUM_NEOS_RING; iNeos++)
will return 7 (tra-la!).
{
So, just to illustrate where we’re at thus far, what we are
// Turn the new pixel on
going to do is create a simple sketch that lights our pixels
tmpNeo = RingXref[iNeos];
from 0 to 15, first red, then blue, then green, then start all
NeosRing.setPixelColor(tmpNeo, tmpColor);
over again. Since these LEDs are so bright, we’re going to add
a ModifyBrightness() function that will dim them down
// Turn the old pixel off
to a specified percentage of their full value, which will allow
tmpNeo = iNeos – 1;
us to keep our original colour definitions as-is. The heart of
tmpNeo = RingXref[tmpNeo];
this program is a function called LightMultiple(), which
NeosRing.setPixelColor(tmpNeo, COLOR_BLACK);
we will call from our loop() function (file CB-Jan21-05.txt).
NeosRing.show();
void LightMultiple (uint32_t thisColor)
delay(InterPixelPadDelay);
{
}
int
tmpNeo;
uint32_t tmpColor;
This would work great for every value of iNeo except 0 because 0 – 1 = –1, which will cause our program to do sometmpColor = ModifyBrightness(thisColor, BRIGHTNESS);
thing excruciatingly painful when we attempt to use this value
as an index into RingXref[]. It’s always the ‘end conditions’
for (int iNeos = 0; iNeos < NUM_NEOS_RING; iNeos++)
that bite you when you are least expecting it. One alternative
{
would be to add a test for this end condition as shown below:
tmpNeo = RingXref[iNeos];
NeosRing.setPixelColor(tmpNeo, tmpColor);
for (int iNeos = 0; iNeos < NUM_NEOS_RING; iNeos++)
NeosRing.show();
{
delay(InterPixelPadDelay);
// Turn the new pixel on
}
tmpNeo = RingXref[iNeos];
}
NeosRing.setPixelColor(tmpNeo, tmpColor);
As you can see, we first modify the brightness of the colour (I’ve
cut things down to only 20% for this experiment, and they are
still bright). Next, we cycle round lighting each of our pixels,
using our RingXref[] to cross-reference the pixel numbers,
upload the new values, and pause for a short delay that we’ve
called InterPixelPadDelay. If you look at the code, you’ll
see that I’ve defined a CYCLE_TIME of one second. Also, I’m
assuming that it takes only 1ms (one millisecond, represented
by CALC_UPLOAD_DELAY) to perform all my calculations and
upload the new values. If you look at the setup() function,
you’ll see how we used these values, along with the number
of pixels in the ring, to calculate the InterPixelPadDelay.
Practical Electronics | January | 2021
// Turn the old pixel off
if (iNeos == 0) tmpNeo = 15; else tmpNeo = iNeos – 1;
tmpNeo = RingXref[tmpNeo];
NeosRing.setPixelColor(tmpNeo, COLOR_BLACK);
NeosRing.show();
delay(InterPixelPadDelay);
}
Now, although this would be a perfectly acceptable solution,
it still feels a bit ‘graunchy,’ if you know what I mean. What I
usually do in this sort of case is perform thought experiments
61
5
6
5
7
10
2
11
1
12
0
15
14
13
( a) Using a single pix el
7
8
9
3
9
3
6
4
8
4
10
2
11
1
12
0
15
14
13
( b ) Using m ultiple pix els
Fig.11. Two ways to reflect the position of the knob.
with pencil and paper. The first thing is to
reduce the scope of the problem to a smaller
number of pixels. Our original ring contains
16 pixels, which is an even number and a
power of two (2^4 = 24). Given a choice,
we want to come up with a generic solution that can work for any number of pixels,
so we will play with a non-power of two.
Furthermore, for this sort of thing, I prefer
an odd number and a prime number on the
basis that, if our solution works for this, it
will work for anything.
So, purely for this thought experiment,
let’s assume that we have a 5-pixel ring. I
start by drawing out a table (Fig.10). My
first column lists what we’ve got (ie, what
we know in the form of the information we
have to hand), which is the number of the
new pixel we’re going to turn on. The next
column lists what we want, which is the
number of the old pixel we want to turn off.
I then dork around with various equations until I come up with a calculation
that satisfies my needs. In this case, a
simple calculation using the modulo operator % satisfies our requirements (this
operator returns the integer remainder
from an integer division). At this point,
I transferred the equivalent over to my
real-world code (file CB-Jan21-06.txt).
Now, our programs thus far have involved lighting our pixels in a clockwise
fashion. Just for giggles and grins, let’s suppose we want to modify our most recent
sketch such that it lights the pixels in a
widdershins (anticlockwise) pattern. Can
you create your own table to determine the
necessary calculation? – you can check
out my solution in file CB-Jan21-07.txt
Turning the knob
Finally, for the moment, let’s consider
how we are going to translate the turning of the knob, which we read via our
potentiometer, into the lighting of the
pixels in our ring. Remember that we’ve
decided not to access the bottom three
pixels, which we will light magenta.
Let’s assume that our On colour will be
yellow and our Off colour will be red. Two
main possibilities immediately spring
to mind. The first is that we could light
a single pixel to indicate the position of
62
Fig.12. Steve Manley’s array of ten 21-segment displays.
the pot (Fig.11a). The second is that we
could light multiple pixels to indicate the
position of the pot (Fig.11b).
You can take a look at my programs for
both of these implementations in files
CB-Jan21-08.txt and CB-Jan21-09.txt, respectively. You will observe that I’ve also
added the gamma correction we introduced earlier into these final two sketches. Also, I just created a short video that
shows all of the effects we’ve discussed
here in action (https://bit.ly/360O2hw).
21-Segment Victorian Displays
Do you remember watching Monty Python
when they said, ‘And now for something
completely different’? Well, hold onto
your hat because here we go.
Way back in 1898 (123 years ago as I
pen these words), someone called George
Lafayette Mason filed a patent for a 21-segment display. These devices used 21 small
incandescent bulbs (one per segment) to
create letters, numbers, and symbols. A
complicated electromechanical switch
could be used to activate various groups
of segments as required to represent the
different characters.
The way I heard about this is that I
have some friends (stop laughing; it’s
true) called Steve Manley and Paul Parry,
where Paul is the owner of Bad Dog Designs (https://bit.ly/2FTSBBk). Paul and
Steve ran across a group called Smartsockets (https://bit.ly/2HOeFhw), which
was founded by Chris Barron and is moderated by Chris and John Smout.
In fact, it was John who came up with
the idea of resurrecting these displays, but
John and Chris are focused on their Smartsocket implementations in which each
display has its own PIC microcontroller.
By comparison, Paul, Steve, and myself
prefer to drive all of our displays with a
single Arduino-compatible microcontroller.
As a result, the two sub-groups are heading in slightly different implementation
directions, although they still communicate what they are doing with each other.
Steve has done a tremendous amount of
work creating the circuit boards and 3D
printed shells for these displays (Fig.12).
Steve, Paul, and I each have ten of these
displays, although I’ve not had the time
to do anything with mine thus far. In fact,
Steve has created a fantastic video that illustrates everything he’s done in exquisite
detail (https://bit.ly/3oJwZcm).
As we see in this image, Steve has used
his 3D printer to make a pseudo-brass faceplate for his display. In my case, Paul introduced me to one of his friends, Kevin
McIntosh. Kevin’s company, the Laser Hut
(https://bit.ly/2Gf8qmg) offers laser cutting
and engraving services, and he’s going to
laser my pseudo-brass faceplates for me. I
will, of course, be documenting all of this
in excruciating detail in future columns.
Coming soon
As I’ve been known to say on occasion,
‘Show me a flashing LED and I’ll show
you a man drooling’ (hence the title of this
miniseries). When we first started discussing the topic of flashing LEDs and drooling engineers (PE, March 2020), I really
had no idea as to the myriad topics into
which we were going to stick our snouts.
In reality, of course, we’ve barely scratched
the surface of this multifaceted topic, but
I hope that the stuff we have covered has
sparked your imagination and tempted
you to toy with your own creations.
In the not-so-distant future, we’re going
to take a break from LEDs and turn our
attention to other topics, but turn that
frown upside down and turn it into a
smile, because that time is not yet come.
Next month, for example, we will be
using our 12×12 array to implement a
version of Conway’s Game of Life – see:
https://bit.ly/pe-jan21-cgol
Until then, as always, I welcome your
questions, comments, and suggestions.
Cool bean Max Maxfield (Hawaiian shirt, on the right) is emperor
of all he surveys at CliveMaxfield.com – the go-to site for the
latest and greatest in technological geekdom.
Comments or questions? Email Max at: max<at>CliveMaxfield.com
Practical Electronics | January | 2021
|