Topics

► Games

► Sound & Music

► Watches & Clocks

► GPS

► Power Supplies

► Computers

► Graphics

► Thermometers

► Wearables

► Test Equipment

► Tutorials

► Libraries

► PCB-Based Projects

By processor

AVR ATtiny

► ATtiny10

► ATtiny2313

► ATtiny84

► ATtiny841

► ATtiny85

► ATtiny861

► ATtiny88

AVR ATmega

► ATmega328

► ATmega1284

AVR 0-series and 1-series

► ATmega4809

► ATtiny1604

► ATtiny1614

► ATtiny3216

► ATtiny3227

► ATtiny402

► ATtiny404

► ATtiny414

► ATtiny814

AVR DA/DB-series

► AVR128DA28

► AVR128DA32

► AVR128DA48

► AVR128DB28

ARM

► ATSAMD21

► RP2040

► RA4M1

About me

  • About me
  • Twitter
  • Mastodon

Feeds

RSS feed

Tiny GPS Speedometer [Updated]

29th November 2014

This article describes a simple speedometer based on a low-cost GPS module interfaced to an ATtiny85. It's based on a simple GPS parsing routine designed to run on any AVR processor, such as the ATtiny85. The resulting code described here is around 2Kbytes and doesn't require any additional GPS or floating-point library; it's completely self-contained.

The Tiny GPS Speedometer is based on the Adafruit Ultimate GPS Breakout [1] available from Proto-PIC in the UK [2], but would probably work with any GPS module:

Speedometer.jpg

Tiny GPS Speedometer. We're going at 1.69 mph.

Serial interface

The first step was to implement serial communication on the ATtiny85. GPS modules communicate using serial, and are easiest to interface to a chip with a built-in hardware UART, such as the ATmega328 in the Arduino Uno. The only breadboard-friendly ATtiny chip with a UART is the ATtiny 2313, but this is a 20-pin package with more capabilities than this project needs. I decided to use the minimal ATtiny85, which would require implementing a UART in software/hardware.

Because I didn't need to change the GPS module's settings I didn't need a serial transmit, so I implemented a simple 9600 baud receive-only UART using the ATtiny85's USI, as described in an earlier article: Simple ATtiny USI UART 2.

Decoding the GPS string

The information in the NMEA string from the GPS module is decoded by the routine ParseGPS(); a full description of this is given in a separate article: Minimal GPS Parser [Updated]

The routine decodes the time, latitude, longitude, speed, track, and date, although only the speed is used in this application.

Circuit

For simplicity I used a serial 7-segment display module for the display [3], available in the UK from HobbyTronics [4]. The ATtiny85 communicates with the display using its SPI interface, and needs two I/O lines; the SS line can be tied to ground since there's only one SPI device.

Here's the circuit:

Speedometer.gif

Tiny GPS Speedometer circuit.

A lower-cost solution would be to use a processor with more I/O lines, and drive a seven-segment display directly; for an example of this approach see Odometer/Speedometer Pendant.

Compiling the program

I compiled the program using Spence Konde's ATTiny Core, which supersedes the various earlier ATtiny cores [5]. Select the ATtiny x5 series option under the ATtiny Universal heading on the Boards menu. Then choose Timer 1 Clock: CPUB.O.D. Disabled, ATtiny85, 8 MHz (external) from the subsequent menus. Choose Burn Bootloader to set the fuses appropriately. Then upload the program using ISP (in-system programming); I used Sparkfun's Tiny AVR Programmer Board; see ATtiny-Based Beginner's Kit.

Displaying the speed

The display initially shows "----" until the GPS module gets a fix; this can sometimes take a few minutes.

The main routine loop() then simply waits until the GPS data has been updated, and then reads the decoded GPS speed and displays it on the four-digit LCD display:

void loop (void) {
  long temp;
  while(!Fix);
  cli(); temp = Knots; sei();
  Fix = 0;
  // Continuously display the speed in mph
  Display(temp*38/33);
}

Because the GPS variables are updated under interrupt, you need to disable interrupts around any reference to them with cli() and sei() to avoid the risk of reading a half-updated value. The speed in knots is multiplied by 38/33, which gives a good approximation to 1.151, the number of mph in a knot. The routine Display() displays the speed on the display, autoranging between two decimal places for speeds up to 99 mph, and one decimal place for speeds over 99 mph.

Here's the whole Tiny GPS Speedometer program: Tiny GPS Speedometer Program.

Updates

10th March 2017: I have updated the program to incorporate the latest version of ParseGPS(), which has been optimised to reduce its execution time. The older version could cause the software serial routine to miss the start of the next character, resulting in corrupted data. I am grateful to Miles Treacher for helping me to track down this problem.

25th October 2018: If you want to display the speed in km/h rather than mph, change the fraction in the call to Display() to 50/27, which is a good approximation to 1.852, the number of km/h in a knot. In other words:

  // Continuously display the speed in km/h
  Display(temp*50/27);

  1. ^ Ultimate GPS Breakout on Adafruit.
  2. ^ Ultimate GPS Breakout on Proto-PIC.
  3. ^ 7-Segment Serial Display on Sparkfun.
  4. ^ 7-Segment Serial Display on HobbyTronics.
  5. ^ ATTinyCore on GitHub.

blog comments powered by Disqus