This is only a preview of the November 2020 issue of Practical Electronics. You can view 0 of the 72 pages in the full issue. Articles in this series:
|
Make it with Micromite
Phil Boyce – hands on with the mighty PIC-powered, BASIC microcontroller
Part 22: A modern-style analogue GPS clock
L
ast month, we explored how
Fig.2 shows the original concept of using
three different coloured LEDs (dots) to
represent the three clock hands. Here,
blue represents hours, green represents
minutes and red represents seconds. So,
the time shown in Fig.2a is 10:13:43.
The white dots are the
hour markers (or fiveminute markers) as
usually found on most
analogue clocks – and
are simply there to help
make it easier to read
the displayed time. Note
that the top-most marker
at the 12:00 position is
brighter than the other
markers to help orient
the clock.
So, what exactly is
the problem with using
three coloured dots to
represent the three clock
hands? Well, most of
the time there is no
issue at all since the
three dots will be in Fig.1. This analogue GPS-based clock uses a ring of 60
different positions to RGB LEDs, producing a modern twist on a classic format.
each other. However,
as the seconds dot (red) moves around
Let’s focus on the time 01:05:22. Our
the clock ring, at some stage it will be
code ensures that of the three hands, the
in exactly the same position as the
green minutes dot is drawn first (at the
minute dot (green), or perhaps the
5-minute marker), then the blue hours dot
same position as the hours dot (blue).
is drawn at the 1-hour marker, effectively
Likewise, the minutes dot could be
overwriting the green dot. Finally, the
in the same position as the hours dot.
red seconds dot is drawn in the relevant
The result is that you would just see
position. The result is one blue dot in
two dots; for example, when the time is
the 5th position, and one red dot in the
01:05:22 meaning that the hour dot and
22nd position – see Fig.2b.
the minute dot would be in the same
In fact, for the whole minute of the
position. Similarly, just a single dot
time 01:05, the green (minutes) dot is
might be seen; for example, when the
not displayed as it is always overwritten
time is 12:00:00.
by the blue (hours) dot. Also note that at
In the above scenarios, the resultant
exactly 01:05:05, only the red (seconds)
colour of the one, or two dot(s) would
dot would be visible for one whole second
be determined by the sequence in which
– see Fig.2c.
they are ‘drawn’ to the RGB ring. In our
The conclusion is that the ‘three
code we have specifically drawn the
coloured dots’ method sometimes makes
twelve markers first, followed by the
minutes dot (green), then the hours dot
Micromite code
(blue), then the seconds dot (red) last –
The code in this article is available
the reason why we chose this sequence
for download from the PE website.
will be explained later.
Practical Electronics | November | 2020
45
to connect your Micromite Keyring
Computer (MKC) to a GPS module,
and enable them to communicate with
each other via the UART protocol. With
just a few lines of program code we were
able to extract the highly accurate time
information contained within a GPS
‘sentence’, and format it for display
on your computer’s terminal app
screen. This month, we want to use
this accurate GPS time data and display
it on a dedicated display, allowing the
creation of a standalone gadget, free
from being tethered to your computer.
We could have simply displayed the
time information in the usual digital
format on one of the several screens
that we discussed earlier in the series,
such as the mini-IPS screen, or the larger
2.8-inch TFT touchscreen. However,
we wanted to set ourselves a challenge
and see if we could do things a little
differently by displaying the time in
the more traditional analogue format.
To avoid anything mechanical, it
seemed logical to base the display
hardware on a ring of 60 RGB LEDs.
Having 60 RGB LEDs in a circle means
that each LED can represent a minute
on an analogue clock. We can then use
three different coloured LED ‘dots’ to
represent the positions of the three ‘clock
hands’ (hours, minutes, and seconds).
This gives a traditional analogue clock
a nice modern twist; however, it turned
out that the three coloured ‘dots’ were
not quite suitable for displaying the time
as we will now discuss.
Dot-Dot-Dot
a )
b )
c)
Fig.2a. Knowing which colour represents which clock hand allows the time to be read – here 10:13:43. Fig.2b. In this example of
01:05:22, the minutes dot (green) is overwritten by the hours dot (blue) resulting in just the blue hours dot and the red seconds dot
being visible. Fig.2c. At 01:05:05, only the red seconds dot is visible because all three ‘dots’ fall in the same position on the clock ring.
it difficult to read the time; hence we
need a way to resolve this.
Dot-Dash-Dash
On a normal analogue clock, the hours
hand is physically shorter than the
(bigger) minutes hand. Therefore,
when they are aligned, you can still
see both of them even though they are
in the same position. We will use this
concept to resolve our ‘three dots issue’
by representing the hours hand as a
smaller ‘dash’ of three adjacent blue
dots, and the minutes hand as a bigger
‘dash’ of five adjacent green dots. The
red seconds hand remains as a single
dot and the end result is shown in FIg.1
and Fig.3. At first glance it may look
confusing; however, remember that the
big (green) dash represents minutes and
the smaller (blue) dash represents hours,
then it does become easy to read the time.
There are three points to note regarding
the dashes:
1. The central LED in a dash is much
brighter than the other LEDs in the dash.
Therefore, the dash can be considered
as a dot with an ‘illuminated shadow’.
2. The green minutes dash has two shadow
LEDs on either side of the central bright
green LED. The shadow LEDs furthest
away from the central dot are dimmer
than the two shadow LEDs immediately
next to the central LED.
3. The central bright LED in a dash will
overwrite a white marker; however, any
‘shadow LED’ in a dash is overwritten
by the marker. This means that a marker
is visible unless a hand falls exactly on
the marker. Fig.4 shows an example
of this for the time 07:09:28 in which
a minutes shadow LED is behind the
10-minute marker.
Once again, let us consider the times
01:05:22 and 01:05:05 – these are both
shown using the Dot-Dash-Dash method
in Fig.3a and 3b respectively.
46
Now that we have a concept for showing
all three hands simultaneously, no matter
what the time is, there is one more
consideration to take into account in order
for the time to be easily read. On a normal
analogue clock, as the minute hand works
through it’s one revolution in an hour, the
hour hand slowly progresses from onehour marker to the next. For example,
at half-past the hour, the hour hand sits
halfway between the two relevant hour
markers. We want to mimic that effect
in our clock so we will describe how
this is achieved shortly. First though, we
will describe how we can conveniently
control the 60 LEDs.
The RGB LED ring
Back in Part 13 (PE, Feb 2020) we
discussed how to control a strip of
eight individual RGB LEDs (on a BlinkT
module) by using just two SPI pins (Clock
and Data). The specific type of RGB LED
used in the BlinkT was the APA102, and
these LEDs are perfect for easy control
with a Micromite. As we saw back then, to
control each individual LED we just need
to send four bytes of data representing
a )
the brightness, and the red, green and
blue intensity values that together define
the overall colour of an LED. But our
analogue clock requires sixty of these
APA102 RGB LEDs (not just eight), with
all sixty being arranged in a circle (and
not a straight line). Thankfully, a ring of
60 × APA102 LEDs exists as a module and
they can be purchased from many of the
usual online suppliers. We sourced ours
from Cool Components (no affiliation) and
this particular ring comes in a compact
3-inch diameter (see photos). Be careful
when you search online, some suppliers
will sell at a price that at first seems
relatively low, but this is for a ‘quarter
of a ring’ and hence you will need four
quarters to make the full ring. The most
important point is that the total ring
comprises 60 APA102 LEDs (other rings
containing different quantities of LEDs
do exist – so beware!).
The nice thing about the APA102 LED
is that no matter how many of them you
have connected to the Micromite (60 in
this case), you can control the colour and
the brightness of each individual LED by
simply sending the appropriate quantity
b )
Fig.3. The bigger minutes hand (green) and the smaller hours hand (blue) make it much
easier to read the time when the hands overlap since all three coloured hands can be
seen no matter what the time is. In Fig.3a the time 01:05:22 and in Fig.3b it is 01:05:05.
Practical Electronics | November | 2020
Fig.4. (left) Any shadow
LED on the minute and/
or hour hand(s) is drawn
behind a marker. Here,
the time 07:09:28 shows
one of the green minute
shadow LEDs behind the
white 10-minute marker.
Fig.5. (right) The APA102
data communication
format. Each RGB LED
requires a 4-byte frame
to define its brightness
and overall colour.
of 4-byte data-frames (one 4-byte frame for each LED). You will
also need to send a header and a footer to signify the start and
end of the LED frames when communicating with the LED ring.
Fig.5 shows the format of APA102 data communication – the
diagram is taken from Part 13 and has been updated slightly to
show the data for the LED string as being 60 frames in length
(as opposed to eight frames). Do not worry about the detail for
now, it is just for easy reference when viewing the comments
in this month’s code. The important point to note here is that
we have 60 LEDs that can be individually controlled in terms
of brightness (one byte in the frame), and colour (three bytes
in the frame). It is well worth re-reading Part 13 to clarify
further details.
Defining the seconds hand
Let’s now consider how we can position and define the
seconds hand. Imagine that in our code we have a way of
referring to any of the 60 LEDs by using a reference number
between 0 and 59. Imagine also that we can set the colour of
the referenced LED as well as its brightness. It would then
make sense to use the reference number (between 0 and 59)
to represent the position on the clock for the LED we wish
to set. To achieve this in code we can simply use four arrays
as follows:
BrBuf() stores the brightness value of an LED; between 0 (off)
and 31 (full brightness).
rBuf() stores the RED intensity of an LED; between 0 (off)
and 255 (full intensity).
gBuf() stores the GREEN intensity of an LED; between 0 (off)
and 255 (full intensity).
bBuf() stores the BLUE intensity of an LED; between 0 (off)
and 255 (full intensity).
S D I
32*0 LED1 LED2 LED3 LED4 –––– LED60 (32+8)*0
S ta rt
fra m e
S T A R T
fra m e
3 2 b its
( 4 b yt e s)
D a ta fo r L E D
00000000
00000000
8 b its
B r ig h tn e s
111 xxxxx
E n d
fra m e
st r i n g
00000000
00000000
8 b its
8 b its
8 b its
B lu e
bbbbbbbb
G re e n
gggggggg
R e d
rrrrrrrr
8 b its
8 b its
8 b its
00000000
00000000
00000000
00000000
00000000
8 b its
8 b its
8 b its
8 b its
8 b its
L E D
fra m e
3 2 b its
( 4 b yt e s) 3 b i t s
E N D
fra m e
3 2 + 8 b its
L E D
fra m e
5 b its
Defining the minutes hand
The minutes hand is similar to the seconds hand, but the relevant
minute value between 0 and 59 references a bright green LED.
If we use the variable mm to store the minute value (eg, the 44th
minute) then to define the green minute hand we begin with:
mm=44
‘ define minute position in the array
BrBuf(mm)=31 ‘ maximum brightness
rBuf(mm)=0
‘ zero red intensity
gBuf(mm)=255 ‘ full green intensity
bBuf(mm)=0
‘ zero blue intensity
However, as explained above, the minute hand is a dash
comprising of five dots, and hence has two adjacent shadow
LEDs on each side of the above defined bright green LED. To
define the two shadow LEDs preceding the bright green minute
value, we can use the following:
BrBuf(mm-1)=3
rBuf(mm-1)=0
gBuf(mm-1)=255
bBuf(mm-1)=0
BrBuf(mm-2)=1
rBuf(mm-2)=0
gBuf(mm-2)=255
bBuf(mm-2)=0
‘ low value brightness
‘ zero red intensity
‘ full green intensity
‘ zero blue intensity
‘ minimum value brightness
‘ zero red intensity
‘ full green intensity
‘ zero blue intensity
BrBuf(22)=31 ‘ maximum brightness
rBuf(22)=255 ‘ full red intensity
gBuf(22)=0
‘ zero green intensity
bBuf(22)=0
‘ zero blue intensity
Note that the two shadow LEDs after the bright green minute
hand would be referenced in a similar manner to the above
eight lines of code but with mm+1, and mm+2. However, there is
one thing to note, and it is best explained by using mm=59. The
two preceding shadow LEDs in this example are not a problem
(at array position 57 and 58), but the two shadow LEDs after
the minutes hand would be in array positions 60 and 61 – both
of these are invalid as we only go up to array position 59. The
way we deal with this is easy, since the (invalid) position 60
is the same as (valid) position 0, and position 61 is the same
as position 1. To do the calculation for the two shadow LEDs
after the central bright green minute ‘dot’, we will use a variable
called Tmp, along with an IF…THEN statement. We can then
adjust array position 60 to 0, and position 61 to 1 as follows:
Note that this does not turn on the relevant LED; the four
arrays are simply storing the information that ultimately make
up the frame values for the referenced LED. So, the above
four lines of code store the required values in the four arrays
that will ultimately result in the second hand (bright red dot)
being drawn in position 22. When all sixty LEDs have been
defined in a similar fashion, we can then call a subroutine
that is programmed to send the stored array data to the LED
ring via a code loop that uses the SPI command to send all 60
data frames (and the header and footer).
Tmp=mm+1: IF Tmp>59 THEN Tmp=Tmp-60
BrBuf(Tmp)=3
‘ low value brightness
rBuf(Tmp)=0
‘ zero red intensity
gBuf(Tmp)=255 ‘ full green intensity
bBuf(Tmp)=0
‘ zero blue intensity
Tmp=mm+2: IF Tmp>59 THEN Tmp=Tmp-60
BrBuf(Tmp)=1
‘ minimum value brightness
rBuf(Tmp)=0
‘ zero red intensity
gBuf(Tmp)=255 ‘ full green intensity
bBuf(Tmp)=0
‘ zero blue intensity
So, to define the seconds hand (red dot) at position 22 (meaning
22 seconds) we just need to set the values in the four arrays
as follows:
Practical Electronics | November | 2020
47
In a similar manner, the two shadow LEDs prior to the central
bright green minute ‘dot’ need checking to ensure the calculated
array position doesn’t equal the invalid values of –1 or –2. Thus:
Tmp=mm-1: IF Tmp<0 THEN Tmp=60+Tmp
....
‘ low value brightness
Tmp=mm-2: IF Tmp<0 THEN Tmp=60+Tmp
....
‘ minimum value brightness
The above is not a listing of the complete code, it is purely
for explaining the concepts; and will help to make it easier to
understand the comments that are in the code.
Positioning the hours hand
Regarding the hours hand (a dash comprising of three blue
dots), the first point we need to consider is how to convert
the hour value (0 to 23) into a clock position value (0 to 59).
Then, as mentioned earlier in the article, the second point to
understand is how to make the hours hand slowly progress
from one hour marker to the next (while the minutes hand
makes its full revolution).
The first point is addressed by taking the hours ( hh) and using
MOD 12 to obtain a value between 0 and 11. Then multiply it by five
to get a clock (array) position. So, if we are in the 14th hour (hh=14)
the resulting hours clock position is (14 MOD 12)* 5 = 10.
The second point is addressed by then adding a value
between 0 and 4 to the hours clock position we calculated
above. It may seem complicated, but do stick with me. The exact
value (0-4) needed to be added to the hours clock position is
determined by the minutes value (just as it is on an analogue
clock). Having five available progressive step positions for the
hours hand means that we can divide an hour (60 minutes)
into five equal ‘windows’ of 12 minutes each. So, assuming the
minutes value is stored in variable mm, when mm is between 0
and 11, we add 0 to the hours clock position, and when mm is
between 12-23 we add 1, and so on (24-35 add 2, 36-47 add
3, and 48-59 add 4). There is a useful operator in MMBASIC
that we can use to return the integer part of a division – this
is the ‘\’ operator as opposed to the usual ‘/’ divide operator
(which returns the complete value of a division, not just the
integer part). Used correctly with mm, the ‘\’ operator returns
the relevant value between 0 and 4 to be added to the hours
clock position value.
All of the above determines the position of the central dot
in the hours dash (which in total comprises this central bright
blue dot, along with two adjacent shadow LEDs). We then need
to use similar checking to ensure that we don’t end up with
an invalid array position such as −1 or 60 (no other invalid
values are possible for the hours hand if you follow the logic
through). So, our code to define the blue hours hand becomes:
‘ convert hours (0-23) into clock position (0-59)
hh=((hh MOD 12)*5)+(mm\12) ‘ and add step-increment
BrBuf(hh)=22
‘set brightness
rBuf(hh)=0
‘RED intensity
gBuf(hh)=0
‘GREEN intensity
bBuf(hh)=255
‘BLUE intensity
Tmp=hh-1:If Tmp<0 Then Tmp=60+Tmp
BrBuf(Tmp)=3
‘shadow brightness
rBuf(Tmp)=0
‘RED intensity
gBuf(Tmp)=0
‘GREEN intensity
bBuf(Tmp)=255
‘BLUE intensity
Tmp=hh+1:If Tmp>59 Then Tmp=Tmp-60
BrBuf(Tmp)=3
‘shadow brightness
rBuf(Tmp)=0
‘RED intensity
gBuf(Tmp)=0
‘GREEN intensity
bBuf(Tmp)=255
‘BLUE intensity
48
This concludes the explanation of how the clock’s three
hands are defined in terms of values stored in the four
arrays. We will now quickly discuss how we define the 12
white ‘hour’ markers.
Defining the markers
This is really simple – I promise! All we need to do is set the
LEDs at positions 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55
to a low intensity white colour, and then the LED at position
0 to a slightly brighter white. We can do this with a FOR…NEXT
loop as follows:
FOR count=5 TO 55 STEP 5
BrBuf(count)=1 ‘set minimal brightness
rBuf(count)=3 ‘RED intensity
gBuf(count)=3 ‘GREEN intensity
bBuf(count)=3 ‘BLUE intensity
NEXT count
‘ now define the brighter marker at position 0
BrBuf(0)=16
rBuf(0)=3
gBuf(0)=3
bBuf(0)=3
Overall program flow
Now that we have covered the building blocks for our GPS
analogue clock, we will next discuss the sequence of steps that
our program code follows in order for it to perform as we desire.
This will be kept to a high level as there are the usual supporting
comments in the program code that explain things further.
1. On power-up, the TIME$ system variable starts at 00:00:00
2. The Brightness value is set to the maximum value (31)
3. The MKC checks for a valid GPS signal. If valid, the TIME$
is set to the amended UTC value (as described last month)
4. The current TIME$ is displayed on the LED ring as follows:
a) SUB ClearBuffer ensures that all 60 array elements
are cleared to the following values:
BrBuf()=Brightness
rBuf()=0
gBuf()=0
bBuf()=0
b) The hours, minutes and seconds values are extracted from
the TIME$ variable, and loaded into variables hh, mm and ss
c) SUB DrawMinutes is called and sets the relevant array
values to define the green minutes hand (as described above)
d) SUB DrawHours is called and sets the relevant array
values to define the blue hours hand (as described above)
e) SUB DrawMarkers is called to define the twelve white
markers (as described above)
f) SUB DrawSeconds is called to define the red seconds
hand (as described above)
g) SUB SendLED is called to output the array data in an
SPI format (as outlined in Fig.5)
5. Program returns back to repeat from Step 3
The program code for the analogue clock (GPS_AnalogueClock.
txt) can be downloaded from November 2020 page of the PE
website. Do read through the comments in the code, along with
the above notes, and the ideas will fall into place. Now that
we have covered the design, theory, and have the code loaded,
it is just a matter of connecting up the necessary hardware.
Circuit diagram
Please refer to Fig.6 for the schematic of the MKC GPS Analogue
Clock. As can be seen, there are only three hardware elements
to the complete design: the MKC, the GPS module, and the LED
ring. The GPS module requires 5V power, and a single UART
data link between the GPS Tx pin, and the Micromite’s COM1
Rx pin (pin 22) – this is as described last month.
Practical Electronics | November | 2020
The only constructional challenge is
attaching the four inter-connecting cables
to the LED ring. We used a spare femaleto-female connector ribbon cable since
these contain stranded cable inside each
conducting wire (making it more flexible
than if it were solid core cable). We tore
off four cables to meet our requirements
and then cut off the four connectors
from one end. Next we removed four
short pieces of insulation from the cut
end, and tinned them in preparation
for soldering them to the four relevant
pads on the back of the RGB ring. The
end result is a short 4-way ribbon cable
soldered at the LED ring end, and four
female connectors at the other end into
which we can insert male-to-male jumpers
to connect it to the MKC –
see Fig.7. Be sure to connect
5V power (from the MKC) to
the correct two points on the
LED ring, otherwise it may
be damaged.
With the GPS module and
the LED ring connected to the
MKC (and with the Analogue
Clock program code loaded),
power up your MKC, type
RUN and you should see the
LED ring come to life. If not,
then recheck all four power
connections that supply 5V
power to the two modules,
and also check the correct
SPI pins (pin 3 and 25) are
connected to the correct two
pads on the LED ring.
Initially the LED ring
will not display the correct
time because the Micromite
always resets the time to Fig.7. Four connecting cables are made from cutting
00:00:00 on power-up. Only down a female-to-female ribbon cable (see inset lower
when a valid GPS signal is right). Normal male-to-male jumper wires are then used
received will the time be to connect the LED ring to the MKC, as shown here.
displayed correctly. If the
correct time is not displayed within
GPS signal to periodically update the
three minutes, then it will be worth
time stored in it, ensuring it is always
repositioning your GPS module (or
accurate with zero drift.
externally mounted antenna) to a location
4. Add an LDR (light-dependent resistor)
that has a better view of the sky (in order
to an analogue input pin to sense the
to pick up clear satellite signals). Do
light level in the room. Then have the
remember to set the correct UTC offset
code automatically adjust the brightness
at the start of the program. The offset
of the LEDs. This allows you to dim
value depends on which time zone you
the display in a darkened room (eg, at
are in, as well as any daylight saving –
night) so that the LEDs aren’t too bright.
see the comments contained in the code.
Likewise, in a well-lit room, the LEDs
That concludes the build of the MKC
can be made brighter so that the clock
GPS Analogue Clock – once again, this
is more visible.
project has shown you just how easy it is
5. Add an IR receiver and a piezo sounder
to use minimal hardware and just a few
to make an alarm clock. Use a remote
lines of BASIC code to create a useful
control to switch between the actual
product that can then be customised by
time, and the alarm time (use colour to
simply making a few changes to the code.
indicate what is currently being shown).
Use cursor keys on the IR remote to
select between setting the alarm hours
Challenges
and minutes. Use the remote to silence
There are endless modifications you
(or snooze) the alarm. Use VAR SAVE
could make to the code this month. We
and VAR RESTORE to save (and recall)
would always encourage you to change
the alarm time.
the code as it is a fantastic way to learn,
6. Use a different method to display the
and it also ensures that you understand
time in the analogue format – making
the concepts presented. To give you some
it easy for anyone to read the time.
ideas as to what you could try, have a go
at coding some of the following:
I hope these have provoked some ideas
1. Change the colours and brightness of
– and please do email us with anything
the hands and markers to suit your
that you create, and that you feel is
own personal preference.
worth sharing. Until next month, have
2. Have an indication as to when a valid
fun coding!
GPS signal is being received – for
example, use the 12:00 marker (the
upper most marker) and use one colour
such as white to indicate a valid GPS
signal, and another colour such as
Questions? Please email Phil at:
yellow to indicate no GPS signal.
contactus<at>micromite.org
3. Add an RTC module from the IPS
Display Module (IDM) and use the
Practical Electronics | November | 2020
49
GPS module
GND
Vdd
Rx
Tx
N C
5V
0V
3
D I
C I
5 V
C O
N C
N C
D O
0 V
D O
22 M K C
C O M 1 : R x
25
C O
C I
D I
5 V
0 V
S o ld e r p a d s o n u n d e r s id e o f r in g
Fig.6. The schematic of the MKC GPS
Analogue Clock. There are just seven
connections to be made between the
MKC, GPS module, and the LED ring, as
shown here.
The LED ring also requires 5V power
and is connected to the Micromite’s SPI
Dout pin (pin 3) and the Micromite’s SPI
Clock pin (pin 25) – this was effectively
described in Part 13.
Assembly
|