Two Teensy Touchscreens:
This project’s goal was to explore and learn how to use small
touchscreens with microcontroller-based applications. At first I did
not have a
specific application in mind, so to get started I decided to redo a
couple of previously completed projects, substituting touchscreens
where before there had
been switches and knobs. Right away I encountered a challenge of sorts.
The touchscreen I’d bought (HiLetgo 2.8 inch TFT, 320 horizontal by
240 vertical pixels) does not have built-in serial bus
capability.
Instead it connects via two Serial Peripheral
Interface (SPI) channels, one for display and one for touch. Each SPI
consumes up to 5 or 6 pins for various signals:
clock, data-out, data-in, CS, DC (TFT), or IRQ (touch). In other words
this small touchscreen device is pin-hungry!
Of course
microcontroller applications themselves consume I/O pins, in addition to their
user-interface parts. This realization may have been the stimulus that
caused
me to search for an alternative to the Arduino Uno
(ATmega328P) that I had used most often in projects. The Uno has
14 digital I/O channels, more than adequate for most projects, but
perhaps fewer than would be needed to wire two SPI channels in addition
to typical application specific I/O requirements.
The Teensy series of microcontroller development boards has
been around for several years. However, for me it was a revelation to learn
how much more compute power and memory this series has than boards and chips that were
previously familiar. I wondered how it was possible not to have noticed the
Teensy long ago!
Teensy 3.5 is not the latest in
the Teensy series, but was advertised as “5-volt tolerant.” That claim,
which evidently applies to some but not all Teensy 3.5 I/O pins,
appealed to me, and is why I decided to start with 3.5.
The following table compares significant
features or parameters of the Uno and Teensy —
Arduino Uno’s 2 KB
dynamic memory limitation is especially troublesome when the
sketch (control program) includes string variables. The Arduino IDE’s
low
memory warning
is all too familiar, and cannot as a general rule be ignored. I was
aware that the larger Arduino program
memory allocation could also be used to
store arrays of constants, and had taken advantage of this construct in a couple of
sketches (for example, https://lloydm.net/Demos/magic_eye.html).
However, the PROGMEM facility is rather awkward, at best a workaround,
and does not compare to the 256 KB of no-tricks dynamic storage
available in Teensy 3.5.

To exploit the more than hundred-fold greater dynamic storage
in Teensy while also learning how to interface the touchscreen I thought of implementing a memory intensive extension for
the ‘Mother of all Keyers’ MOAK
project. Some time ago I had written a (NetBeans) computer application
that included an array of 1000 common English words together with their
relative
frequencies, for presentation via the MOAK as Morse practice (https://lloydm.net/Demos/moak.html#netmoak).
With Teensy it would be possible to bypass the computer interface,
which didn’t work very well, and instead store the words along with
their empirical probabilities in the microcontroller’s memory. I did
this. It worked. And the revised MOAK has no switches or knobs—all main options
are displayed on a single screen and are selectable by touch.
In order to fit everything into a small
package (photo above right) I designed a PCB in Autodesk Eagle (the free version)
and ordered prototype boards from JLCPCB.
The PCB design (my part) had three errors, two omitted resistors
and one omitted trace.
These were easy to solder in place under the manufactured PCB. On the
software side, I split the Teensy sketch into separate
executable
and data files for flexibility. Thus, additional words or terms could be entered into the common
words and radio terms files without changing anything in the main sketch. Although this summary omits construction details, the pinouts worksheet is
shown below and a zipped folder
containing
the sketch and data may be downloaded (Right click link and select ‘Save
as...’).
Printed lowercase letters refer to a generic (prototype)
PCB legend—Ignore these. Labels 5v, AG, etc. correspond to the top (or
front) view of the Teensy 3.5. The handwritten letter ‘R’
indicates that a 4.7K pullup resistor was also connected. Inner pins
were not used. For that matter, some labeled pins (option and select
buttons) were not wired in this touchscreen implementation.
Hilltopper touchscreen: My
next touchscreen exercise began as a harebrained idea. About a year
ago I had interfaced a two-line character-based LCD to the Hilltopper
20 and later also the Hilltopper 40 (https://lloydm.net/Demos/Hilltopper-20.html).
These are low-powered CW transceiver kits from Four
State QRP Group. Later I added minimal CAT
capability to the Hilltopper’s microcontroller code, enabling frequency
to be displayed or adjusted in Ham Radio Deluxe (HRD) or other ham
radio computer applications that support CAT. The harebrained part of
my touchscreen idea involved replacing the Hilltopper’s built-in Atmel
microcontroller with a Teensy, which would necessarily have to be
located outside the unit’s
enclosure—there’s no room inside for it.
I carried this
idea so far as to route a couple of ribbon cables from the
microcontroller’s 28 pin DIP socket to a breadboard-mounted ATmega328P
chip, and subsequently to map nearly all Hilltopper microcontroller
functions to
Teensy. I used small round pin headers for the 28-pin socket end of
these cables, not the shaped headers that go with Arduino shields.
These small pins did not destroy the socket, although
the MPU chip did not fit as snuggly after having seated and unseated the pin headers a
half-dozen or
so times. Upon replacing the ATmega328P with a
breadboard-wired Teensy 3.5, Hilltopper microcontroller-based functions
worked the same, but the unit was no longer receiving, or more
precisely it appeared to be receiving somewhere out-of-band.
I am
not sure why—possibly its 5-volt regulator was overloaded. It
doesn’t matter because at this point I realized that nothing would be
gained by replacing the transceiver’s microcontroller with a different
one located outside the box. Why not instead use the previously
implemented CAT interface to transfer data between a touchscreen
accessory and the Hilltopper.
Exchanging frequency data was straightforward, the same as using HRD or
another computer program. I made up a couple of CAT Z-commands in order
to retrieve the Hilltopper’s RIT step and Morse speed for display on
the TFT. (The modified sketch is linked in the next to last
paragraph of this write-up.) However, after displaying essentially all
data
available to display from the Hilltopper, the TFT screen was less than
half full. A 2.8 inch TFT has considerably more
space available for displaying textual data than a 16 x 2
LCD. At first I thought of
filling the empty space with a picture or design, and I read about rendering bitmaps on a TFT. Then I thought it would be neat
to display a virtual S-meter or even better, a spectrum or waterfall,
such as Icom or Yaesu ham shack transceivers have. Of course, I had no
idea how to do this, either the electronic or coding parts. It occurred
to me that a reasonable starting point would be to learn a little about
Fourier
transforms.
A digression:
Joseph Fourier (1768-1830) surely had
many good vibrations between his ears. Some of these led to a profound
conclusion about vibrations in general, namely
that complicated ones
can be broken down into combinations of simpler ones. Any sound wave,
for example, can be expressed as a combination of pure tones. Fourier
figured out how to do this, and how to do it backwards. It would
be challenging
to name anything in pure mathematics, or at least in Analysis, that has
proven
more useful to
science and technology, or indeed to 21st century life, than this one
thing that Fourier thought of more than 200 years ago…
Science and engineering
students learn about the ‘Fourier transform’ as a tool that is
essential for solving a range of problems s
panning
the subject
areas of their studies. Students of computer programming learn to
compute the transform over discrete datasets, using techniques that
have been designed and perfected to make the most efficient use of
whatever computer resources are available. Consumers who listen to
recorded music, or view .jpeg photo images, or watch cable TV, or do
anything other than retreat to the wilderness, are certain to make
frequent use of Fourier’s insights, without perhaps being aware of them
or their importance. None of these artifacts of modern life had
been imagined two centuries ago. Maxwell’s theory of
electromagnetism, Hertz’s discovery of electromagnetic waves, and
Marconi’s subsequent
invention of wireless communication all came to
pass in the late 1800’s. From these seeds has sprung a mind-boggling
range of artifacts and applications.
In the mid-20th century, partly in
consequence of efforts to improve communications, mathematicians
discovered another powerful abstraction that
would eventually be
applied along with evolving communications technology to bring about
revolutionary change in science and society. That concept was
‘information’. —Information theory and Fourier analysis fit
hand-and-glove to yield applications that have advanced scientific
understanding in many fields, as well as technological ‘spin-offs’ of
inestimable value.1
Learning
by doing: An
Internet example from Norwegian Creations
was particularly helpful for constructing a working Arduino sketch that
demonstrated the Fast Fourier Transform (FFT). I hooked up a function
generator (AKA signal
generator) to a Teensy
ADC input pin, then set the output
amplitude to my instrument’s lowest possible level (4 mV P-P), and the
DC offset to 1.8 volts, the approximate midpoint of the ADC’s
range. The FFT peak corresponding to the
generated 2
KHz sine wave was crystal clear in the TFT display. (The outline in the
upper left corner of the photo is a tab for removing the protective
cover from the TFT.) Twirling the frequency knob moved the peak left
and right, as expected. Substituting a square wave source revealed the expected
secondary peaks, etc. For this graph and others reproduced in these paragraphs, amplitude was
auto-scaled to the maximum value across frequencies, excluding the DC
end, where of course the peak is very large.
Without investigating the matter I imagined it should be possible to
hook into a signal
source, somewhere before Hilltopper’s narrowband CW filter, and display
a few kilohertz of spectrum on either side of the tuned frequency. This
half-formed ‘plan’ is what motivated the exercise.
However, as it turned out I was not able to do this. At this point I proceeded blindly along, not stopping to think in more
detail about how to integrate the display with the Hilltopper.
A
waterfall display is like successive spectrums, each a single row of
pixels, where amplitude has been converted to brightness or
color. The waterfall’s vertical dimension records previously
scanned spectrums, hence corresponds to time. I decided to use shades
of blue for amplitude, from RGB (230, 230, 255) lightest to (0, 0, 255)
darkest. Once the waterfall display was working I blended the FFT
sketch (program code) into the Hilltopper TFT / CAT sketch (or in the
reverse order) so that both Hilltopper frequency data and the spectrum
graphs could be displayed on the same screen, filling it up!
(Cross-hatch lines in the photo are camera artifact—not present in the TFT
display.)
I thought it was possible that touch
sensing would interfere with weak signal sampling and introduce
undesirable artifacts, but it does not. Adjusting
frequency or RIT step by touch does not affect the graphic display. It
is
fair to note, however, that integration efforts did not always succeed
on initial testing. At several points I had to troubleshoot
and
modify the code to get a desired result.
Before digging into the Hilltopper
receiver schematic, I thought to connect a splitter to the headphone
jack, and run one part through a ground isolator (superfluous, as it
turned out) to the ADC, just to see what would happen. In place of the
previous audio test signal I set the function generator to output RF
near the Hilltopper’s power-on frequency of 7.030 MHz, and laid the
function generator probe (antenna) on the table next to the Hilltopper.
As expected, the RF signal was detected by the Hilltopper. When tuned
to between maybe 400 and 800 Hz the audio was clearly visible as a line
in the spectrum / waterfall displays (sorry, no photo). However, the CW filter completely
blocks audio above about 1 KHz, so that only low-level noise displayed in the top
three fourths of the graph with this test setup. Furthermore the tuned
frequency was not at the center of the graph. (Assuming that the tuned
frequency is the same as the audio zero-beat frequency, it would
correspond to the left edge.)
As previously noted I have not figured out how
to extract a suitable passband of say 4 or 8 KHz from the receiver,
with the tuned frequency at the center, if that is even possible. One
constraining factor is that transmit-mute blocks only the final stage
of amplification—In truth I don’t know enough to work out how to use
existing circuitry and I did not want to duplicate receiver stages. So for this
phase of the exercise the spectrum and waterfall displays remain
essentially decorative, as a bitmap image or unrelated graphic would
be.
This story of exploration does not include
schematics or other details, such as would accompany a construction
project. Nevertheless for whatever interest they may have, the revised
Hilltopper sketch with made-up CAT Z-commands for returning RIT step
and Morse speed data may be found here
and the Teensy 3.5 sketch that interfaces with the Hilltopper for
displaying and adjusting frequency via touchscreen may be
found here.
The project as a whole has been
instructive,
not only about interfacing TFT/touch devices, but also how to compute
FFTs using an Arduino FFT library, and how to display
frequency-domain data in forms resembling those of advanced devices.
Demo video: TwoTouchscreens.mp4
1. Joseph Fourier image from
Wikimedia Commons and Claude Shannon image from
here.
Project descriptions
on this page are intended for entertainment only.
The author makes no claim as to the accuracy or completeness of the
information presented. In no event will the author be liable for any
damages, lost effort, inability to carry out a similar project, or
to reproduce a claimed result, or anything else relating to a decision
to
use the information on this page.