Silicon ChipTeach-In 2024 – Learn electronics with the ESP32 - October 2024 SILICON CHIP
  1. Contents
  2. Publisher's Letter: Updates on kits and the magazine
  3. Feature: Techno Talk - Sticking the landing by Max the Magnificent
  4. Feature: Net Work by Alan Winstanley
  5. Feature: The Fox Report by Barry Fox
  6. Project: 500W Monoblock Class-D Amplifier by Phil Prosser
  7. Subscriptions
  8. Feature: Circuit Surgery by Ian Bell
  9. Project: TQFP Programming Adaptors by Nicholas Vinen
  10. Feature: Audio Out by Jake Rothman
  11. Feature: Electronic Modules - 16-bit precision 4-input ADC by Jim Rowe
  12. Feature: Max’s Cool Beans by Max the Magnificent
  13. Review: Linshang LS172 Colorimeter by Allan Linton-Smith
  14. Back Issues
  15. Project: 2m VHF FM Test Signal Generator by Andrew Woodfield, ZL2PD
  16. Feature: Teach-In 2024 – Learn electronics with the ESP32 by Mike Tooley
  17. PartShop
  18. Market Centre
  19. Advertising Index
  20. Back Issues

This is only a preview of the October 2024 issue of Practical Electronics.

You can view 0 of the 80 pages in the full issue.

Articles in this series:
  • (November 2020)
  • Techno Talk (December 2020)
  • Techno Talk (January 2021)
  • Techno Talk (February 2021)
  • Techno Talk (March 2021)
  • Techno Talk (April 2021)
  • Techno Talk (May 2021)
  • Techno Talk (June 2021)
  • Techno Talk (July 2021)
  • Techno Talk (August 2021)
  • Techno Talk (September 2021)
  • Techno Talk (October 2021)
  • Techno Talk (November 2021)
  • Techno Talk (December 2021)
  • Communing with nature (January 2022)
  • Should we be worried? (February 2022)
  • How resilient is your lifeline? (March 2022)
  • Go eco, get ethical! (April 2022)
  • From nano to bio (May 2022)
  • Positivity follows the gloom (June 2022)
  • Mixed menu (July 2022)
  • Time for a total rethink? (August 2022)
  • What’s in a name? (September 2022)
  • Forget leaves on the line! (October 2022)
  • Giant Boost for Batteries (December 2022)
  • Raudive Voices Revisited (January 2023)
  • A thousand words (February 2023)
  • It’s handover time (March 2023)
  • AI, Robots, Horticulture and Agriculture (April 2023)
  • Prophecy can be perplexing (May 2023)
  • Technology comes in different shapes and sizes (June 2023)
  • AI and robots – what could possibly go wrong? (July 2023)
  • How long until we’re all out of work? (August 2023)
  • We both have truths, are mine the same as yours? (September 2023)
  • Holy Spheres, Batman! (October 2023)
  • Where’s my pneumatic car? (November 2023)
  • Good grief! (December 2023)
  • Cheeky chiplets (January 2024)
  • Cheeky chiplets (February 2024)
  • The Wibbly-Wobbly World of Quantum (March 2024)
  • Techno Talk - Wait! What? Really? (April 2024)
  • Techno Talk - One step closer to a dystopian abyss? (May 2024)
  • Techno Talk - Program that! (June 2024)
  • Techno Talk (July 2024)
  • Techno Talk - That makes so much sense! (August 2024)
  • Techno Talk - I don’t want to be a Norbert... (September 2024)
  • Techno Talk - Sticking the landing (October 2024)
  • Techno Talk (November 2024)
  • Techno Talk (December 2024)
  • Techno Talk (January 2025)
  • Techno Talk (February 2025)
  • Techno Talk (March 2025)
  • Techno Talk (April 2025)
  • Techno Talk (May 2025)
  • Techno Talk (June 2025)
Articles in this series:
  • Win a Microchip Explorer 8 Development Kit (April 2024)
  • Net Work (May 2024)
  • Net Work (June 2024)
  • Net Work (July 2024)
  • Net Work (August 2024)
  • Net Work (September 2024)
  • Net Work (October 2024)
  • Net Work (November 2024)
  • Net Work (December 2024)
  • Net Work (January 2025)
  • Net Work (February 2025)
  • Net Work (March 2025)
  • Net Work (April 2025)
Articles in this series:
  • The Fox Report (July 2024)
  • The Fox Report (September 2024)
  • The Fox Report (October 2024)
  • The Fox Report (November 2024)
  • The Fox Report (December 2024)
  • The Fox Report (January 2025)
  • The Fox Report (February 2025)
  • The Fox Report (March 2025)
  • The Fox Report (April 2025)
  • The Fox Report (May 2025)
Articles in this series:
  • Circuit Surgery (April 2024)
  • STEWART OF READING (April 2024)
  • Circuit Surgery (May 2024)
  • Circuit Surgery (June 2024)
  • Circuit Surgery (July 2024)
  • Circuit Surgery (August 2024)
  • Circuit Surgery (September 2024)
  • Circuit Surgery (October 2024)
  • Circuit Surgery (November 2024)
  • Circuit Surgery (December 2024)
  • Circuit Surgery (January 2025)
  • Circuit Surgery (February 2025)
  • Circuit Surgery (March 2025)
  • Circuit Surgery (April 2025)
  • Circuit Surgery (May 2025)
  • Circuit Surgery (June 2025)
Articles in this series:
  • Audio Out (January 2024)
  • Audio Out (February 2024)
  • AUDIO OUT (April 2024)
  • Audio Out (May 2024)
  • Audio Out (June 2024)
  • Audio Out (July 2024)
  • Audio Out (August 2024)
  • Audio Out (September 2024)
  • Audio Out (October 2024)
  • Audio Out (March 2025)
  • Audio Out (April 2025)
  • Audio Out (May 2025)
  • Audio Out (June 2025)
Articles in this series:
  • Max’s Cool Beans (April 2024)
  • Max’s Cool Beans (May 2024)
  • Max’s Cool Beans (June 2024)
  • Max’s Cool Beans (July 2024)
  • Max’s Cool Beans (August 2024)
  • Max’s Cool Beans (September 2024)
  • Max’s Cool Beans (October 2024)
  • Max’s Cool Beans (November 2024)
  • Max’s Cool Beans (December 2024)
Articles in this series:
  • Teach-In 2024 (April 2024)
  • Teach-In 2024 (May 2024)
  • Teach-In 2024 – Learn electronics with the ESP32 (June 2024)
  • Teach-In 2024 – Learn electronics with the ESP32 (July 2024)
  • Teach-In 2024 – Learn electronics with the ESP32 (August 2024)
  • Teach-In 2024 – Learn electronics with the ESP32 (September 2024)
  • Teach-In 2024 – Learn electronics with the ESP32 (October 2024)
  • Teach-In 2024 – Learn electronics with the ESP32 (November 2024)
Teach-In 2024 Learn electronics with the ESP32 by Mike Tooley Part 8 – Where Am I? (GNSS) I n the last part of our Teach-In series, we showed how an ESP32 can use an NTP (network time protocol) server to obtain the current time very accurately. Our Practical Project was an accurate digital clock displayed on a low-cost 16 × 2 LCD panel, and our Coding Workshop introduced arrays and structures. In this instalment, we explore the use of low-cost GNSS/ GPS modules as a means of providing location and time data, possibly for navigation purposes. The learning objectives for the eighth part of our series are to know how to: n interface with a low-cost GNSS/GPS module n decode and interpret data received from GNSS satellites n use satellite data to determine the precise UTC time n create user-defined functions The Global Positioning System (GPS) and GNSS Originally developed for use by the US military, and known as Navstar (navigation system with timing and ranging), the global positioning system (GPS) was first used in 1978. However, the full constellation of satellites was not in place and fully operational until 1994. GPS is now widely available for use in many applications including ship, ground vehicle and aircraft navigation. GPS works by triangulating the distances from several satellites. A minimum of three satellites is required for a GPS receiver to calculate a unique lateral position, while four or more provide additional altitude information (a three-dimensional position fix). GPS requires a highly accurate time reference. This is provided by atomic clocks in the GPS ground control stations and the satellites themselves. Because of its global accessibility, GPS has now become extremely popular as a source of highly accurate time information. GPS satellites circle the earth in medium Earth orbit (MEO), at an altitude of approximately 20,200km (12,550 miles). The baseline satellite constellation has 24 satellites in six earthcentred orbital planes. The system can support a constellation of up to thirty satellites in orbit for increased reliability. The satellites in the GPS constellation are arranged into six equally-spaced orbital planes with four slots each. This ensures that GPS receivers are always within view of at least four baseline satellites. Individual satellites broadcast their signals on several frequencies in L-band. The three frequencies used by civilian GPS satellites are 1575.42MHz (L1), 1227.60MHz (L2) and 1176.45MHz (L5). 68 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 hands-on 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 Each month, there’ll be projects and challenges to help you check and develop your understanding of the topics covered. To improve the accuracy and resolution, a network of groundbased stations sends correction data to GPS satellites. Such systems include Wide Area Augmentation System (WAAS) in North America and EGNOS (European Geostationary Navigation Overlay Service) in Europe. The signals transmitted by different GPS satellites use a pseudo-random code comprising a sequence of 1023 binary 1s and 0s. These sequences are modulated using binary phaseshift keying (BPSK). The resulting modulated signal occupies a significant amount of spectrum space, and a GPS receiver employs a circuit known as a ‘correlator’ to recover the original narrowband data from the received signal. In practice, several correlators can be present and operating at the same time. This can significantly reduce the time taken to obtain an initial position fix (TTFF), with different correlators operating on signals from different satellites. In effect, each of these correlators can be acting on a different information ‘channel’. Modern GPS units can use as many as 50 different channels, but typically no more than about a dozen, or so will be in use at any time. Transient data transmitted by GPS satellites is referred to as “ephemeris data”. It provides information about their current (and predicted) location, timing and status. Ephemeris data can also be used to predict future satellite conditions at a specified location and time. These days, GPS is not the only satellite navigation system. There is also Galileo (EU), GLONASS (Russia), BeiDou (China) Practical Electronics | October | 2024 Sentence type Information content GPGGA Time, position and fix type data GPGLL Latitude, longitude, UTC time and status GPGSA GPS receiver operating mode, number of satellites used in the position solution and DOP values GPGSV Number of satellites in view, satellite IDs, elevation, azimuth and signal-to-noise ratio (SNR) GPMSS SNR, signal strength, frequency and bit rate from radio-beacon receiver GPRMC Time, date, position, course and speed GPVTG Course and speed relative to the ground GPZDA PPS timing message (synchronized to PPS) and some regional systems. Many modern ‘GPS’ receivers can also use some or all of those other systems. With GPS, collectively they are known as Global Navigation Satellite Systems or GNSS. GNSS data The data from a GPS/GNSS receiver is a series of ASCII characters, arranged in a format defined by the National Marine Electronics Association (NMEA), so they are referred to as “NMEA sentences”. Several different types of NMEA sentence are produced by receivers. The use of standard ASCII characters makes it possible to receive navigation data using common data interfaces like RS-232, USB, Bluetooth or Wi-Fi. Since not all the received NMEA sentences will be relevant in a particular application, we can ignore those that we are not interested in and concentrate on the sentences containing the data we need. To do this, we need to recognise the type of sentence before decoding the data contained in it. Luckily, we don’t need to write our own code to do this, as there are some excellent libraries available to perform this task for us. For normal positioning application, the two most-used NMEA sentences are GPGGA and GPRMC (see Table 8.1). These carry GNSS fix data and time, date, position, course and speed data respectively. Note that in some more complex GPS equipment GPGGA is replaced by GNGGA which includes navigation data from multiple global navigation satellite sources (often both GPS and GLONASS satellites). A more complete list of NMEA messages is shown in Table 8.1. Antennas GNSS receivers require an antenna to collect signals from GNSS satellites. Since the wavelength is relatively short (approximately 20cm), the antennas can be quite compact. Some GNSS patch antennas can be as small as 1.5×1.5cm, making them ideal for situations where the antenna is mounted on a flat surface, like the windscreen, roof or dashboard of a car. When mounted on a large ground plane (eg, a car roof), patch antennas can exhibit relatively large gain values. This, coupled with their relatively low profile, makes them ideal for use in vehicle, aircraft and most portable applications. Small PCB-mounted chip antennas are popular in low-cost applications where space is paramount. Small helical antennas are also found on some equipment. They are particularly suitable for applications when the orientation is unpredictable or a robust external antenna is needed. NMEA sentences GNSS data is sent as a series of sentences. Here’s an example of a typical NMEA GPGGA sentence: $GPGGA,083258.000,5101.4028,N,00026.9145, W,1,09,1.3,35.8,M,47.1,M,,0000*7B Let’s parse this into some useful data. The first thing we should notice is that the sentence header ($GPGGA) tells us this sentence contains time, position and fix data. From this data we can extract latitude and longitude, as well as a variety of other useful data shown in Table 8.2. Table 8.2 – Example of the data in a typical NMEA sentence Name Value Message ID $GPGGA Time (UTC) 083258.000 hhmmss.sss Latitude 5101.4028 ddmm.mmmm N/S Indicator N N = north, S = south Longitude 00026.9145 ddmm.mmmm E/W indicator W E = east, W = west Position Fix Indicator 1 0=Fix not available or invalid; 1=GPS (SPS mode) fix valid; 2=Differential GPS (SPS mode) fix valid Satellites used 9 0 to 12 HDOP 1.3 Horizontal dilution of precision Altitude (relative to MSL) 35.8 MSL = mean sea level Units M Geoid separation 47.1 Units M metres Age of diff. corr. 0 second Diff. ref. Station ID 0000 Checksum *7B Terminator <CR><LF> Practical Electronics | October | 2024 Format/units Note GGA protocol header metres Only valid when DGPS is used Check for errors End of message 69 Gotcha! Different startup times are quoted for GPS units depending on whether they are started from cold, warm or hot. A cold start is a restart of a unit after a long period of being powered off. A warm start assumes that ephemeris data is still present and available. A hot start is when the previously received satellite constellation is unchanged from last time, so a fix can be quickly obtained. This is why you sometimes have to wait a while for GPS data to become available. Fig.8.1: Robert Larsson’s excellent online GPRMC and GPGGA sentence decoder. You can use an online service to decode the NMEA sentence. The author’s favourite online parser is https://rl.se/gprmc (see Fig.8.1). Location fixing and accuracy A GNSS unit will attempt to fix its location continuously. The rate at which this occurs is referred to as the “update rate”. The standard for most GNSS modules is one update per second (ie, an update frequency of 1Hz). This is adequate for many applications, but faster rates are essential for applications involving aircraft and other fast-moving vehicles. Some modules default to 1Hz but can be configured for, say, 10Hz. Faster update rates will require speedier processing of NMEA sentences. Several sources of error can affect the GNSS fix. Some errors are introduced by signals received from multiple paths. These can be due to reflections from buildings and other large structures, as well as natural objects such as cliffs and rocky outcrops. Others can be caused by unwanted ionospheric and tropospheric effects. All these factors can affect the time taken for satellite signals to arrive at a GNSS receiver. The combination of errors introduced when the GNSS receiver calculates a position are expressed in terms of dilution of precision (DOP). The DOP depends on the positions of the GNSS satellites relative to the location of the receiver. Since the position of the satellites is known, it is possible to estimate the accuracy of a GNSS position fix. The DOP calculation uses both the position and number of satellites available. Since Navstar satellites constantly change position their number and position vary, the DOP will also change continuosly. To make things a little more complicated, the DOP can be divided into vertical and horizontal components (VDOP and HDOP, respectively). Lower values of VDOP and HDOP are associated with more accurate indications. For land- and sea-based operation, HDOP is usually more important. The conclusion from all of this is that DOP provides you with a valuable indicator of how much confidence you can place on a particular GNSS location fix. With lower DOP values your results are likely to be much better than when higher values of DOP are prevalent. You can reduce DOP and improve a GNSS unit’s positional accuracy by one or more of the following: 1. Placing the antenna of your GNSS receiver (or the complete unit if it has an integrated antenna) so it has a clear and unobstructed view of the full sky. This increases the number of satellites in view and gives the most favourable satellite geometry. 2. Arranging the antenna of your GNSS unit so it is not susceptible to signals reflected from buildings, aircraft and other large structures. 3. Allowing your GNSS to average position over a reasonably long period (eg, several minutes). If you can’t, check on the DOP values returned by the GNSS unit, placing more confidence on the data when the lowest values of HDOP (or VDOP) are indicated. GNSS Modules The advent of low-cost widely available GNSS receiver modules, such as the one shown in Fig.8.2, has made it possible to add some exciting features to a huge range of microcontroller applications. Fig.8.2: A low-cost GPS module based on the NEO-6M chip from Swiss company u-blox. Gotcha! The time taken to obtain an initial position (TTFF) while waiting for a GPS module to return data is a key performance indicator of a GPS unit. Since the unit needs to receive signals from as many satellites as possible, the TTFF can be significantly degraded when it is not optimally positioned (eg, indoors) or used in a different location than last time. 70 Fig.8.3: A block diagram of the GPS module shown in Fig.8.2. Practical Electronics | October | 2024 Fig.8.4: The layout of the GPS module board. For example, they can be used to record accurate position information so that objects can be tracked. Not only is it possible to provide a location fix, but even obtain values for altitude, speed, bearing, distance and time. This can literally add a completely new dimension (or three) to your ESP32 applications! GNSS modules usually comprise a GNSS receiver chip and GNSS antenna (or a connector for an external active antenna), together with the necessary serial interfacing logic (eg, a UART) and power-conditioning circuitry. They are available at low cost from suppliers in the UK, USA and Asia. GNSS modules usually operate from a +5V or +3.3V DC supply and employ a serial data interface to transfer information to a computer or microcontroller. This interface usually operates at quite low baud rates, typically 4800 or 9600 bits per second. The low-cost module shown in Fig.8.2 is based on the popular NEO-6M GNSS receiver chip. It is usually supplied with a matching active antenna measuring a mere 25×25mm. The matching antenna requires mounting on an external surface with a clear and unobstructed view of the sky. The module incorporates one LED that flashes continuously when a position fix is obtained. It uses a standard TTL serial connection so interfacing with an ESP32 (or another popular microcontroller) is extremely straightforward. The functional arrangement and board layout for a typical low-cost GNSS module are shown in Fig.8.3 & 8.4. These modules are usually supplied with a 4-way header that can be soldered in place. Its specifications are shown in Table 8.3. Table 8.3 – Typical specifications for a low-cost GPS module Parameter Specification Supply voltage range 3.3 to 6V (onboard 3.3V regulator) Supply current 35mA (11mA in power saving mode) Maximum I/O voltage 3.6V Baud rate 4800 to 115,200bps (default 9600) Operating frequency 1.57542GHz (L1) Sensitivity -156dBm (hot start) Time to first fix (TTFF) <1s for hot start, ~27s for cold start Update rate 10Hz maximum (1Hz default) Number of channels Up to 50 Positional accuracy 2m (or better) achievable Velocity accuracy Typically within 0.1m/s Maximum velocity 500m/s Heading accuracy 0.5° achievable whilst in motion Memory Battery-backed EEPROM Practical Electronics | October | 2024 Fig.8.5: Interfacing a low-cost GPS module to an ESP32 development board only requires five wires. Checking it out It’s time to get to grips with GPS! All you need is the simple four-wire connection from the ESP32 development board to a low-cost GPS module, as shown in Figs.8.5 & 8.6. When you’ve completed the wiring, we suggest you jump right in by downloading, compiling and executing Listing 8.1. The code can be downloaded from the PE website by going to https://pemag.au/link/abyr Listing 8.1 – Using the TinyGPS library to decode NMEA sentences (code extract only) /* Print TinyGPS data using the Serial Monitor. Uses code developed by Mikal Hart (see TinyGPS documentation) */ #include <SoftwareSerial.h> // EspSoftwareSerial library #include <TinyGPS.h> // Mikal Hart's TinyGPS library TinyGPS gps; SoftwareSerial ss(16, 17); // TX and RX serial pins static void smartdelay(unsigned long ms); static void print_float(float val, float invalid, int len, int prec); static void print_int(unsigned long val, unsigned long invalid, int len); static void print_date(TinyGPS &gps); static void print_str(const char *str, int len); void setup() { // The setup code is here } void loop() { // The code for the main loop is here } Fig.8.6: A breadboard layout matching Fig.8.5. 71 When you execute the code in Listing 8.1, you will find that it generates and continuously updates a table of values like that shown in Fig.8.7. The data is decoded for successive NMEA $GPGGA sentences, and may at first sight appear baffling. To make it easier to understand, we’ve added columns (in red) and headings to the figure. Using GPS data Now here are a few pointers that might help you develop your own ESP32 code to be used with a GPS module. To begin, you might need to include one or more of the following libraries: Fig.8.7: Typical $GPGGA NMEA data in the Serial Monitor, produced by Listing 8.1. The somewhat tedious problem of converting NMEA format GPS data into variables that you can use in your code is handled very capably by Mikal Hart’s excellent TinyGPS and TinyGPS++ libraries. This useful library package handles the parsing and conversion of NMEA data and also includes several useful methods and functions that allow you to process and present data in different ways. The TinyGPS library can be downloaded and installed using the IDE’s Library Manager. To include the TinyGPS library, use: #include <LCD.h> #include <LiquidCrystal_I2C.h> #include <SoftwareSerial.h> #include <TinyGPS.h> The next few fragments of code will give you an idea of how data from a GPS module can be handled. For further information, refer to the full code for Listing 8.1 or the examples included with the TinyGPS library. Display the number of satellites being received using the IDE’s serial monitor: Serial.print("Satellites: "); Serial.println(gps.satellites()); ... or on an LCD screen: #include <TinyGPS.h> Listing 8.1 creates a TinyGPS object (we’ve used the rather obvious title, gps) using: lcd.print("Satellites: "); lcd.print(gps.satellites()); Display the HDOP using the serial monitor: TinyGPS gps; Serial.print("HDOP: "); Serial.println(gps.hdop()); While it is possible to create multiple TinyGPS objects, you will probably not need to do that. A single TinyGPS Display the HDOP on an LCD screen: object will suffice for this and most other applications. The low-cost GPS module uses a serial interface to comlcd.print("HDOP: "); municate with the ESP32, so the code includes the ESP lcd.print(gps.hdop()); SoftwareSerial library. It can also be obtained from the IDE’s Library Manager (make sure that you download and install Display the number of characters and sentences received the ESP32 version of this library). The serial I/O provided by the GPS module connects di- using the IDE’s serial monitor: rectly to the RX2 and TX2 pins of the ESP32 development // First we need the statistics to display board (see Fig.8.5). These pins correspond to I/O pins D16 unsigned long chars = 0; and D17, respectively, so those are the pin numbers that unsigned short sentences = 0, failed = 0; need to be referenced in your code: SoftwareSerial ss(16, 17); // TX and RX serial pins Each byte present in a received NMEA sentence is handled by the TinyGPS encode() method, using SoftwareSerial to obtain data from the GPS module one character at a time. This process continues as long as valid data is available: void loop() { while (ss.available()) { int c = ss.read(); if (gps.encode(c)) // Valid? { // New GPS data is processed here } } } 72 gps.stats(&chars, &sentences, &failed); // Then we send them to the serial monitor Serial.print("Characters: "); Serial.println(chars); Serial.print("Sentences: "); Serial.println(sentences); Display the number of characters and sentences received on an LCD screen: Gotcha! The TX and RX signals of the serial GPS interface must be cross-connected so that TX for the GPS module is taken to RX2 (D16) on the ESP32 while RX on the GPS module is connected to TX2 (D17) on the ESP32. Practical Electronics | October | 2024 Gotcha! When you’ve uploaded your code and the ESP32 has reset, the LCD panel will remain blank until the GPS module starts reporting data. This may take several minutes from a cold start and up to a minute following a hot start. Once the unit has acquired a position fix, the module will blink the onboard LED and the LCD should show information (see Fig.8.11). // First we need the statistics to display unsigned long chars = 0; unsigned short sentences = 0, failed = 0; gps.stats(&chars, &sentences, &failed); // Send the # of characters to the first // line of the LCD display lcd.setCursor(0,0); lcd.print("Characters: "); lcd.print(chars); // Send the # of sentences to the second // line of the LCD display lcd.setCursor(0,1); lcd.print("Sentences: "); lcd.print(sentences); Fig.8.8: Some date and time data provided by Listing 8.2. Fig.8.9: The interconnections for the GPS location fixer. Telling the time (again) In Part 7 of Teach-In, we showed how the ESP32 could be This uses the same interface and wiring arrangement that configured for use as an accurate clock using an NTP time we described earlier, in Figs.8.5 and 8.6, and the code is server. We’ll now look at an alternative technique for obtain- shown in Listing 8.2. The output from the Serial Monitor ing date and time information using GNSS. is shown in Fig.8.8. Listing 8.2 – Extracting GPS data and time information /* GPS time/date displayed using the ESP32's Serial Monitor */ #include <TinyGPS++.h> // The GPS library file #define GPSbaud 9600 // Set GPS baud rate TinyGPSPlus gps; // The GPS object void setup() { // Confirm connection Serial.begin(115200); Serial2.begin(GPSbaud); Serial.println(F("ESP32 GPS data")); delay(2000); } void loop() { if (Serial2.available() > 0) { // Check serial port if (gps.encode(Serial2.read())) { // Read the data if (gps.location.isValid()) { // Check if valid if (gps.date.isValid() && gps.time.isValid()) { Serial.print(F("GPS Date/Time: ")); Serial.print(gps.date.day()); Serial.print(F("-")); Serial.print(gps.date.month()); Serial.print(F("-")); Serial.print(gps.date.year()); Serial.print(F(" ")); Serial.print(gps.time.hour()); Serial.print(F(":")); Serial.print(gps.time.minute()); Serial.print(F(":")); Serial.println(gps.time.second()); } else { Serial.println(F("Data invalid!")); } Serial.println(); // Blank line for spacing } } Practical Project Our Practical Project involves the construction of a simple GPS location fixer using an ESP32 development board, low-cost GPS module, and a 20×4 LCD screen. The required interconnections and wiring are shown in Figs.8.9 and 8.10. The 20-character, four-line display is like those used previously in this Teach-In series and, as before, it employs an I2C interfaced to minimise wiring and avoid the use of multiple digital I/O lines. The I2C interface is usually supplied together with the display, and either already soldered in place or comes with a suitable header for interconnection. The complete code listing for the GPS location fixer is shown in Listing 8.3. The code uses the following libraries: LCD.h, LiquidCrystal_I2C.h, SoftwareSerial.h and TinyGPS.h. Before finalising your code, you will need to determine the I2C address of your display. Often this will be 0x27 (ie, hexadecimal 27 or decimal 39). You can determine it by running the I2C if (millis() > 5000 && gps.charsProcessed() < 10) Serial.println(F("Error - GPS data unavailable!")); } } Practical Electronics | October | 2024 Fig.8.10: The wiring layout for the GPS location fixer. 73 Scanner application provided in Listing 5.3 (available for download from the PE website at https://pemag.au/link/abys). Listing 8.3 – Complete code listing for the GPS location fixer Coding workshop /* ESP32 GPS data displayed on an 20x4 LCD panel */ Our Teach-In code examples and listings have made liberal use of functions, so you will know that a function is simply a block of code that’s been given a name and incorporates statements that will be executed when the function is called. Functions are a great way to perform repetitive tasks. They help to minimise and simplify your code, making it easier to understand and re-use. All of our full code listings have included the two most fundamental functions, setup() and loop(). If you’ve been wondering about the void prefix, it just indicates that the function does not return a value directly. If a function returns a value, the function definition needs to begin by indicating the type returned (eg, int). The standard format for a function declaration is thus: type functionName(parameters) { statement1; statement2; statement3; etc. return value; } Note how the list of function statements is enclosed in curly braces and each statement ends with a semicolon. The parameters that follow a function name enclosed in brackets (parenthese) will be passed to the function. If there are none, the brackets are simply left empty. Here’s an example of a function with a void type that doesn’t return anything: void checkLevel() { if (tankFull == 1) { Serial.println("Warning - tank full!"); } else { Serial.println("Filling, please wait"); } } While void functions can still do useful work, you can’t use them within expressions, because they don’t evaluate to anything. #include <TinyGPS++.h> // The GPS library file #define GPSbaud 9600 // Set GPS baud rate TinyGPSPlus gps; // The GPS object #include <LiquidCrystal_I2C.h> int lcdColumns = 20; int lcdRows = 4; LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows); void setup() { lcd.init(); lcd.backlight(); // Confirm connection Serial.begin(115200); Serial2.begin(GPSbaud); Serial.println(F("ESP32 GPS data")); delay(2000); } void loop() { if (Serial2.available() > 0) { // Check serial port if (gps.encode(Serial2.read())) { // Read the data Serial.println("Data read OK "); if (gps.location.isValid()) { // Check if valid Serial.println("Data is valid"); lcd.setCursor(0, 0); lcd.print("Lat: "); lcd.setCursor(7, 0); lcd.print(gps.location.lat(), 6); lcd.setCursor(0, 1); lcd.print("Lon: "); lcd.setCursor(7, 1); lcd.print(gps.location.lng(), 6); lcd.setCursor(0, 2); lcd.print("Alt: "); if (gps.altitude.isValid()) { lcd.setCursor(7, 2); lcd.print(gps.altitude.meters()); lcd.setCursor(12, 2); lcd.print(" m"); } lcd.setCursor(0, 3); lcd.print("Speed: "); if (gps.speed.isValid()) { lcd.setCursor(7, 3); lcd.print(gps.speed.kmph()); lcd.setCursor(11, 3); lcd.print(" km/h"); } lcd.setCursor(18, 3); lcd.print(gps.satellites.value()); lcd.print("*"); Serial.print(F("DATE/TIME: ")); if (gps.date.isValid() && gps.time.isValid()) { Serial.print(gps.date.day()); Serial.print(F("-")); Serial.print(gps.date.month()); Serial.print(F("-")); Serial.print(gps.date.year()); Serial.print(F(" ")); Serial.print(gps.time.hour()); Serial.print(F(":")); Serial.print(gps.time.minute()); Serial.print(F(":")); Serial.println(gps.time.second()); } else { Serial.println(F("Invalid data")); } } Fig.8.11: the position, altitude and speed data are shown on the LCD panel of the ESP32 GPS location fixer. 74 } Serial.println(); } else { lcd.setCursor(0, 3); lcd.print("Wait!"); } if (millis() > 5000 && gps.charsProcessed() < 10) Serial.println(F("No GPS data received: check wiring")); } Practical Electronics | October | 2024 Listing 8.4 – Passing parameters to a user-defined function Gotcha! /* Example of passing parameters to a function */ Several LCD libraries with similar names exist, so it is important to ensure that you use the correct library for the LCD panel that you use. In many cases, guidance is provided by suppliers, but it is worth double-checking that you are using the correct library for the display that you will be using. int analogPin = 15; void setup() { // Use the serial monitor to display the results Serial.begin(9600); } void loop() { int rawReading; int percent; // Get a raw reading from the potentiometer rawReading = analogRead(analogPin); // Send the raw reading to the function percent = getPercent(rawReading); // Print the result using the Serial Monitor Serial.println(percent); delay(2000); } int getPercent(int inputValue) { int result; // Map the value to a percentage result = map(inputValue, 0, 4095, 0, 100); return result; // and return the value } location such as your home, place of work, or intended destination. The TinyGPS library provides you with methods that will allow you to do this but to get you started here’s some code fragments that will get you started. To get the distance from one location (lat1, long1) to another (lat2, long2), use the following function call: TinyGPS::distance_between(lat1, long1, lat2, long2) It returns the distance in metres between two positions where both are specified as signed decimal degrees of latitude and longitude. You can get the course from one location (lat1, long1) to another (lat2, long2) using this function call: TinyGPS::course_to(lat1, long1, lat2, long2) It returns the course in degrees (North = 0°, West = 270°) from the first to the second position, where both are specified as signed decimal degrees of latitude and longitude. Using the above lines of code, if one of the two locations is obtained from gps.get_position() or gps.fget_position() ,it’s possible to compute and display the distance and bearing from a fixed point of reference. The point of reference could be defined as a constant using a line of the form: Parameters can be passed into a function and results returned to the main loop. Listing 8.4 provides you with a simple example that shows how this is done. The example displays the setting of a potentiometer that has its slider connected to D15 and its two ends taken to +3.3V and GND. The raw data read from the analog port is passed to the getPercent() function. It, in turn, determines the percentage of the control setting using the map() function. The resulting static const double LONDON_LAT = 51.508131, value is returned to the main loop where, it is displayed LONDON_LON = -0.128002; using the Serial Monitor. Note that although we’ve used a simple loop in this exFinally, to carry out tests while moving around, you will ample, the getPercent() function could be called whenever need a portable source of USB power. You can easily do this a new percentage reading is needed. with an ordinary USB 5V “power bank”. Another option is to use four rechargeable NiMH cells Teach-In Challenge mounted in a suitable battery holder (see Fig.8.12). Note Extend the functionality of the basic location fixer so that it that, when series-connected, four standard alkaline cells displays navigational information relative to a destination will provide a higher voltage (6V) and are therefore unsuitable for this use. Next month Next month we will be bringing Teach-In to a close by showing you how to interface a matrix keypad and use your ESP32 as the basis of a password-protected entry control system. Coding workshop will introduce files and file handling techniques that will allow you to save data to an SD or microSD card for later analysis. Finally, the Checkpoint section will provide you with the ultimate test of your ESP32 PE knowledge. Howzat! Fig.8.12: a power supply for portable operation using four rechargeable NiMH cells. Practical Electronics | October | 2024 Function names can use alphanumeric characters (A to Z; a to z; 0 to 9) and the underscore character, but they must not start with a number. When choosing names for your functions, they must not be the same as the keywords or functions that are already provided by the language. 75