This is only a preview of the July 2024 issue of Practical Electronics. You can view 0 of the 72 pages in the full issue. Articles in this series:
Articles in this series:
Articles in this series:
Articles in this series:
Articles in this series:
Articles in this series:
Articles in this series:
|
Max’s Cool Beans
By Max the Magnificent
Arduino Bootcamp – Part 19
D
o you know what you were
doing at 5:16:20 pm on Saturday, 23 November 1963? I do.
I was six years old, and I was standing bravely (cowering) behind the sofa
with my teddy bear captivated by the
sound of the electronic opening music
accompanying the very first episode of
the British science fiction television
series, Doctor Who. I’ve been a devoted
fan ever since. Why did this just pop
into (what I laughingly refer to as) my
mind? Well…
A gaggle of techno-geeks
There is no official collective noun for
a group of engineers, but two terms I
favour are ‘a sprocket of engineers’ and
‘a rube of engineers,’ where the latter
derives from the American cartoonist,
sculptor, author, engineer and inventor,
Reuben Garrett Lucius Goldberg (a.k.a.
Rube Goldberg). Rube is best known for
his cartoon depictions of complicated
gadgets performing simple tasks in
indirect and convoluted ways.
Fig.1. Electronic component artwork for the
Doctor Who TARDIS (Source: Paul Parry).
50
(a) Flat cut
(b) Bevel cut
Fig.2. A cut above the rest.
As I’ve mentioned before, whenever I
return to England to visit my dear old mom,
on the Friday before I return to America,
a gaggle of my techno-geek friends flock
from across the country. We all meet at the
house of my brother, Andrew, where we
spend a happy day and evening showing
off our latest and greatest creations and
telling tall tales of derring-do. Why do I
mention this here? Well…
Electronic component art
One of the guys who attends our geeky
gatherings is Paul Parry, who is the
founder and owner of Bad Dog Designs
(https://bit.ly/3QsB8kw). Over the
past decade, Paul has captivated and
cultivated a worldwide following for
his Nixie-tube-based timepieces.
More recently, Paul has started a new
line in electronic component-based
artworks (https://bit.ly/4dryK7t). I love
all these creations, but the one that really
caught my eye was that of Doctor Who’s
TARDIS (Fig.1). I have one on order for
when I visit the UK this summer.
Meanwhile, back in America, I meet
up with a group of friends on Tuesday
evenings. We have a light supper and
then watch two episodes of Doctor Who
(we started with the 2005 reboot starring
Christopher Eccleston). These guys are
going to be blown away when I flaunt
my new acquisition.
A handy-dandy tip
In my previous column (PE, June
2024), I remarked on how my friend
Joe Farr has a vast amount of practical
knowledge. I also commented on the kits
of pre-stripped, pre-formed, solid core
jumper wires you can find on Amazon
(https://bit.ly/3vDs2KK).
While we were chatting about ‘this
and that,’ Joe dropped a little nugget
of knowledge into the conversation. He
noted that he always cuts his solid core
jumper wires at a 45° angle if he’s using
them with breadboards (Fig.2). This is
(a) Without insulating tape
(b) With insulating tape
Fig.3. The old insulating tape trick.
because (a) they slide in more easily and
(b) square ends have the potential to
damage the breadboard’s sockets. I tell
you; I learn something new every day!
Seeing red
Joe also taught me another tidbit of
trivia. He says he usually covers the
front of his red light-emitting diode
(LED) 7-segment displays with a piece
of red insulating tape.
I must admit to being surprised. ‘I’m
surprised,’ I said (so it must be true).
I told Joe I’d assumed insulating tape
was opaque. He replied that although
the tape does dim the displays a little,
it also makes the active segments ‘pop.’
I just tried this myself and I see what Joe
means. I’ve tried to replicate this effect in
Fig.3 (only partially successfully, I fear).
The situation without insulating tape is
shown in Fig.3a. In this case, the active
segments are a little brighter, but the
inactive segments still manage to stand
out. By comparison, when the insulating
tape is applied as depicted in Fig.3b,
even though the active segments are a tad
dimmer, the inactive segments become
almost invisible, thereby making their
active counterparts more prominent. Once
again, I learn something new every day!
Resistance is futile!
Toward the end of my previous column, I
showed a picture of my own breadboard
setup with four multiplexed 7-segment
displays presenting the hours and
minutes in HH:MM format. At that time,
I directed your attention to a rinky-dinky
Practical Electronics | July | 2024
Fig.4. Replacing free-standing resistors
with a BOB.
little board in the upper right-hand
corner of my breadboards.
As you may recall, at one stage in our
experiments we had two groups of eight
150Ω current-limiting resistors (this was
before we realised that we needed only
one such group). We started off using
free-standing resistors, as shown in the
upper portion of Fig.4.
In addition to looking untidy, one
problem with having a bunch of resistors
in proximity like this is that it’s easy for
the leads of adjacent resistors to make
unwanted connections with each other. This
can result in annoying issues, especially if
the connections are intermittent.
One solution is to replace the freestanding resistors with dual in-line
(DIL) resistor packages. An example is
provided by the Bourns 4100R Series
(https://bit.ly/4biAmPH). These are
available in different-sized packages with
different numbers and configurations
of resistors. For our purposes here, we
would like a 16-pin package containing
eight isolated 150Ω resistors.
The main problem with this approach
is that the range of resistance values
supported by the Bourns 4100R Series
(and similar offerings from other
manufacturers) is limited.
A cheap-and-cheerful alternative is
to build our own breakout board (BOB)
carrying eight discrete 150Ω resistors, as
shown in the middle of Fig.4. In addition
to preventing any leads shorting, using
BOBs like this makes it easy to replace
one group of resistors with another,
which is something we may well be
doing a lot of in the not-so-distant future
(I feel like an oracle… but where are we
going to find one at this time of the day?).
Building a BOB
As an aside, I have more than my fair
share of friends called Bob. When I’m
Practical Electronics | July | 2024
talking to my wife (Gina the
Gorgeous), I need to qualify
which Bob is the topic of
discussion, so I call them
Bible Bob, Carpenter Bob,
Sparkly Bob... I recently ran
(a) Saw between holes
(b) Score and snap through holes
across a science fiction book
called We Are Legion (We Are
Bob). I had to buy this book Fig.5. Preparing the BOB board.
just for the title. It was only
board to the header pins at the same time.
after it had arrived that I discovered it’s
Fight this temptation with all your might.
an awesome story. And I’m not the only
If you do solder them simultaneously,
one who thinks so because this tome
there’s more than a batting chance the
has 4.5 stars with 24,000+ ratings on
solder won’t wick (get sucked through)
Amazon (https://bit.ly/3wsnoiQ).
the via all the way to the other side. In
But we digress. To build our BOB,
turn, when you eventually plug your
we will need to start with a piece of
BOB into your project’s breadboard,
board. One contender is stripboard
the header pins may separate from the
(https://bit.ly/3JLtbTJ), but this would
BOB (sad face).
require us to cut tracks using a knife or
Thus, our first task is to solder the
a special stripboard track cutting tool
board to the header pins (Fig.6a). Use
(https://bit.ly/3UprIYh). In this case,
a hot soldering iron and hold it on each
however, I opted for a piece of prototyping
joint long enough for the solder to wick
board (https://bit.ly/3UMkcZ1).
all the way through the via (remember
Now we have another choice. We can
we talked about soldering, along with
either use a fine-toothed hacksaw to cut
Alan Winstanley’s handy-dandy Basic
our board between the holes (Fig.5a),
Soldering Handbook, in PE, March 2024).
or we can use a utility knife to score
When it comes to attaching the
lines through the holes and then snap
resistors, you have another decision to
the board along these lines (Fig.5b). In
make because there are various ways to
my case, I opted for the latter solution
do this. Joe comes from a prototyping
because I happened to have a utility
background where things often need to
knife in my pocket whilst my hacksaw
be reworked. Based on this, he favours
was hiding in the tool chest in the garage
simply bending the resistor leads at 45°
(thus are our decisions made).
angles, soldering them to the pins, and
We’re also going to need cut two
cutting off any excess lead (Fig.6b). The
8-pin pieces of the same long-tailed
advantage of this approach is that it’s
(0.1-inch pitch) header pins we used
easy to desolder things if required later.
to create the breadboard power LED
By comparison, I tend to come from
assemblies in our previous column
a more mission-critical and safety(https://bit.ly/3U1Vp2z). Stick these 8-pin
critical background where ‘Failure is
header pin strips into an old breadboard
not an option.’ Based on this, I tend to
mounted four holes apart. The reason
overengineer things, such as twisting the
for using an old breadboard is that we
leads through a full 360° circle (Fig.6c).
are about to do some soldering. Bits of
The downsides to this approach are
solder and fragments of wire can fall
that it’s easier to create solder bridges
into the breadboard’s holes, so we will
between adjacent pins (because the joints
want to reserve this board for soldering
are bigger) and it’s harder to rework the
and similar non-active activities in the
BOB later. The upside is that these solder
future. This means it would be a good
joints are not going to fail anytime soon.
idea to mark ‘Do Not Use’ on this board
Just to make sure we’re all up to date,
for future reference.
I’ve added this BOB to the drawing
Now, this next part is important, so
of the latest and greatest incarnation
sit up and pay attention. You may be
of our prototyping platform (file
tempted to solder the resistors and the
CB-Jul24-01.pdf). As usual, all the files
(a) Solder
header pins
(b) Bend legs
at 45°
(c) Twist legs through 360°
(a step too far? )
Fig.6. Adding the resistors to the BOB board..
51
No connection
C onnection
D3
Display segments
and pin numbers
G round (0V )
D2
Set New Segment Value → Turn Transistor T0 On → Wait 2ms → Turn Transistor T0 Off
Set New Segment Value → Turn Transistor T1 On → Wait 2ms → Turn Transistor T1 Off
Set New Segment Value → Turn Transistor T2 On → Wait 2ms → Turn Transistor T2 Off
Set New Segment Value → Turn Transistor T3 On → Wait 2ms → Turn Transistor T3 Off
:
(b)
Set New Segment Value → Set 2:4 Inputs to 00 → Wait 2ms
Set New Segment Value → Set 2:4 Inputs to 01 → Wait 2ms
Set New Segment Value → Set 2:4 Inputs to 10 → Wait 2ms
Set New Segment Value → Set 2:4 Inputs to 11 → Wait 2ms
:
May result in
“Ghosting” on
old display
(c)
Set 2:4 Inputs to 00 → Set New Segment Value → Wait 2ms
Set 2:4 Inputs to 01 → Set New Segment Value → Wait 2ms
Set 2:4 Inputs to 10 → Set New Segment Value → Wait 2ms
Set 2:4 Inputs to 11 → Set New Segment Value → Wait 2ms
:
May result in
“Ghosting” on
new display
(d)
en = 0 → Set 2:4 Inputs to 00 → Set New Segment Value → en = 1 → Wait 2ms
en = 0 → Set 2:4 Inputs to 01 → Set New Segment Value → en = 1 → Wait 2ms
en = 0 → Set 2:4 Inputs to 10 → Set New Segment Value → en = 1 → Wait 2ms
en = 0 → Set 2:4 Inputs to 11 → Set New Segment Value → en = 1 → Wait 2ms
:
(e)
Turn All Segments Off → Set 2:4 Inputs to 00 → Set New Segment Value → Wait 2ms
Turn All Segments Off → Set 2:4 Inputs to 01 → Set New Segment Value → Wait 2ms
Turn All Segments Off → Set 2:4 Inputs to 10 → Set New Segment Value → Wait 2ms
Turn All Segments Off → Set 2:4 Inputs to 11 → Set New Segment Value → Wait 2ms
:
5 10 9 1 2 4 6 7
D0
D1
(a)
DP G F E D C B A
3
3
3
3
C
C
C
C
B
B
B
E
E
13
B
E
11
12
E
10
9 8 7 6 5 4 3 2
Arduino pin numbers
Fig.7. Current circuit with four 7-segment displays.
In a crunchy nutshell, the question
posed by James the inquisitor can be
summarised as follows: ‘Why don’t we
use a 2:4 decoder to drive the transistors,
thereby freeing up two of the Arduino’s
digital I/Os?’
That’s a good question. Remembering
that I’m only ever an email away, I’m
surprised you haven’t presented this
poser yourself. Using a 2:4 decoder (we
read this as ‘two-to-four decoder’) is
certainly a possibility, although there are
some considerations to… well, consider.
On the off chance this function is new to
you, let’s start by considering what we
mean by a 2:4 decoder in the first place.
The idea is to create a logic function
that has two inputs and four outputs.
The inputs, which we will drive using
our Arduino, have 2 2 = 4 possible
combinations: 00, 01, 10, and 11.
We want to use each of these input
combinations to select one of our four
possible outputs, which we will use to
control the transistors that control our
displays. Furthermore, in the case of our
current circuit, we require ‘active high’
outputs, which means their active state
is 1 and their inactive state is 0. This is
due to the way we have things wired,
whereby a 1 will turn the corresponding
transistor on. Remember, we want only
one transistor (and thus one display) to
be active at a time.
It may (or may not) be worth noting
that our hypothetical 2:4 decoder can be
thought of as implementing a ‘one hot’
mentioned in this column are available
from the July 2024 page of the PE website:
https://bit.ly/pe-downloads
Why don’t we…
I received an interesting email from
a reader we will call James (because
that’s his name). James had a question
regarding our current circuit (Fig.7). As
you will recall, in the present incarnation
of our clock, we are using eight of our
Arduino’s digital input/output (I/O) pins
to drive the display segments, with all
four displays connected in parallel (sideby-side). Also, we are using four digital
I/O pins to control the transistors we use
to activate the displays. This means we
are using 12 digital I/Os in all.
As we’ve previously noted, the
Arduino Uno has only 14 digital I/O pins
(remember that we aren’t considering
the 6 analogue pins, which can also
be used as digital I/Os, because we
are holding them in reserve for a later
date). Also, we aren’t using digital I/Os
0 and 1 because these are reserved for
communications between the Arduino
and the host computer.
So, the situation we find ourselves in
is (a) the Arduino Uno has 12 digital I/Os
available to us and (b) we are using all
of them to drive our four displays. This
means we don’t have any digital I/Os
free to implement other functions, like
driving our piezoelectric buzzer, for
example (we introduced this component
in PE, December 2023).
s1 s0
y3 y2 y1 y0
0
0
0
0
0
1
0
1
0
0
1
0
1
0
0
1
0
0
1
1
1
0
0
(a) Truth table
Fig.9. Alternative control scenarios.
s1
s1
y3
F rom s1
Arduino s0
2:1
y2
y1
y0
0
(b) Symbol
s0
T o transistors
s0
y3
&
y2
&
y1
&
y0
(c) G ate-level implementation
Fig.8. 2:4 decoder with active-high outputs (driving 4 displays).
52
&
code in that only one of the four outputs
is ‘hot’ (active) at any time.
Based on the functional specification
we just established for our 2:4 decoder,
we can create a truth table (Fig.8a),
a symbol (Fig.8b), and a gate-level
implementation (Fig.8c), where s stands
for ‘select’ and y stands for ‘output.’
In this case, we are using two NOT
(inverter) gates and four 2-input AND
gates. You can find a quick refresher
on the truth tables and functioning of
NOT, AND, NAND and XOR gates in my
Cool Beans Blog on the C/C++ bitwise
operators (https://bit.ly/3UqT9B6). A
more in-depth discussion is provided in
my book Bebop to the Boolean Boogie
(https://bit.ly/4a6wDDm).
So, in the case of our current fourdisplay clock, we now have a choice
between not using a 2:4 decoder and
having no free digital I/Os or using a 2:4
decoder and having two free digital I/Os.
As a slight aside, if we ever decide
we want to drive anywhere from five to
eight displays, the way we are currently
implementing things would leave us with
no choice but to use a 3:8 decoder (three
inputs and eight outputs), which would
still leave us with one free digital I/O.
Seeing ghosts
Remember that we are just spitballing
ideas here. We aren’t really going to
deploy a 2:4 decoder, but it’s well worth
taking the time to cogitate and ruminate
over the implications if we were to do so.
Your knee-jerk reaction might be that
using a 2:4 decoder as discussed above
would be easy peasy lemon squeezy.
Hold hard! Not so fast! Remember
that I said there were considerations
to consider. Take a moment to think
about (a) our gate-level implementation
and (b) how we might use the Arduino
to drive the inputs to the decoder. Can
you envisage any potential problems?
Practical Electronics | July | 2024
s
y1 y0
0
0
1
1
1
0
s
1:2
y1
y0
(b) Symbol
(a) Truth table
s
y0
d0
d1
y1
y0
s
(c) Gates
y1
d0
d1
(d) Waveforms
Fig.10. 1:2 decoder with active-high outputs
(driving 2 displays).
Hold onto your hat because I’m about
to make your head spin and your brain
wobble on its gimbals. Let’s start by
reminding ourselves that the way
our program is driving our existing
circuit can be summarised as shown in
Fig.9a (observe we are using the twomillisecond (2ms) on/active time for
our displays that we settled on in our
previous column).
The key point with respect to our
existing implementation is that it’s
possible for us to turn all the transistors
off at the same time. Now consider our
2:4 decoder-based solution. In this case,
there will always be one of our displays
that’s active.
In the context of this column, the term
‘ghosting’ refers to our trying to display
two values too closely together on the
same display, one for a longer time
(the desired value) and one for shorter
duration (the fainter, ‘ghost’ value).
For the moment, let’s assume that we
are always driving our segments with
on/off values associated with one of the
digits 0 through 9. In this case, we have
two options. We could set the segments
to their new values and then set the 2:4
decoder’s inputs to their new values
(Fig.9b), but this may result in ghosting
on the old display. Alternatively, we
could set the 2:4 decoder’s inputs to their
new values before setting the segments
to their new values (Fig.9c), but this may
result in ghosting on the new display.
Could things get worse? You betcha!
One at a time
The way we’ve been thinking about
things based on the truth table in Fig.8a
and the sequences discussed in Fig.9b
and Fig.9c is that the inputs to our 2:4
decoder will transition as follows: 00,
01, 10, 11, 00… In turn, this means we
are activating our displays in the order
D0, D1, D2, D3, D0…
Unfortunately, this leads us to fall
into the trap of thinking that both
inputs to our 2:4 decoder will change
simultaneously. Thus far, however, we’ve
learned how to change only one of our
Arduino’s digital outputs at a time.
Practical Electronics | July | 2024
What are the implications of this?
Well, suppose that s1 = 0 and s0 =
1, which means display D1 is active.
Now suppose we wish to deactivate
display D1 and activate display D2.
This means we want s1 = 1 and s0 =
0. To put this another way, we want
the s1-s0 inputs to our 2:4 decoder
to transition from 01 to 10. One way
to achieve this would be to use the
following statements:
digitalWrite(S0, 0);
digitalWrite(S1, 1);
Unfortunately, this means the inputs to
our 2:4 decoder would now follow the
sequence 01, 00, 10, which means we
would be driving our displays in the
order D1, D0, D2.
Alternatively, we could swap the order
of our statements to read as follows:
digitalWrite(S1, 1);
digitalWrite(S0, 0);
In this case, the inputs to our 2:4 decoder
would follow the sequence 01, 11, 10,
which means we would be driving our
displays in the order D1, D3, D2.
Either way, we may now experience
ghosting on two displays (let’s call this
‘double ghosting’) rather than one (our
original ‘single ghosting’ scenario),
which means things are going from
bad to worse.
Happily, there are two ways around
this problem that immediately spring to
mind. The first relies on the fact that it
doesn’t really matter in which order we
activate our displays, just so long as we
follow the same sequence repeatedly. So,
rather than feeding the inputs of our 2:1
decoder with the binary sequence 00,
01, 10, 11, 00… (D0, D1, D2, D3, D0…),
in which multiple bits change on the 01
to 10 and 11 to 00 transitions, we could
instead use a Gray code sequence (named
after Frank Gray), such as 00, 01, 11, 10,
00… (D0, D1, D3, D2, D0…), in which
only one bit changes at a time.
An alternative solution relies on the
fact that there is a way by which we
can change multiple Arduino outputs
simultaneously (although we don’t want
to get into that here). However, we would
still have our original ‘single ghosting’
problem, and neither of these techniques
would protect us from another potential
‘gotcha’ resulting from gate-level delays.
Don’t delay
We often fall into another trap – that
of thinking our primitive logic gates
switch instantaneously. In the real world,
however, there’s always some element of
delay. Just to make things a little simpler,
let’s perform a thought experiment. Let’s
imagine we have only two displays and
consider the signals associated with a
1:2 decoder implemented using two
NOT gates (Fig.10).
As we see, due to the delays associated
with the NOT gates, there’s a period
when both the output signals are 1,
which means both the displays will be
activated at the same time. The same
thing will apply to our 2:4 decoder
(and a 3:8 decoder if we decided to
use one); that is, there will be short
periods where multiple displays are
active simultaneously.
With respect to our earlier ghosting
examples (both ‘single ghosting’ and
‘double ghosting’), only one display was
active at any time. In this case, however,
we really do have multiple displays
active simultaneously. This means that,
in addition to a new form of ghosting,
our Arduino’s pins will have to drive
twice the expected current.
Since we are talking about multiple
outputs being simultaneously active for a
duration of only a few nanoseconds due
to this gate delay scenario, would either
of the associated ghosting and current
issues really be a problem? Probably not.
On the other hand, I think it behooves us
to engineer things in such a way that such
a situation never occurs in the first place.
Adding an enable
There are two relatively simple solutions
that will address both our sequencing
and our gate-delay-induced problems.
First, we could add an en (‘enable’) input
to our 2:4 decoder. This signal would be
controlled by our Arduino. In this case,
let’s say that if en is 0, all our outputs
will be forced to their 0 (inactive) states.
It’s only when en is 1 that the selected
output will be 1. The truth table, symbol,
and gate-level implementation of this
new incarnation of our 2:4 decoder
function are shown in Fig.11.
In the case of the truth table (Fig.11a), X
represents a ‘Don’t Care’ state. Thus, we
read the first row of this table as: ‘When
en = 0, we don’t care what values are
presented to s1 and s0 because we are
going to force all the outputs to 0.’ We
read the remaining rows as: ‘It’s only
when en = 1 that we use the values on
s1 and s0 to activate one of our outputs.’
Having this enable signal allows us
to use the control sequence presented
in Fig.9d. This solution addresses all
the ghosting and over-current issues
we introduced earlier. However, there’s
a fly in the soup and an elephant in the
room (I never metaphor I didn’t like).
Remember that we started off using 4
of the Arduino’s pins to directly drive
our transistors. Then we moved to using
only 2 of the Arduino’s pins to drive
our 2:4 decoder, which freed up 2 pins,
but caused us to run into ghosting and
other issues. By adding the enable to
53
implementation shown in Fig.8c. To
do this, we will need a hex inverter
y3
&
s1
in the form of an SN7404 (Fig.13a)
0 X X
0 0 0 0
y3
y2
&
and a quadruple 2-input AND in
1 0 0
y2
0 0 0 1
F rom s 1
To
s0
2:1
y1
&
Arduino s 0
the form of a SN7408 (Fig.13b).
1 0 1
0 0 1 0
y1 T ransisto rs
s0
Both these devices are available in
1 1 0
0 1 0 0
y0
y0
&
14-pin breadboard-mountable dual
1 1 1
1 0 0 0
en
en
in-line (DIL) packages. You can also
(a) T ruth Table
(c) G ate-level implementation
(b) S ymbol
access downloadable data sheets:
7404 (https://bit.ly/44Rs3bb) and
Fig.11. 2:4 decoder with active-high enable and active-high outputs.
7408 (https://bit.ly/3UwuCKV) on
the interweb.
You can order these chips individually
means we can turn them all off before
the 2:4 decoder, we are now using 3 of
if you wish, or you could opt for a
we modify the values on the inputs to
the Arduino’s pins, leaving only 1 pin
small kit containing two each of the
our 2:4 decoder. When all the segments
free, which prompts us to ask, ‘Is all
ten most popular 74LS devices, such as
are off, it doesn’t matter if we transition
this worth the effort?’
the Bridgold set on Amazon (https://bit.
through intermediate input values or if
The answer to this question is, ‘It
ly/3wqgzyv). Note that the ‘LS’ portion
the decoder’s gate delays cause multiple
all depends.’ If having a free pin is
of their monikers stands for ‘low-power
transistors to be activated, because all we
mission-critical and this is the only
Schottky,’ but that’s not something we
are displaying is… a blank. This means
way to get it, then the answer would
need to concern ourselves with here.
that if we were to add a 2:4 decoder to
be ‘Yes.’ Otherwise, we might have to
The plastic packages typically have
our current circuit, we would employ
think about living without the decoder.
a small semicircular notch at one end
the sequence depicted in Fig.9e.
between pins 1 and 14 as shown in
Now, you may be thinking that our
Drawing a blank
Fig.13. Alternatively, they may have a
rambling 2:4 decoder discussions serve
Are you drawing a blank with respect
dimple next to pin 1. Either way makes it
no purpose, to which I would respond:
to the second solution that will address
easy to determine which pins are which.
(a) it’s all curious James’s fault for asking
both our sequencing and our gate-delayN e x t , l e t ’s u s e t h e g a t e - l e v e l
the question in the first place and (b)
induced problems? If so, that would
implementation from Fig.8c and our
you may be surprised how the problems
be ironic, because ‘drawing a blank’
knowledge of the chip pins from Fig.13
and solutions we’ve talked about here
is the solution.
to create a schematic (Fig.14).
pop up again in the future.
Let us now return to our current
It’s common to use the character ‘U’
implementation, but we’ll assume it’s
to indicate an integrated circuit in a
What the heck!
been augmented with a simple 2:4
schematic (we are saying that U1 is our
I fear that I can no longer be trusted.
decoder (without an enable) as illustrated
SN7404 and U2 is our 7408). In the case
Why? Well, earlier I said that we were
in Fig.12 (observe that we now enjoy
of this sort of logic, sometimes we might
just spitballing ideas and we weren’t
two free pins).
show the entire package as a single
really going to deploy a 2:4 decoder.
Do you remember earlier when we said:
symbol. Other times we may show the
However, looking at Fig.12 has given me
‘For the moment, let’s assume that we are
individual gates, in which case we add a
an uncontrollable urge to do just that.
always driving the segments associated
number or letter to indicate which gate
I just glanced at my trusty Texas
with one of the digits 0 through 9.’ I’m
in the package we are talking about (eg,
Instruments TTL Data Book (Second
afraid this was a bit of a hareng rouge
U2.1 is the gate in the 7408 with signals
Edition) from 1981 – a classic, do yourself
(‘red herring’).
1A, 1B, and 1Y; U2.2 is the gate with
a favour and get one. The SN74139
As we know, we currently have
signals 2A, 2B, and 2Y; etc.). The pin
is a 16-pin device containing two 2:4
total control of all the segments. This
numbers provide a further clue.
decoders, and they
Now, let’s add these devices to our
even have enables
Displ ay segments
No connection
G round (0V )
C onnection
breadboard-based clock (Fig.15) and wire
if we wanted to use
and pin numbers
them up as per our schematic (Fig.14).
them, but they have
I’ve updated our master drawing to reflect
active low outputs,
these changes (file CB-Jul24-02.pdf).
which is opposite to
We will talk about the four unexpected
what we want.
5 10 9 1 2 4 6 7
D3
D2
D0
D1
resistors in a moment, but first…
Also, it will be
Sometimes when you look at a gatemore fun to replicate
DP G F E D C B A
level schematic of a circuit board like
the gate-level
s1
en s 1 s 0
y3 y2 y1 y0
3
3
3
3
C
C
C
C
B
B
E
B
E
B
E
(+5V ) (+5V )
V CC V6A
CC
6A
6Y
6Y
5A
5A
5Y
5Y
4A
4A
4Y
4Y
(+5V ) (+5V )
V CC V4B
CC
4B
4A
4A
4Y
4Y
3B
3B
3A
3A
3Y
3Y
14
13
12
12
11
11
10
10
9
98
8
14
13
12
12
11
11
10
10
9
98
8
&
&
&
&
14
13
14
13
E
&
y3 y2 y1 y0
&
&
&
2:1
s1 s0
F ree
13 12
9 8 7 6 5 4 3 2
11 10
Arduino pin numbers
Fig.12. Current circuit augmented by 2:4 decoder.
54
1
12
23
34
45
56
1A
1A
1Y
1Y
2A
2A
2Y
2Y
3A
3A
3Y
(a) SN7404
(a) SN7404
7
1
12
23
34
45
56
G3Y
ND G ND
(0V ) (0V )
67
1A
1A
1B
1B
1Y
1Y
2A
2A
2B
2B
2Y
67
7
G2Y
ND G ND
(0V ) (0V )
(b) SN7408
(b) SN7408
Fig.13. Chip packages.
Practical Electronics | July | 2024
4
Connection
6
&
5
No connection
y3
U2.2
1
From
Arduino
3
&
2
U2.1
5
12
6
y2
To transistors
11
&
13
U1.3
s0
P in 10
1
U1.1
s1
Pin 11
2
y1
U2.4
10
U1 = 7404
U2 = 7408
8
&
9
y0
U2.3
Fig.14. Gate-level schematic for 2:4 decoder.
D3
D2
D1
To displays
D0
7408
7404
11 (s1) 10 (s0)
From Arduino
Listing 3a. Modifications to use 2:4 decoder.
Fig.14, you wonder as to the rationale
behind the way in which the designer
selected which gates in which chips
were to be connected to which wires.
Why did I use U2.3, U2.4, U2.1, and
U2.2 to drive signals y0, y1, y2, and
y3, respectively, for example?
Oftentimes, the answer is more
pragmatic than you might expect – it
facilitates the physical layout in some
way. In this case, I wanted to be able
to draw the wires associated with our
chips in such a way that they didn’t
cross over, which would have made
things harder for you to comprehend.
Feeling unconnected?
One final point worth noting before we
fire up our new implementation is that
we are using only two of the six inverters
(NOT gates) in our SN74LS04 package.
In a real-world design intended for
production, we would typically use pullup or pull-down resisters to connect any
unused input pins to power or ground,
respectively (Fig.16).
Why? Well, there’s a faint possibility
that an unconnected input, which may
‘float’ up and down, could result in
that NOT gate undergoing uncontrolled
oscillations, and an oscillating gate
consumes power. Also, even though
Practical Electronics | July | 2024
Fig.15. Wiring up the chips on the breadboard.
the outputs on our unused gates aren’t
connected to anything via wires, such
oscillations may result in noise in the
form of electromagnetic interference
(EMI) that can affect other signals nearby.
Happily, the chances of this being
a problem are extremely slight in our
case, not least because of the SN74LSxx
technology we are using. On the other
hand, I’m trying to teach you good
practices, and it’s a good idea to get
into the habit of tying off unconnected
inputs, so that’s what we are going to do.
In a scenario where gates are totally
unused, as in our example, it’s often up to
the designer to decide between attaching
pull-up or pull-down resistors to their
inputs (remember that they are the same
resistors; the ‘up’ and ‘down’ qualifiers
are used to remind ourselves what we are
doing with them). In this case, I favour
using pull-down resistors to ground.
Also, it’s usually the designer’s
choice as to the value of resistors to
use. Anything 1kΩ or higher is typically
good. I personally favour 10kΩ resistors
(brown-black-orange). I have friends
(seriously) who opt for 2.2kΩ (red-redred) or 4.7kΩ (yellow-purple-red). In the
case of a cheap-and-cheerful prototype,
you may end up using whatever you
have to hand.
In some situations, we may be using
a gate or a more complex function, but
not employing all its inputs. In such
cases (unless stated otherwise in the
data sheet), it’s imperative that we apply
appropriate resistors to place these pins
in appropriate states. If we are using
only two inputs to a 3-input AND gate,
for example, we would use a pull-up
resistor on the unused input (a pulldown would force the AND’s output to
(+5V )
V CC
14
6Y
13
12
1
2
3
1A
1Y
s1 s1
5Y
11
10
4Y
9
8
4
5
6
7
2Y
3A
3Y
G ND
(0V )
s0 s0
Fig.16. Unconnected inputs connected to
ground via pull-down resistors.
55
0). Alternatively, if we are using only two inputs to a 3-input
OR gate, we would use a pull-down resistor on the unused
input (a pull-up would force the OR’s output to 1).
Let’s rock and roll!
I just forked the latest and greatest program from our previous
column (PE, June 2024), edited it, and made it available for
your perusing pleasure (file CB-Jul24-03.txt).
Let’s skim through the minor changes before we look at
the tasty part. We’ve removed our TRAN_ON and TRAN_OFF
definitions because we are no longer driving the transistors
directly. Similarly, we’ve replaced our PinsTrans[]
array in which we specified the four pins used to drive
our transistors with two independent definitions for our
decoder select controls:
int PinS0 = 10;
int PinS1 = 11;
There are a few more minor tweaks of this ilk, but the big
change takes place in our loop() function, as illustrated in
Listing 3a.
To be honest, apart from the line numbers themselves,
the statements associated with Lines 71 through 89 remain
unchanged. The only new part takes place when we come to
output our HH:MM data to the displays in Lines 92 through 99.
What we are doing is implementing the sequence shown
in Fig.9e: Turn all segments off (Line 94) → Set 2:4 inputs
(Lines 95 and 96) → Set new segment values (Line 97) →
Delay 2ms (Line 98).
Most of this is achieved by reusing and reordering statements
we’ve seen before. The only new part occurs on Lines 95
and 96 when we set the 2:4 input signals. To understand
this, we first need to remind ourselves that we previously
made the decision to activate our displays in the sequence
D0, D1, D2, D3 (we could have done it the other way round,
but this was easier).
To achieve this with our new circuit, we want the s1-s0
signals driving the inputs to our 2:4 decoder to follow the
sequence 00, 01, 10, 11 (Fig.8a, Fig.14, and Fig.15).
As part of our for() loop declaration on Line 92, our integer
iDisp variable cycles through the values 0, 1, 2 and 3. In the
case of the Arduino Uno, variables of type int (integer) are
16 bits wide. Let’s consider the binary values of the leastsignificant eight bits in the context of our counting sequence
(the most-significant eight bits will all be 0s).
iDisp
0
≡
1
≡
2
≡
3
≡
Binary
00000000
00000001
00000010
00000011
The math symbol ≡ means ‘equivalent to’ or ‘identical to.’
We discussed how to use the bitwise operators as masks in a
previous Cool Beans (PE, March 2021). These are the techniques
we are using here. Consider the following portion of Line 95:
iDisp & B0000001
Components from Part 1
LEDs (assorted colours)
https://amzn.to/3E7VAQE
Resistors (assorted values)
https://amzn.to/3O4RvBt
Solderless breadboard
https://amzn.to/3O2L3e8
Multicore jumper wires (male-male) https://amzn.to/3O4hnxk
Components from Part 2
7-segment display(s)
https://amzn.to/3Afm8yu
Components from Part 5
Momentary pushbutton switches
https://amzn.to/3Tk7Q87
Components from Part 6
Passive piezoelectric buzzer
https://amzn.to/3KmxjcX
Components for Part 9
SW-18010P vibration switch
https://bit.ly/46SfDA4
Components for Part 10
Breadboard mounting trimpots
https://bit.ly/3QAuz04
Components for Part 12
Light-Dependent Resistor
https://bit.ly/3S2430m
Components for Part 13
BC337 NPN Transistor
https://bit.ly/40xAgyS
Components for Part 14
HC-SR04 Ultrasonic Sensor
https://bit.ly/49AMBq4
Components for Part 15
Real-Time Clock (RTC)
https://bit.ly/3S9OjHl
Components for Part 18
Long tailed (0.1-inch pitch)
header pins
https://bit.ly/3U1Vp2z
Components for Part 19
Prototyping boards
Kit of popular SN74LS00 chips
https://bit.ly/3UMkcZ1
https://bit.ly/3wqgzyv
What this means is that this operation will return 00000000
(0) when iDisp is 0 or 2, and 00000001 (1) when iDisp is
1 or 3. Remembering that 0 and 1 are equivalent to LOW and
HIGH, respectively, these are the values we are writing to our
2:4 decoder’s s0 input.
Now consider the following portion of Line 96:
(iDisp >> 1) & B0000001
This starts by using the >> bitwise shift right operator to shift
the value from iDisp one bit to the right (again, this doesn’t
modify the value stored in iDisp because we aren’t assigning
anything to iDisp). The original least-significant bit ‘falls
off the end’ and a 0 is shifted into the new most-significant
bit. What this means is that, following the >> operation, we
have the following intermediate value to play with:
iDisp
0
≡
1
≡
2
≡
3
≡
Binary after >> 1
00000000
00000000
00000001
00000001
Since we are using a bitwise & (AND) operator, any 0s in our
When we subsequently perform the bitwise & (AND) operation,
Bxxxxxxxx value will return 0s in the corresponding positions
we will see 00000000 (0) when iDisp is 0 or 1, and 00000001 (1)
in the result. By comparison, any 1s in our Bxxxxxxxx value
will return whatever 0 or 1 value
is in the corresponding bit of
Cool bean Max Maxfield (Hawaiian shirt, on the right) is emperor of all he
iDisp (note that this doesn’t
surveys at CliveMaxfield.com – the go-to site for the latest and greatest
modify the contents of iDisp
in technological geekdom.
because we aren’t assigning
Comments or questions? Email Max at: max<at>CliveMaxfield.com
anything to iDisp).
56
Practical Electronics | July | 2024
when iDisp is 2 or 3, and these are the values we are writing
to our 2:4 decoder’s s1 input.
There are a couple of things to note here. The first is that
the following two statement return identical results:
(iDisp >> 1) & B0000001
iDisp >> 1 & B0000001
This is because the >> (bitwise shift) operator has a higher
precedence than the & (bitwise AND) operator (for further
details on this, I recommend C/C++ Operator Precedence
at: https://bit.ly/3wH8w06). Personally, I prefer to use ( )
parentheses to (a) force the precedence I want and (b) to make
it clear what I expect to occur to anyone reading my code
(including me) in the future.
The second point is that we don’t really need to perform the
shift at all. For example, although the following statements
return different results, these values will result in the same
action in the context of our program:
(iDisp >> 1) & B0000001
iDisp
& B0000010
This is because the digitalWrite() function will set the
output to 0 (off, LOW) if it is presented with a value of 0 (zero),
and it will set the output to 1 (on, HIGH) if it is presented
with any other (non-zero) value of 1 or more.
I just ran our new program, and… ran into a WTW (‘what
the what?’) problem with one of my breadboards. I’ll tell you
about this in my next column. Suffice it to say that, once I’d
sorted my wayward breadboard, our 2:4 decoder-based clock
performed like a dream (happy dance).
Online resources
For the purposes of this series, I’m going to assume
that you are already familiar with fundamental concepts like voltage, current and resistance. If not, you
might want to start by perusing and pondering a short
series of articles I penned on these very topics – see:
https://bit.ly/3EguiJh
Similarly, I’ll assume you are no stranger to solderless breadboards. Having said this, even if you’ve used
these little scamps before, there are some aspects to
them that can trap the unwary, so may I suggest you
feast your orbs on a column I wrote just for you – see:
https://bit.ly/3NZ70uF
Last, but not least, you will find a treasure trove of
resources at the Arduino.cc website, including example programs and reference documentation.
Next time…
I’m afraid I’ve told two untruths (my mother won’t be happy).
As you may recall, at the end of our previous column, I
said: ‘In our next column, we really and truly are going to
refresh our minds as to the concept of binary-coded decimal
(BCD) and then investigate various deployments of BCD-to7-segment decoders in our clock (otherwise my name’s not
Max the Magnificent).
The first untruth is that I failed in my BCD quest (we’ll
cover that next time). The second untruth is that my name is
indeed Max the Magnificent, because that’s what appears as
my moniker on Zoom calls and name badges when I attend
technical conferences, and you can’t argue with logic like
that! Until next time, have a good one!
STEWART OF READING
17A King Street, Mortimer, near Reading, RG7 3RS
Telephone: 0118 933 1111 Fax: 0118 933 2375
USED ELECTRONIC TEST EQUIPMENT
Check website www.stewart-of-reading.co.uk
Fluke/Philips PM3092 Oscilloscope
2+2 Channel 200MHz Delay TB,
Autoset etc – £250
LAMBDA GENESYS
LAMBDA GENESYS
IFR 2025
IFR 2948B
IFR 6843
R&S APN62
Agilent 8712ET
HP8903A/B
HP8757D
HP3325A
HP3561A
HP6032A
HP6622A
HP6624A
HP6632B
HP6644A
HP6654A
HP8341A
HP83630A
HP83624A
HP8484A
HP8560E
HP8563A
HP8566B
HP8662A
Marconi 2022E
Marconi 2024
Marconi 2030
Marconi 2023A
PSU GEN100-15 100V 15A Boxed As New
£400
PSU GEN50-30 50V 30A
£400
Signal Generator 9kHz – 2.51GHz Opt 04/11
£900
Communication Service Monitor Opts 03/25 Avionics
POA
Microwave Systems Analyser 10MHz – 20GHz
POA
Syn Function Generator 1Hz – 260kHz
£295
RF Network Analyser 300kHz – 1300MHz
POA
Audio Analyser
£750 – £950
Scaler Network Analyser
POA
Synthesised Function Generator
£195
Dynamic Signal Analyser
£650
PSU 0-60V 0-50A 1000W
£750
PSU 0-20V 4A Twice or 0-50V 2A Twice
£350
PSU 4 Outputs
£400
PSU 0-20V 0-5A
£195
PSU 0-60V 3.5A
£400
PSU 0-60V 0-9A
£500
Synthesised Sweep Generator 10MHz – 20GHz
£2,000
Synthesised Sweeper 10MHz – 26.5 GHz
POA
Synthesised Sweeper 2 – 20GHz
POA
Power Sensor 0.01-18GHz 3nW-10µW
£75
Spectrum Analyser Synthesised 30Hz – 2.9GHz
£1,750
Spectrum Analyser Synthesised 9kHz – 22GHz
£2,250
Spectrum Analsyer 100Hz – 22GHz
£1,200
RF Generator 10kHz – 1280MHz
£750
Synthesised AM/FM Signal Generator 10kHz – 1.01GHz
£325
Synthesised Signal Generator 9kHz – 2.4GHz
£800
Synthesised Signal Generator 10kHz – 1.35GHz
£750
Signal Generator 9kHz – 1.2GHz
£700
HP/Agilent HP 34401A Digital
Multimeter 6½ Digit £325 – £375
HP 54600B Oscilloscope
Analogue/Digital Dual Trace 100MHz
Only £75, with accessories £125
(ALL PRICES PLUS CARRIAGE & VAT)
Please check availability before ordering or calling in
HP33120A
HP53131A
HP53131A
Audio Precision
Datron 4708
Druck DPI 515
Datron 1081
ENI 325LA
Keithley 228
Time 9818
Practical Electronics | July | 2024
Marconi 2305
Marconi 2440
Marconi 2945/A/B
Marconi 2955
Marconi 2955A
Marconi 2955B
Marconi 6200
Marconi 6200A
Marconi 6200B
Marconi 6960B
Tektronix TDS3052B
Tektronix TDS3032
Tektronix TDS3012
Tektronix 2430A
Tektronix 2465B
Farnell AP60/50
Farnell XA35/2T
Farnell AP100-90
Farnell LF1
Racal 1991
Racal 2101
Racal 9300
Racal 9300B
Solartron 7150/PLUS
Solatron 1253
Solartron SI 1255
Tasakago TM035-2
Thurlby PL320QMD
Thurlby TG210
Modulation Meter
£250
Counter 20GHz
£295
Communications Test Set Various Options
POA
Radio Communications Test Set
£595
Radio Communications Test Set
£725
Radio Communications Test Set
£800
Microwave Test Set
£1,500
Microwave Test Set 10MHz – 20GHz
£1,950
Microwave Test Set
£2,300
Power Meter with 6910 sensor
£295
Oscilloscope 500MHz 2.5GS/s
£1,250
Oscilloscope 300MHz 2.5GS/s
£995
Oscilloscope 2 Channel 100MHz 1.25GS/s
£450
Oscilloscope Dual Trace 150MHz 100MS/s
£350
Oscilloscope 4 Channel 400MHz
£600
PSU 0-60V 0-50A 1kW Switch Mode
£300
PSU 0-35V 0-2A Twice Digital
£75
Power Supply 100V 90A
£900
Sine/Sq Oscillator 10Hz – 1MHz
£45
Counter/Timer 160MHz 9 Digit
£150
Counter 20GHz LED
£295
True RMS Millivoltmeter 5Hz – 20MHz etc
£45
As 9300
£75
6½ Digit DMM True RMS IEEE
£65/£75
Gain Phase Analyser 1mHz – 20kHz
£600
HF Frequency Response Analyser
POA
PSU 0-35V 0-2A 2 Meters
£30
PSU 0-30V 0-2A Twice
£160 – £200
Function Generator 0.002-2MHz TTL etc Kenwood Badged
£65
Function Generator 100 microHz – 15MHz
Universal Counter 3GHz Boxed unused
Universal Counter 225MHz
SYS2712 Audio Analyser – in original box
Autocal Multifunction Standard
Pressure Calibrator/Controller
Autocal Standards Multimeter
RF Power Amplifier 250kHz – 150MHz 25W 50dB
Voltage/Current Source
DC Current & Voltage Calibrator
£350
£600
£350
POA
POA
£400
POA
POA
POA
POA
Marconi 2955B Radio
Communications Test Set – £800
57
![]() ![]() |