This is only a preview of the March 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:
|
Teach-In 2024
Learn electronics with
the ESP32 by Mike Tooley
Part 1 – Getting started
W
elcome to Teach-In 2024!
In this first article of the series,
we will start with an overview
of the ESP32 and how to use the development environment. We will move
on to show you how to use your PC to
monitor the ESP32’s built-in capacitive
touch sensors and our practical project
involves using the ESP32 in a portable
emergency beacon.
The learning objectives for this part
are to know and understand:
n Installation and use of Arduino IDE
n How to enter and test code
n Use of a breadboard with the ESP32.
Why ESP32?
There are several good reasons why
we’ve chosen the ESP32 as a platform
for this series. Put simply, the ESP32
is well-established (launched in 2016),
powerful and easy to use. The device
is highly configurable and can be used
in applications ranging from the most
basic application – controlling an LED
display – to the most demanding uses
– MP3 streaming and decoding. The
device offers extensive analogue and
digital I/O, a serial UART, compatibility
with popular and universal SPI and I2C
devices. It also has Ethernet, dual-mode
Bluetooth, and Wi-Fi connectivity. At
well under £10 for a development board
(see Fig.1.1) that’s really hard to beat!
A really handy plus point is that
the ESP32 has excellent built-in RF
technology. This avoids the tricky
problem of having to add external RF
components, which, because of the
signal frequencies involved, can often be
challenging and problematic in terms of
circuit layout. The device incorporates an
RF power amplifier (with an output of up
to 20dBm), a low-noise receiver amplifier,
an antenna switch and RF filters. That’s a
lot of tricky electronics avoided.
In recent years the feature rich ESP32
has become firmly established as the
starting point for a wide range of lowcost control and IoT (Internet of Things)
applications. The reasons for its success
include, in no particular order:
Exceptional connectivity
The ESP32 boasts multiple connectivity
options based on 2.4GHz Wi-Fi, Bluetooth
Fig.1.1. A low-cost ESP32 development board.
42
About Teach-In
Our latest Teach-In series is about
using the popular ESP32 module
as a basis for learning electronics
and coding. We will be making no
assumptions about your coding
ability or your previous experience
of electronics. If you know one but
not the other, you have come to the
right place. On the other hand, if you
happen to be a complete newbie
there’s no need to worry because the
series will take a progressive handson approach. There will be plenty of
time to build up your knowledge and
plenty of opportunity to test things
out along the way.
We’ve not included too much basic
theory because this can be easily
found elsewhere, including several
of our previous Teach-In series, see:
https://bit.ly/pe-ti
https://bit.ly/pe-ti-bundle
There will be projects and challenges
to help you check and develop your
understanding of the topics covered
each month.
Fig.1.2. ESP8266 and ESP32 boards.
Practical Electronics | March | 2024
and Ethernet, as well as basic serial
UART connectivity. The Bluetooth
interface supports both ‘classic’ and
Bluetooth Low Energy (BLE) operation.
The IEEE 802.1-compatible Wi-Fi can
be configured in access point (AP) mode
as well as client and station mode. The
former allows the ESP32 to set up its own
local wireless network, while the latter
provides a way to connect to the Internet
using your existing Wi-Fi network.
Extensive I/O
The ESP32 supports a wide variety
of external hardware. It has inbuilt
DAC, ADC, PWM and touch sensing
functionality, as well as I2C, SPI and
serial UART interface compatibility.
Low-power operation
The ESP32’s minimal power requirements
are ideal for applications that need
battery power. The ESP32 can be put
into ‘deep sleep’ mode requiring only a
few microamps from a battery supply.
Low-coast and wide availability
ESP32-based modules and Devkits are
available from several suppliers at very
low cost (typically around £5 to £10 for
a complete development board).
Dual-core processor
Most ESP32 modules and boards are
based on dual-core architecture and,
where necessary, code can be run
simultaneously and independently on
the two cores.
Firmware
The ESP32 board is supplied with
FreeRTOS firmware installed. This
powerful, well-documented opensource OS (operating system) supports
multi-tasking and provides a vast
array of API (application programming
interface) functions.
Ease of coding
Coding is straightforward and can be
based on the Arduino IDE or other popular
software development tools (see later).
What is an ESP32?
ESP32 is a generic name that describes
Espressif’s family of powerful System
on Chip (SoC) devices. The name has
also been used to describe modules
and a plethora of development boards
(Devkits) based on this processor. The
ESP32 SoC follows on from the success
of its predecessor, the ESP8266, but
incorporates several important new
features (see Fig.1.2).
Supplied as an SoC package, the ESP32
is designed to be embedded in systems
designed for specific applications,
such as access control, environmental
monitoring, machine control and home
automation. When supplied in the form
of a module, the ESP32 is mounted on
a small daughter board that typically
includes external circuitry such as a
printed Wi-Fi antenna.
Taking it one step further, development
boards, known as ‘Devkits’, offer an
enhanced experience for experimentation
and learning. They provide a generous
subset of the ESP32’s I/O pins, along
with a USB programming interface and
a voltage regulator. Our Teach-In series
focuses on the most popular Devkits
using the ESP-WROOM-32 module.
These boards are available in both 30and 36-pin versions. Although either
version can be used to follow our series,
we have used the smaller 30-pin board
in most of our practical layout diagrams.
The ESP-WROOM-32 has the impressive
specification listed in Table 1.1.
Finally, if you happen to already
have experience of the Arduino UNO,
you will find that the ESP32 has been
made available in board configurations
matching that of the UNO (see Fig.1.3).
This neat arrangement makes it possible
to use peripheral hardware designed for
the UNO with an ESP32 SoC. The ESP32
has even been integrated into the latest
Arduino UNO R4 Wi-Fi. This merges
the RA4M1 processor from Renesas with
the ESP32-S3 from Espressif, a really
powerful and versatile combination.
Table 1.1 ESP-WROOM-32 specification
Feature
Specification
Notes
Processor
32-bit dual core, 40nm process
Single-core versions are also available
Processor speed
160 or 240 MHz
ROM
448kB
Booting and core function storage
SRAM
520kB
Instructions and data storage
External memory
Up to 32Mb of flash memory
DAC
2 × 8-bit
ADC
18 channels × 12-bit
SAR type ADC
GPIO
34 programmable pins
See Table 1.2 for limitations
SPI
Four channels
I2S
Two channels
2-wire connection
I2C
Two channels
3-wire connection
UART
Three serial ports
Wi-Fi
IEEE 802.11 b/g/n
Bluetooth
V4.2 BR/EDR and BLE 1
Ethernet
MAC interface with dedicated DMA
RTC
Time is retained in various sleep modes
Memory controller
SD/SDIO/CE-ATA/MMC/ MMC host controller
LED and motor PWM
Up to 16 channels
IR remote controller
TX/RX up to 8 channels
For external memory
Touch sensors
10 capacitive touch sensor inputs
Via GPIO pins
Power
+3.3V or +5V from a USB connector
Deep sleep supply current can be as low as a few µA
Practical Electronics | March | 2024
43
Fig.1.3. (left)
An Arduino UNO
and an ESP32
development
board sharing the
same form factor.
Fig.1.4. (right)
Typical ESP32
development
board layout.
What we will be covering
Regular features of this new Teach-In
series will include the following sections
and features:
Check it out!
Put simply, this will be the point at
which you can stop reading and start your
practical investigation of the concepts that
we’ve introduced in the text. Check it out!
will reinforce your learning by putting
ideas and techniques into context.
Practical project
Our practical project will showcase
the topics covered each month. Most
practical projects can be completed in a
couple of hours and parts can be saved
for use in later projects.
Coding workshop
We will develop coding skills progressively
throughout the series and, while this isn’t
a series about coding, it’s important to be
able to understand what the code does and
how your coding style can be improved.
Teach-In challenge
After completing our practical project you
might be keen to try something yourself.
Our monthly Teach-In challenge will set
you a task and give you something to get
your teeth into. We will provide a few
pointers along the way, but the solution
will always be in your hands.
Finally, and to help you avoid some
potential pitfalls along the way, we’ve
included some short Gotcha! hints and
tips, providing pointers and solutions to
problems that you might encounter in
your projects. We’ve added these at the
points at which you are most likely to
need them. You will find five of them in
this first part – hopefully they will help
you avoid the painful head scratching
that we experienced when putting the
series together!
What you will need
Just like previous Teach-In series, you
will need a few basic items to explore
the showcased examples and to construct
the projects featured each month. We’ve
strived to ensure that the requirements
are simple, inexpensive and we suspect
that most of our readers will already have
many of the items to hand. If that’s not the
case, you will find numerous suppliers
online, mentioned in the pages of PE,
and listed in our Going further feature
each month. To get started this month
you will need:
n
L ow-cost ESP32 microcontroller
development/Devkit board (see later)
n
Low-cost breadboard with jumper
leads for connecting to external
circuitry
n USB cable to connect the development
board to your PC
n Copy of the freely available Arduino
integrated development environment
(IDE) installed on your PC (see later)
n
5V USB charging power pack for
remote and stand-alone operation of
some of your projects
n Standard red LED and a 150Ω resistor.
Coding and the ESP32
The ESP32 can be used with several
popular programming environments,
including:
n Arduino IDE
n PlatformIO IDE (VS Code)
n LUA
n MicroPython
n
E spressif IDF (IoT Development
Framework).
Since many readers will already be
familiar with the Arduino IDE, this is
Fig.1.5. Pin connections for a typical 30-pin ESP32 development board.
44
Practical Electronics | March | 2024
Table 1.2 Recommended GPIO pins for general use
Designation
Function
Direction
Comment
GPIO0
TX0 (serial port)
O
Serial programming and debugging
GPIO2
User LED
I/O
Avoid external connection
GPIO3
RX0 (serial port)
I
Serial programming and debugging
GPIO4
I/O
I/O
Available for general use
GPIO5
I/O
I/O
Strapping pin – avoid
GPIO6-11
Flash memory
n/a
Avoid external connection
GPIO12
I/O
I/O
Strapping pin – avoid
GPIO13-14
I/O
I/O
Available for general use
GPIO15
I/O
I/O
Mutes debugging messages
GPIO16-33
I/O
I/O
Available for general use
GPIO34-39
I/O
I
Input only
the ESP32’s onboard LED on and
off at 1s intervals.
/* On-board LED flasher */
You should be
int ledPort = 2; // GPIO2 is connected to the LED
able to get an
idea of what the
// Initialise the port
code does even
void setup() {
if you’ve never
pinMode(ledPort, OUTPUT);
seen it before!
}
Notice that this
// Loop forever
code includes
void loop() {
some comments
digitalWrite(ledPort, HIGH); // Set LED on
(insertedbetween
delay(1000);
// 1s delay
the ‘/*’ and ‘*/’
digitalWrite(ledPort, LOW);
// Set LED off
characters and
delay(1000);
// 1s delay
also after the ‘//’
}
characters). Even
though they have
no impact on the execution of your code,
the platform that we will be using. The
these comments are invaluable – top tip,
IDE is reasonably intuitive and is free to
do keep them short and meaningful.
download and use. It is also exceptionally
Coding is an iterative process based on
well supported with reference tutorial
a repeated cycle of entering (or editing)
material and extensible with code
code, uploading to the target system,
libraries for a huge variety of peripheral
executing, debugging and optimising
devices. To give you some idea of just
your code. You may find that you have to
how easy ESP32 programming can be,
loop through this cycle many times before
above is some example code that will flash
Example code
your code executes in the way that you
need. You will also find that once you’ve
developed a block of code that works
well you will be able to reuse it in other
situations. This is another reason why it
is important to comment your code so that
you can understand what it does, how to
use it, and – where necessary – adapt it.
What’s on the board?
Fig.1.4 shows a typical development
board. We’ve labelled the board to show
you the most important features. You will
notice that the external pin connections
run along the two longer sides of the
board, while the printed Wi-Fi antenna
and USB connector are located at the
opposite ends. Adjacent to the USB
connector are two small buttons, labelled
EN (enable) and BOOT. These buttons are
used to restart the system and for
uploading code respectively. There are
two LEDs on the board. The Power LED
indicates that power is present, while the
User LED is available for test purposes.
We will make use of this later.
Gotcha!
Ther are many ESP32 development
boards available from different
suppliers and manufacturers. The
features, layout and pinout may
vary from those shown in Fig.1.4.
We’ve used the most common
subset of pins and connections in
this series, but it is important to
check the layout and configuration
of your board before making any
connections to it, or applying power.
The ESP32’s GPIO pin configuration is
summarised in Table 1.2. Note that GPIO
pins have multiple functions, and some
are unsuitable for general use. Those
shown shaded in green are recommended
for general purpose use.
Fig.1.6. Pin connections for a typical 36-pin ESP32 development board.
Practical Electronics | March | 2024
45
Fig.1.7. Two (slightly modified) breadboards provide a
convenient space for a 30-pin ESP32 development board.
Gotcha!
Several different pin configurations
are found on ESP32 development
boards. The most common of which
use either 30 or 36-pins. There may
also be minor differences in the way
in which the pins are marked on the
boards. You may also find that not all
the GPIO pins listed in Table 1.2 are
available on your board. The ones
that are ‘safe’ for general purpose
use are shaded in green.
Pin connections for typical 30- and 36pin ESP32 development boards are shown
in Figs.1.5 and 1.6 respectively. We have
shown the different signal functions for
the GPIO pins on this diagram. Notice how
the GPIO pin numbering is not always
consecutive and how some pins can have
up to five different functions. For example,
GPIO4 can be configured for use:
n As a normal digital I/O pin
n As an analogue input (Channel 0 of
ADC2)
n As a touch sensing input
n
In conjunction with the real-time
clock (RTC)
n As a means of connecting an SPI (serial
peripheral interface) device.
This may sound baffling at first, but it will
become clearer when we look at some
practical examples of how the chip is
used and interfaced to external devices.
Breadboards
You will need a breadboard to connect
electroniccomponentstoyourdevelopment
board. These are available in various sizes
and with different numbers of connecting
points. For Teach-In, and because of the
size of the ESP32 development board we’ve
standardised on an arrangement based on
two separate breadboards placed side-byside. We’ve also modified one of the boards
by unclipping and removing one of the
supply rails (red and blue) before glueing
the two boards onto a small piece of MDF.
Fig.1.7 shows how this is done, and Fig.1.8
shows a typical breadboard circuit
arrangement with ESP32 and external
components connected.
Gotcha!
Whatever breadboard you use it’s
important to have plenty of space
available for mounting components.
A cramped layout can quickly
become confusing.
Fig.1.9. Selecting the IDE installer for your computer.
46
Fig.1.8. A typical breadboard circuit arrangement ready for
testing.
Installing and configuring the
Arduino IDE
Before you can begin to enter code into
your ESP32 you will need to connect it
to a PC that has a copy of the Arduino’s
integrated development environment
(IDE) installed on it. The process is
quite painless, but it requires an Internet
connection so that you can download the
latest version of the IDE package.
We’ve installed the IDE package
successfully on a whole host of different
computers, including some running
32- and 64-bit versions of Windows and
also a couple running different flavours
of Linux. The step-by-step procedure
described here was carried out on a
computer running Windows 10, but the
process is similar, if not quite identical, on
other machines. Note that an installation
under Linux may require the installation
of the Java run-time environment (JRE)
if not already installed.
1 O
pen your Web browser and go to
www.arduino.cc (the official Arduino
home page). When the page has
loaded click on ‘Software’ to open the
downloads page. Then scroll down
to the latest version of the Arduino
IDE (currently 2.2.1) which usually
appears at the top of the list. Next,
select the installer for your machine
(we chose the Windows 10 64-bit
installer) from the list on the right.
Fig.1.10. Selecting the destination folder for
your installation.
Practical Electronics | March | 2024
Fig.1.11. The Arduino IDE has been
successfully installed and is ready to run.
2 A
t this point you will be asked if you
would like to make a contribution
(see Fig.1.10). You can either click
on ‘Just download’ or ‘Contribute
and download’. When you’ve made
your choice the installation file will
be downloaded to your computer.
The download is quite large, so,
depending on the speed of your
Internet connection, you may have
to wait for a minute or two for the
download to complete.
3 Next, click on the installer or unzip the
file (depending on which version you
have chosen) and simply follow the
prompts. You can choose a destination
folder (see Fig.1.10) or just accept the
default. Finally, click on ‘Install’ to
start the installation process.
4
Depending on the speed of your
computer the installation process
may take as little as 30 seconds or
up to several few minutes. You may
also be given the option of installing
a USB driver. This driver will allow
your computer to communicate with a
standard Arduino by means of the USB
port. We recommend that you click
on ‘Install’ to install this additional
system software (this is not part of
the IDE itself).
5
When the installation is complete
(and when any USB driver has been
added) you can click on ‘Finish’ and
either return to your normal desktop
or, if you’ve checked the ‘Run Arduino
IDE’ (see Fig.1.11) you can run the IDE
and get started right away.
6 T
o install the extra
libraries and code
for the ESP32 you
will need to tell the
IDE where to go to
fetch the required
files. Run the IDE
(if not already
running), select
‘File’ from the
menu bar and then
‘Preferences’. Next,
you will need to
manually enter the
URL in the dialogue Fig.1.12. A URL is used to locate the code needed to
box (see Fig.1.12). configure the IDE for the ESP32.
The URL is rather
serial COM port has been identified
long but here it is:
and allocated to your ESP32. Click on
https://raw.githubusercontent.com/
‘OK’ to complete the set-up process and
espressif/arduino-esp32/gh-pages/
your ESP32 is ready for some code!
package_esp32_index.json
9 You should now be rewarded with
a window like the one shown in
Just enter the above URL (exactly as
Fig.1.16. The message in the ‘Output’
shown in Fig.1.12) and then click on ‘OK’.
field (at the bottom of the screen)
confirms that the ESP32 platform has
7 Next, select ‘Tools’, ‘Board’ and ‘Board
been installed successfully. Note also
Manager’ from the drop-down menu.
that the status bar (also at the bottom
Scroll down the list of supported boards
of the screen) is reporting that the IDE
to the entry headed ‘esp32 by Espressif’
is connected to an ‘ESP32 Dev Module
and then click on ‘INSTALL’ as shown
on COM4’. If that’s not the case, click
in Fig.1.13. It may take several minutes
on ‘Tools’, scroll down to ‘Board’ and
for the library files to be downloaded,
‘Port’, and hover your mouse over
but during that time the progress
them. If the settings are not correct
bar should be active, and a list of
you will be able to change them.
downloaded files should be displayed.
10
If you are ready to try some code,
After these additional tools have been
here’s a simple ESP32 application
automatically configured the IDE will
that flashes the built-in LED. Just type
be ready for use with the ESP32.
the code in Listing 1.1, or download
8 Now connect your ESP32 development
it from March 2024 page of the PE
board to your PC using one of its
website: https://bit.ly/pe-downloads
(powered) USB ports. Note that the
Next, click on the large right arrow
USB port supplies +5V power so there’s
(below the menu bar) to verify, compile
no need for a separate DC supply for
and upload the code to the ESP32 in
the ESP32. With the IDE still open,
executable form. Note that if there
click on ‘Select Board’ and ‘Select
are any errors in the entered code the
other board and port’ (Fig.1.14). Scroll
compilation will fail and you will need
down the list of ESP32 boards (there are
to locate and correct the errors before
quite a few!) until your ESP32 board
trying again. Note also that you can use
is listed (usually this will be ‘ESP32
the ‘File’ menu to save your code (and
Dev Module’). Click to select the board
also rename it, if required).
and a tick will appear against it (see
Fig.1.15). You should also see that a
Check it out!
Now for an exercise that will introduce
you to the ESP32’s touch sensors without
needing any additional hardware (other
Fig.1.13. (left)
Using the
IDE’s Board
Manager to
install support
for the ESP32.
Fig.1.14.
(right)
Selecting the
ESP board
and port.
Practical Electronics | March | 2024
47
+
Listing 1.1 Test code that flashes the ESP32’s on-board LED
/* Flash the built-in LED via GPIO2 */
int ledPort = 2;
// ESP32 built-in LED
int timeOn = 200;
// On time (ms)
int timeOff = 800;
// Off time (ms)
void setup() {
// Initialise the LED port as an output.
pinMode(ledPort, OUTPUT);
}
void loop() {
// This loop runs forever!
digitalWrite(ledPort, HIGH);
delay(timeOn);
digitalWrite(ledPort, LOW);
delay(timeOff);
}
// Turn the LED on
// Turn the LED off
Gotcha!
Fig.1.15. Choose your board from the list of supported hardware.
If you receive a message of the form ‘A fatal error occurred:
Failed to connect to ESP32’ check first that you have the correct
board and port selected. If that doesn’t solve the problem, wait
for the IDE’s ‘Connecting….’ message to appear then press
and hold the BOOT button until the next message confirming
that the connection has been made, at which point the flash
memory will be erased and rewritten. This can be tedious,
but it usually works.
way of replacing pushbuttons and toggle switches. You can check
this out using the code in Listing 1.2.
Enter (or download) the code shown in Listing 1.2 and then
execute it in the same way as before. The user LED on GPIO2
should become illuminated whenever you touch a jumper lead
connected to GPIO15 (see Fig.1.17).
Fig.1.16. The IDE is communicating with the ESP32 Dev
Module on COM4 and ready for some code (the code
displayed is just a blank template).
Coding workshop
To get your hardware to do something useful you will need to have
some code that will tell it what to do and how to respond when
something happens. The process of producing code (ie, ‘coding’) is not
particularly difficult but it does require a structured and systematic
approach. If you’ve ever had to provide someone with a detailed set of
instructions for travelling somewhere you will know how important
it is not to forget any steps and to give your instructions in a clear
Listing 1.2 Code for checking the ESP32’s in-built capacitive
touch sensing inputs
/* Checking out the ESP32’s touch sensors */
int ledPort = 2;
//ESP32 built-in LED
void setup() {
// Initialise the LED port as an output
pinMode(ledPort,OUTPUT);
}
Fig.1.17. The on-board LED should operate when touching a
jumper lead connected to GPIO15 (D15 on most boards).
than a breadboard and jumper wire). Ten of the ESP32’s
GPIO pins can be configured as capacitive touch sensitive
inputs. Simply placing a finger on one of these pins is
sufficient for an input to be generated. This can be a great
48
void loop() {
// This loop runs forever
delay(100);
// Wait for 100ms
if (touchRead(15)<40)
// Touch!
{
digitalWrite(ledPort,HIGH); // LED on
}
else if (touchRead(15)>=40)
// No touch
{
digitalWrite(ledPort,LOW); // LED off
}
}
Practical Electronics | March | 2024
and unambiguous way. The same applies to computer coding,
but with the added complication that we need to present our
instructions in a way that can be interpreted by a machine rather
than a human being. Coding is easy to learn if you ‘start simple’
and build up your skills progressively and systematically. We
start this month with a look at the ways in which data is handled
and manipulated.
Boolean data
Data that can only take one of two possible values is referred to
as ‘Boolean data’. Inside the Arduino this type of data can be
represented using a single byte (8-bits) of data and it can take a
value of either TRUE or FALSE, HIGH or LOW or simply ‘on’ and
‘off’. These two states are mutually exclusive and we refer to them
as ‘Boolean’ because they conform to the rules of Boolean Logic
(much more of this in a later instalment).
The variables that we use in our code need to be declared
before they can be used. An example of a Boolean declarations
is as follows:
boolean powerGood = FALSE;
// power status
At some later point in the code (within the main loop that executes
forever) you might encounter the following line:
powerGood = !powerGood;
// toggle the power status
Note that the ‘!’ in the foregoing code fragment can be read as
‘not’ and the line of code simply changes the state of the Boolean
variable to the opposite of what it was before. In other words, if
powerGood had previously been HIGH it will now become LOW,
and vice versa.
Unfortunately, there’s some potential for confusion here. The
Arduino uses a byte (8-bits) of memory to store Boolean data,
but since Boolean data can only exist in one of two possible
states and where available memory is limited (as it is with the
Arduino) it would be advantageous to use just a single bit of data
rather than an entire byte because seven of the eight bits used to
store the Boolean data are just not being used (a stored binary
value of 0000000 will be interpreted as FALSE and anything
else will be interpreted as TRUE). This is rather wasteful and
so it’s important to remember that using a Boolean data type is
no more efficient in terms of memory usage than using integer
values (see later). That said, it can often be neat and convenient
to use Boolean data types.
Integer data
Whole numbers (ie, numbers with no decimal point) are frequently
stored as integers (or ‘ints’). Integers require two bytes (16 bits) of
storage and the most significant bit (MSB) is used to indicate the
sign of the number. When this bit is 0 the value is positive and
when it is 1 the value is negative. The method of representing
numbers is referred to as ‘2’s complement’ notation and with 16bits of data it yields a range that extends from –32768 to +32767.
A typical extract from a program’s setup code might be:
int powerLED = 11;
// Output pin used for the
power good LED
This line of code defines and initialises a variable that we’ve named
powerLED. We’ve told the Arduino that it is to be handled as an
int (ie, an integer) and that it is to be given an initial value of 11.
The statement ends with a semicolon (;) and this is followed by a
brief comment designed to act as a reminder of what the purpose
of the statement is. Brief comments like this can be invaluable
later on when the time comes to do some software maintenance
and also when code is shared among several authors.
Later on in the program code you might find a line that
takes the form:
Practical Electronics | March | 2024
digitalWrite(powerLED, HIGH);
// Illuminate the
power good LED
Even if you’ve never done any coding before you can probably
make a reasonable guess of what this statement does. At another
point in the code you might find something like this:
if(powerGood = = FALSE) {
digitalWrite(powerLED, LOW);
}
The above code fragment turns the ‘power good’ LED off when
the system has sensed a problem with the power supply. It does
this by examining the state of the powerGood Boolean variable
(see earlier) and, if found to be FALSE (in other words, not good)
the ‘power good’ LED is turned ‘off’ by writing a low (0V) to its
digital output pin (pin-11 as defined within the integer declaration
earlier in the code).
The syntax for the declaration (in this particular case it’s a
constant rather than a variable) is simply the name followed by
the value that you’ve assigned to it. Note that the name takes
the form of a meaningful description (two words with no space
included between them). Note also that the first word begins
with a lower-case character and the second word with a single
upper-case character. This convention helps make the code easier
to read and it avoids the need to include a space character in the
name (which would be invalid).
At some point later in the code you might find something like this:
if(powerGood = = FALSE) {
digitalWrite(powerLED, LOW);
}
There’s often a need to increment or decrement a variable
within a program loop (for example, when counting events)
but, because of the use of 2’s complement notation, it is very
important to be aware that when a variable is incremented or
decremented, the variable will roll-over whenever it reaches
the maximum allowable size. So, for example, incrementing
32767 (the maximum allowable positive value) will cause the
value to become –32768 (note the change of sign). In a similar
manner, decrementing a value of –32768 (the maximum
allowable negative value) will cause a variable to take a new
value of +32767.
Finally please be aware that the use of two bytes to store an
integer is not consistent over all Arduino versions. For example,
the Arduino Due uses four bytes (32-bits) to store integer values.
This provides a range of values extending from –2,147,483,648
to +2,147,483,647.
Floating point data
As the name implies, floating point numbers, or ‘floats’, are
numbers that include a decimal point. They offer a much larger
range from –3.4028235E+38 to +3.4028235E+38. Floats are stored
using four bytes (32 bits) of data.
Floats are often used to represent analogue values from
sensors. Due to the need for four bytes of data, floating point
mathematics can be significantly slower than when integers are
used (where only two bytes of data are involved). Consequently,
it is advisable to use integers rather than floats whenever speed
of execution is important.
A typical extract from a program’s setup code might be:
float peakConvert = 1.4159;
// To convert from
RMS to peak
We could then determine the peak voltage and peak current present
in a 50Ω load using something of the form:
49
Listing 1.3 Code for the portable emergency beacon
/* Listing 1.3 ESP 32 emergency beacon */
char message[] = “SOS”;
int ledPort = 2;
// ESP32 built-in LED
int dotLen = 100;
// length of a dot
int dashLen = dotLen * 3; // length of a dash
int gap = dotLen * 5;
// length of a space
void setup() {
pinMode(ledPort, OUTPUT);
}
byte inputStatus = 0x00;
byte inputFailure = 0xFF;
void loop() {
for (int i = 0; i < sizeof(message) - 1; i++) {
char tempChar = message[i];
GetChar(tempChar);
}
LEDOff(gap); // Extra gap between repeats
}
// DOT
void MorseDot() {
digitalWrite(ledPort, HIGH);
delay(dotLen);
}
limited in range. The minimum value that can be represented
is 0 when all of the bits are 0 (hexadecimal 0x00) and the
maximum value is 255 (hexadecimal 0xFF) when all of the bits
are set to 1. Despite the restricted range, byte data can be useful
in a variety of applications, particularly when dealing with the
status of eight input or output lines. For example:
// LED on
// DASH
void MorseDash() {
digitalWrite(ledPort, HIGH);
delay(dashLen);
}
// LED on
// LED Off
void LEDOff(int holdTime) {
digitalWrite(ledPort, LOW);
delay(holdTime);
}
// LED off
// Morse code
void GetChar(char temp) {
switch (temp) {
case ‘S’: // Three dots
MorseDot();
LEDOff(gap);
MorseDot();
LEDOff(gap);
MorseDot();
LEDOff(gap);
break;
case ‘O’: // Three dashes
MorseDash();
LEDOff(gap);
MorseDash();
LEDOff(gap);
MorseDash();
LEDOff(gap);
break;
}
}
peakVoltage = rmsVoltage * peakConvert;
peakCurrent = peakVoltage / 50;
Byte data
Byte is used to store 8-bits of data as unsigned binary numbers.
So, for example, a binary value of 10000001 (equivalent to 81
in hexadecimal or 128 in decimal) might be defined as follows:
// initialise input
port status
// all port lines
have gone high
At some later point in the code, we might encounter a line of
the form:
if(inputStatus = = inputFailure) {
Serial.print(“Warning: Input failure!”);
}
In this example a fault is present if all of the input lines are
simultaneously in the HIGH state and in this condition the value
of the inputStatus variable will be 0xFF. If this condition is
detected a brief warning message will be sent via the serial port
(more of using the serial monitor later in the series).
Character data
The character data type is used when we just need to represent
alphanumeric information such as plain text. The character
data type uses a single byte of memory to store each character.
Thus, the word ‘character’ would need nine bytes of storage.
Character literals are enclosed within single quotes (eg, ‘A’),
while double quotes are used for strings comprising several
characters (eg, “Power Good”).
Character data is encoded using the American Standard
Code for Information Interchange (ASCII). Each character
is represented by a corresponding signed 8-bit value. ‘A’ for
example is encoded as 01000001 in binary. This is equivalent
to 41 in hexadecimal or 65 in decimal. The basic ASCII
character set uses only seven bits (equivalent to a decimal
range that extends from 0 to +127. When the leading bit is
set (ie, 1 and not 0) the signed byte becomes negative with
a range extending from –1 to –128. These 128 values can be
used to represent special characters. Note that the following
three lines of code are equivalent:
char testChar = ‘A’;
char testChar = 65;
char testChar = 0x41;
Also note how the number base in the last example is indicated
by the prefix 0x, which indicates that the number that follows
is written in hexadecimal format.
The Serial.println() function provides you with a way
of printing data using several different representations:
Serial.println(analogValue);
// print as
ASCII-encoded decimal
Serial.println(analogValue, DEC); // print as
ASCII-encoded decimal
Serial.println(analogValue, HEX); // print as
ASCII-encoded hex
Serial.println(analogValue, OCT); // print as
ASCII-encoded octal
Serial.println(analogValue, BIN); // print as
ASCII-encoded binary
byte bitMask = 0x81; // mask unwanted bits
Note that the ‘0x’ prefix denotes a value expressed in hexadecimal
(base 16) format. Because only eight bits are used, byte data is
50
This concludes our brief look at the way that data is
represented. Next month we will be getting to grips with
some data manipulation.
Practical Electronics | March | 2024
Fig.1.18. Off-board circuit for the
prototype emergency beacon.
Fig.1.21. LED pin connections.
Practical project
Our first practical project involves the
design, construction, and coding for a
simple portable emergency beacon. We will
develop the circuit using an ESP32 Devkit
and development board. The finished
version could use an ESP32 module, a highintensity LED and a rechargeable battery,
but for now we will do the development
using a standard Devkit, LED and USB
power from the host computer.
The minimal circuit and wiring layout for
our prototype emergency beacon are shown
in Figs.1.18 to 1.20. The pin connections
for the LED are shown in Fig.1.21. (Note
that it is important to connect LEDs with
the correct polarity.) The 150Ω resistor is
used to set the current that will be supplied
to the LED (in this case about 7mA).
Having connected the circuit, made the
USB connection to your PC, and started the
IDE, you can enter (or download) the code
shown in Listing 1.3. When you run the
code, you should see the LED repeatedly
flashing an ‘SOS’ message in Morse code.
Now let’s walk through the code. The
first few lines of code define the variables
(explained earlier). Note that we have the
dashlen and gap variables in terms of
the dotlen variable that was previously
defined. Thus, to change the speed of the
Morse code beacon we only need to change
dotlen and the other two variables will
change in proportion.
Next, we enter the main loop which
examines each character in our message in
turn and determines the pattern of dots and
dashes that represent the character in Morse
code (see Fig.1.22). If a dot is required, the
LED is switched on (ledPort goes HIGH)
for a time defined by dotlen before being
switched off for a time defined by gap.
Alternatively, if a dash is required, the LED
is switched on (ledPort goes HIGH) for
a time defined by dashlen before being
switched off for a time defined by gap.
Note that the voltage present at a GPIO
pin voltage will be approximately 3.3V
when in the HIGH state and 0V when in
the LOW state. Thus, when our code takes
GPIO2 HIGH current will begin to flow in
the LED and it will become illuminated.
Conversely, the current will stop when
GPIO2 is taken LOW. This allows us to
switch the LED on and off.
Don’t worry if you don’t fully
understand the code at this stage. The
most important thing to grasp for now
is how the GPIO pins are controlled
through digitalWrite(). We will be
taking a more detailed look at this when
we explain digital I/O next month.
Teach-In challenge
Our Teach-In challenges will provide you
with something to test the knowledge that
you’ve acquired. This month, starting with
Fig.1.19. Wiring for the prototype emergency beacon based on
a 30-pin board.
Practical Electronics | March | 2024
Fig.1.22. Morse code.
the emergency beacon code that we met
earlier, modify and extend the code so that
it continuously flashes a ‘HELLO’ message
in Morse code.
Gotcha!
Code can be pretty darn picky and
unforgiving! Common errors are
forgetting to end lines with ‘;’, not
terminating a multi-line comment
with ‘*/’ and failing to pair opening
and closing braces, ‘{’ and ‘}’. As
time goes on you will undoubtedly
become proficient and learn to avoid
these basic errors.
Next month
In the next part of our Teach-In series
We will take a close look at digital input
and output. We will provide a detailed
look at the relationship between digital
signals and logic levels, and explain
how the GPIO ports are configured.
We will learn how to interface buttons
and switches, and develop simple
code to sense and display their state.
Coding workshop will introduce logical
constructs and decision making. We will
also introduce flow charts, and explain
the design and construction of a simple
traffic light controller.
Fig.1.20. Wiring for the prototype emergency beacon based on
a 36-pin board.
51
|