Distance Measuring (and More) Device Using Arduino and GPS

29,468

60

4

About: A human wanting to have wings to fly...

Intro: Distance Measuring (and More) Device Using Arduino and GPS

In my previous Instructable, I have showed how to get essential data from a portable GPS, Holux M-1000 and convert UTC to local time.  This morning (Nov. 3rd), the Daylight Saving Time ended.  I turned on the device as soon as I woke up this morning to see if the time was correctly adjusted and yes, it worked correctly. :-)

In this Instructable, I'm going to show how:
  • to calculate distance between two points using simple formula I developed.
  • to use the LCD (Nokia 5110) to display info (speed, bearing, date, time, distance from a marked point).
  • to use regulated power source from GPS for microcontroller (JeonLab mini, minimal Arduino) and LCD, which means you don't need separate battery pack.
The main functions of the device are:
  • Calculate and display distance from a point, where you marked by pressing a button, to current position (can be used for playing golf).
  • Alarm at certain speeds (can be used while you are driving).
Since there is still plenty of memory in ATmega328p chip left (~15k), I'm thinking add some more functions in the future versions, for example, Geocache locator or golf assistance using SD card.

Step 1: Parts List

Parts list
  • Arduino board: I used my minimal Arduino board, JeonLab mini, but there are other small or even smaller boards you can buy; Arduino mini, Arduino micro, or Arduino nano for instance.  Small form factor for portability is the key, so choose one as small as possible and one you are familiar with.
  • GPS: Holux M-1000 or any portable GPS unit with a serial data port
  • LCD: Nokia 5110
  • Push button switches: any momentary push button switches (normal open)
  • Speaker: smaller the better. I found one in my junk drawer that I took out long time ago from either a PDA (Palm TX, m100, IIIe, T2 or....) or a digital camera, I don't remember...
  • a piece of prototyping circuit board
  • some double sided foam tape
  • some wire: 28 to 30 wire gauge
  • Time, creative mind and enthusiasmof yours
     

Step 2: Finding Proper Power Source for the Microcontroller and LCD

I opened up the GPS and found a test point, V28A, which must be regulated power from the Li-ion battery (3.7V). The microcontroller, ATmega328p, on Arduino can run at 1.8 - 5.5V and the LCD, Nokia 5110 need 2.7-3.3V. So 2.8V is perfect for both.

As shown in the picture, 30 gauge wires were soldered directly on the GPS pcb, on V28A (2.8V), TX, and GND.

The GPS, Holux M-1000 has TX and RX pins available on the USB mini-B port, but I needed only TX pin to send data to the microcontroller. Using a magnifying glass, I followed the trace of the USB pin and flipped the PCB over and found the spot to solder the wire for the TX pin.

The wire for the GND line is simply soldered to the battery contact pin.

The LCD and JeonLab mini board consume not much current, so with the built-in battery pack on the GPS, it lasts more than 10 hours with even the backlight of the LCD on.

Step 3: Assembling LCD and JeonLab Mini Board

The right angle header pin is used to connect the LCD and the JeonLab mini board.

In order to save power, no LEDs (power and digital pin 13) on the JeonLab mini board was attached.  I wanted to make the board as thin as possible, so bent the legs of the ceramic resonator and found it didn't work.  Probably it was damaged because I bent those legs too much.  I didn't have any extra blue resonator at hand, had to replace it with a little bigger resonator (same frequency, 16MHz).  Look at the pictures in

Step 4: Pin Connections

Here is the full list of pin connections.

Arduino 2 - LCD RST (reset)
Arduino 3 - LCD CS/CE (chip selection)
Arduino 4 - LCD DC (data/commands choice)
Arduino 5 - LCD MOSI/DIN (serial data line)
Arduino 6 - LCD SCLK (clock)

Arduino 10 - GPS TX

Arduino Vcc - LCD Vcc - GPS 2.8V
Arduino GND - LCD GND - GPS GND

Arduino 8 - LCD LED

Arduino 7 - Push button switch to toggle LCD backlight LED (other pin of the switch to GND)
Arduino 9 - Push button switch for future versions (other pin of the switch to GND)
Arduino 12 - Push button switch to mark current position (other pin of the switch to GND)

Arduino 11 - speaker (other pin of the switch to GND)

Step 5: Arduino Programming

1. LCD Driver

First of all, I searched for a simple and small library for the LCD, Nokia 5110. There were a few different libraries for this LCD: Adafruit’s, Sparkfun’s, and Henning Karlsen’s. Among these libraries, I chose Henning Karlsen’s because I needed only simple text display with a couple of different font sizes. Henning Karlsen has separate library for graphics as well. I would like to thank Henning for his sharing his nice work on the library. Henning’s library supports 3 different font sizes: SmallFont (text and number, 6×8), MediumNumber (number only, 12×16), and BigNumber (number only, 14x 24). Only downside of this library is that the Medium and Big fonts do not support texts but only numbers. However I would need only numbers to display with bigger fonts, this limitation was no problem with me.

2. Distance calculation between two locations

There are number of websites showing how to calculate distance between two locations from latitudes and longitudes. Movable Type Scripts shows various calculations of distance, bearing and other useful conversions using Haversine formula and BlueMM posted the Excel formula to calculate distance which is basically the same way as Haversine.

The calculation is quite straightforward but I found there was a problem: Arduino (Atmega328p) cannot handle over 6-7th decimal digits which is very important in trigonometric calculation for short distance.

Arduino reference page says “Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point. Unlike other platforms, where you can get more precision by using a double (e.g. up to 15 digits), on the Arduino, double is the same size as float.”

Let me give you an example. Suppose we started from a position A (lat: 40.00, long: 80) to a position B (lat: 40.01, long: 80.00). That is, we moved 0.01 degrees in latitude only. If you calculate the distance using Haversine formula on your PC, you will get about 1,111.9m. However, Arduino calculates it as 3,110.8m. Big error! More interesting thing is that even if you reduce the latitude difference to 0.001 or 0.0001 degrees, you get the same results, 3,110.8m. So I investigate further what exactly cause this error. Of course I know the culprit is the float precision limitation as said above. But I wanted to know which part of the calculation by Arduino cause this big error. In the Haversine formula, there are COS, SIN and ACOS functions used. I tested a few different calculations using these functions and found the calculation of COS and SIN functions affect minimal but the problem was the ACOS. If you calculate the formula on your PC only inside of ACOS bracket, you will get 0.9999999848. See my point? The decimal places below 6th in ACOS function is actually important to calculate the angular difference for small distance, but unfortunately Arduino cannot handle this. Not only for small distance but for even relatively long distance (say over 1 degree for instance) there is error between the results on the PC and Arduino.

Well, so I started thinking about how to avoid trigonometric function calculation when over 6th decimal places are important. And I found a solution! Instead of calculating angular difference between two positions and THEN calculating the distance by multiplying the mean earth radius, calculating a ratio of angle between two positions (latitude and longitude separately) over 360 degrees and divide the circumference of the earth by this ratio. In other words, keep the numbers big while calculation. Arduino’s float type has a limitation on the small decimal places, but can handle relatively big numbers!

Here is my formula:

The mean circumference of the earth is 2 x 6,371,000m x π = 40,030,170m

Δd (lat) = 40,030,170 x ΔΘ (lat) / 360 (assuming ΔΘ is small)

Δd(long) = 40,030,170 x ΔΘ(long) x cosΘm / 360 (Θm: mean latitude between two positions)

Now, the distance is √[Δd (lat)^2 Δd (long)^2]


I have tested this method by measuring distance from home to my work and it worked fine. First of all, I got the coordinates of my home and my work and then calculated the distance by Haversine method and by my formula shown above. There is some difference in the results but negligeable.

Arduino sketch is attached. The LCD library can be downloaded from here.

Thank you for reading my Instructable. Hope someone find this useful.

Share

    Recommendations

    • Optics Contest

      Optics Contest
    • Electronics Tips & Tricks Challenge

      Electronics Tips & Tricks Challenge
    • Plastics Contest

      Plastics Contest

    4 Discussions

    0
    None
    JohanDoornen

    Question 2 months ago on Step 1

    Wow, Not only a clever idea, but also a nice interpretation.

    I'm a technician, but not able to concentrate so well to think the formula's out and after that program it in nice lib's.

    For a project with a sports team (ski racing) I'm developing some extra time mesurement objects at this moment.

    These objects are part of a project where we are building a platform to gain more information about the performance of the racers, by adding the timing results of the training in a database that is realtime available for the trainers.

    The idea is to set up two optical gates on the track, and then calculate the speed by mesuring the time between the passage of the 2 gates, in relation to the distance between the two gates.

    To calculate the time between the two gates, we need to synchronise the time for both the gates. I'm thinking about using a GPS receiver as a very precize time base. But with your information, it should be also possible to calculate the distance with the aid of the GPS source instead of mesuring by hand an ad the information in the system befor use. I didn't expect that this should be so precise. So now I have to receive and calculate the exact time of passing the optical gate's, but also automaticaly the distance between the two gates. Then calculate the speed and show the information on a display along the track and send it to the trainers at the finisch. For communication i'll use LoRa.

    I'll have some kind programmer's who will help me with sorting out the right Lib's and formula's. I'm more the technical guy and I'm gathering all the components and working out the concept, including all the electronics, chargers, bateries and communications.

    Do you have any clever advice on this subject? Probably there are new knowlage because your project is already 5 years old.

    Would you be interested to assist with your knolage on this subject, that would be wonderfull.

    With kind regards,

    Johan (Netherlands).

    Ps, For use in the indoor accomodation in our area, we will still use a simple version with a fixed distance between the gates and a wired configuration, because it is quite difficult to synchronise the timebase of the two gates so precise, that we think to use a wired link between the two gates there. Communication between the gates and the display and the central timing computer will be build with LoRa communication.

    1 more answer
    0
    None
    JeonLabJohanDoornen

    Answer 2 months ago

    Hi Johan,

    That's quite interesting project. My concern is how fast the GPS data need to be updated. Recently I have posted another GPS related project (

    https://jeonlab.wordpress.com/2018/03/10/golf-gps/) using PA6C GPS module. Its datasheet says its update rate is 10Hz, but due to other calculations on the microcontroller, actual update is much slower than that. I guess your project needs pretty fast update to measure the time difference between two positions. How far is the distance between those two gates and what resolution of time measurement do you need?

    0
    None
    VaskoT

    2 years ago

    I have been always frustrated from the missing double (64bit) type in Arduino world and hence the problem with properly calculating GPS distance, bearing and destination point.

    The following library uses Float64 & Math64 libs and also adds some fast and very fast implementations of trigonometric functions and fast and regular versions of GPS GPS distance, bearing and destination point.

    Feel free to use it - and any help in improving it is welcome !

    https://github.com/vtomanov/Gps64

    0
    None
    josep75

    2 years ago

    Wow, very good, simple and practic.