Introduction
Some time ago, I discovered the M5Stack — for me, one of the most exciting innovations in the microcontroller field.
The stackable system is based on an ESP32 and combines a case, display, SD card reader, vibration motor, speaker, microphone, sensors, and five buttons into an incredibly compact format.
All this is offered at a fair price and opens up nearly endless possibilities for creative projects.
Of course, one could assemble something like this with almost any microcontroller, but that usually ends up as tinkering. With the M5Stack, everything looks neat and is extremely compact. This allows quick implementation of practical things for everyday use.
Hardware
For my first test with the GNSS module, I use the following hardware:
- M5Stack Core2
- GNSS module with pressure sensor, IMU, and magnetometer
- M5GO Battery Bottom2 (only for Core2)
Code
#include
#include
#include
TinyGPSPlus gps;
HardwareSerial SerialGPS(2);
// Position definitions for display
const int xCenter = 160; // Center alignment of values
const int yLatitude = 50;
const int yLongitude = 90;
const int yAltitude = 130;
const int ySpeed = 170;
const int ySatellites = 210;
void setup() {
M5.begin();
Serial.begin(115200);
SerialGPS.begin(38400, SERIAL_8N1, 13, 14); // RX=13, TX=14
// Background and static texts on the display
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(WHITE, BLACK); // White text on black background
displayStaticText();
}
void displayStaticText() {
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(10, 10);
M5.Lcd.print("GNSS Data");
M5.Lcd.setCursor(10, yLatitude);
M5.Lcd.print("Latitude");
M5.Lcd.drawLine(10, yLatitude + 20, 310, yLatitude + 20, WHITE);
M5.Lcd.setCursor(10, yLongitude);
M5.Lcd.print("Longitude");
M5.Lcd.drawLine(10, yLongitude + 20, 310, yLongitude + 20, WHITE);
M5.Lcd.setCursor(10, yAltitude);
M5.Lcd.print("Altitude");
M5.Lcd.drawLine(10, yAltitude + 20, 310, yAltitude + 20, WHITE);
M5.Lcd.setCursor(10, ySpeed);
M5.Lcd.print("Speed");
M5.Lcd.drawLine(10, ySpeed + 20, 310, ySpeed + 20, WHITE);
M5.Lcd.setCursor(10, ySatellites);
M5.Lcd.print("Satellites");
M5.Lcd.drawLine(10, ySatellites + 20, 310, ySatellites + 20, WHITE);
}
void updateGPSData() {
// Latitude
M5.Lcd.setCursor(xCenter, yLatitude);
M5.Lcd.fillRect(xCenter, yLatitude, 140, 20, BLACK);
M5.Lcd.printf("%.6f", gps.location.lat());
// Longitude
M5.Lcd.setCursor(xCenter, yLongitude);
M5.Lcd.fillRect(xCenter, yLongitude, 140, 20, BLACK);
M5.Lcd.printf("%.6f", gps.location.lng());
// Altitude
M5.Lcd.setCursor(xCenter, yAltitude);
M5.Lcd.fillRect(xCenter, yAltitude, 140, 20, BLACK);
M5.Lcd.printf("%.2f m", gps.altitude.meters());
// Speed
M5.Lcd.setCursor(xCenter, ySpeed);
M5.Lcd.fillRect(xCenter, ySpeed, 140, 20, BLACK);
M5.Lcd.printf("%.2f km/h", gps.speed.kmph());
// Satellites
M5.Lcd.setCursor(xCenter, ySatellites);
M5.Lcd.fillRect(xCenter, ySatellites, 140, 20, BLACK);
M5.Lcd.printf("%d", gps.satellites.value());
}
void updateTime() {
// Adjust time (UTC+1 for winter time in Germany)
int hour = gps.time.hour() + 1;
if (hour >= 24) hour -= 24;
M5.Lcd.setCursor(210, 10);
M5.Lcd.fillRect(210, 10, 100, 20, BLACK);
M5.Lcd.printf("%02d:%02d:%02d",
hour,
gps.time.minute(),
gps.time.second());
}
void loop() {
while (SerialGPS.available() > 0) {
gps.encode(SerialGPS.read());
if (gps.location.isUpdated()) {
updateGPSData();
updateTime();
delay(1000);
}
}
}