Introduction: Reverse Geocache

First of all we would like to thank the organisation of the Ghent Arduino Jam Session and especially the main sponsor, Capgemini, which made all of this possible.

Target: make a GPS direction finder that shows the direction of the next waypoint, similar to a radio data finder.
The direction finder will be a great device for organising city (or country) search parties for e.g. scouting.
This was our project for the february 2012 Arduino Jam session that took place in timelab, Ghent Belgium.

The team:  Tom, Thomas and myself, see second picture.

Step 1: System Description

The direction finder has an on-off swith for connecting the internal battery.
There is an OK pusbutton to confirm reaching a waypoint.
A circular led display shows the relative direction to be followed, and several "message".

The device can also be fed from the USB connection to the PC, in which case thebattery can remain switched off.

The player has to find a number of waypoints, stored in the direction finder. As the player starts to move, the Leds on the frontpanel give the direction fo the waypoint, relative to the direction of the movement.

The frontpanel has 16 Led's. The Led's are placed at compass directions of 0°, +- 5°, +- 10°, +-15,+- 30°, +- 60°, +- 90°, +- 135° and 180°.
For improved aiming, the forward direction is more detailed then the others.
Also, the 0° Led.is a 5mm type, the others being 3mm.

After startup, a self test of the device is running untill the GPS module has found a fix. During this self test, the Leds blink in a slow circular movement.

As soon as the player starts moving, a single Led indicates the direction to the next waypoint.

When the player reaches a waypoint, the direction on the display will suddenly change.
The player then pushes the OK button.
If the player is sufficiently close to the waypoint, he/she is rewarded with a "mexican wave" by the Led's, and the device finder then switches to the next waypoint.
If the waypoint is not sufficiently close, the leds say "NO" (alternating the 90° and -90° leds).
After 3 faulty buttons pushes, the player is punished: the direction finder now points to the PREVIOUS waypoint.
When the last waypoint is found, a "Hurray" led display is shown.

Step 2: Bill of Material


Arduino Uno
Skytrack Venus 6  GPS module ST22
LED panel
On-off and pushbutton switch
3 AA batteries and a battery holder
74HCT595 shift register, 2 x  BC547 transistor, resistors: 2 x 10k, 1x 560ohm, 1 x 100nF condensor
A "shield" type experimentation PCB.
MDF device box, cut with a laser cutter.

Step 3: Hardware

An Arduino Uno is the core of the system. Its USB plug sticks out of the box for programming waypoints into the system.

The device is powered from 3 AA batteries.

Electrically, the Led's are arranged in a 8x2 matrix, formed by a 74HCT595 shift register and two transistors, coupled to Arduino outputs.
As only one LED is on at any moment, the shift register can easily source the 5 mA needed.

The GPS module provides latitude, longitude and heading (= direction in which the user moves). At the jam session, an older type was used, that consumes up to 110mA. The ST22 SkyTraq GPS Module consumes only 25 mA, which will allow for a longer battery life.

Hardware description:
The on-off swith just connects the batteries to pins 5V and GND.
The "OK" pushbutton is connected to Arduino pin 6
The shift register has following connetions to the Arduino: Data on pin 5, Clock on pin 2, Strobe on pin 3, Output Enable on pin 4
The "left" and "right" part of the display is controlled by NPN transistors,driven by pins A4 ans A5.
The GPS module connects to pins 11 (Rx) and 12 (Tx).

See schematic diagram below.

Step 4: The BOX

The FABLAB in Gent, where the JAM SESSION took place, has excellent facilities for such prototyping work.

The design was made with BoxMaker ref: http://boxmaker.rahulbotics.com/ and further adapted to include all holes and cutouts.
After format conversion for the laser cutter, it was cut out of a 4mm MDF board.

Bottom and sides were glued together. The lid fits snugly on top, allowing to change batteries.

Step 5: Software Intro

At the end of the Arduino jam session, the software for the direction finder was a work in progress. Basic parts worked and were tested: the Led matrix, the 'mexican wave' self test, the serial connection to a GPS module, extracting latitude and longitude, storing and retrieving float data types in EEprom. Also, work was started to download Waypoints from Google maps.

Since then, I put a lot of work in developing two separate sketches for the reverse geocache game:
 - a menu driven waypoint editor sketch: Geocache_menu
 - the game sketch: Geocache
See next steps.

Combining both sketches in a single sketch would be possible, but I kept them separated for following reasons:
  • both sketches are already rather big (12 and 15 kbytes)
  • unneeded complexity would be added
  • the sketches are executed by different people anyway.


As both programs have almost 400 lines, I split them up in smaller, manageable parts.
E.g. the Geocache sketch has a game logic part, a LED handling part, a waypoint memory handler, a GPS module handler.

Writing and debugging the sketches was done methodically:
  • A small sketch was prepared for every sub item
  • A lot of serial monitoring messages were included for following the program flow, checking input and output variables etc.
  • All possible input values were presented to the sketch and the reaction was evaluated
  • The sketch was debugged untill the result was up to expectation
Then, I integrated the seperate parts one by one in the overall sketch, testing and debugging as I went along.

Finally, the finished product was "field tested".
This still revealed shortcomings, e.g reaction on direction changes was too slow (I had to increase the GPS refresh rate -- back to the drawing board).
I removed most of the debugging stuff, and added comments for ease of maintenance.

I did not try to optimise the sketches for speed, memory size or general beauty.

Environment used: Arduino 1.0

Following libraries were included:
SoftwareSerial.h, used for the serial interface to the GPSmodule, next to the standard serial interface to the PC.

nmea.h for collecting GPS info.
This library offers more possibilities than he simpler TinyGPS library. Especially the "course_to" method proved necessary to clalculate the heading to a given latitude and longitude.
The library did not work as such. A patch is needed for using WProgram.h. After Bill Ho's patch was introduced in nmea.h and nmea.ccp, the sketch compiled OK. ref: http://arduino.cc/forum/index.php?action=profile;u=11017;sa=showPosts

EEPROM.h for storing the waypoint information in the Arduino EEprom.
The waypoint information, consisting of longitude an latitude, comes in float data types. Breaking up a float for storing and reconstructing it after retrieving from the eeprom proved to be a complicated matter. A specialist in  Arduino SW, C and C++,  had to be called in to help us out.

Step 6: Software: the Waypoint Menu

As a sailor, I know how difficult it is to type in a number of waypoints correctly.
Therefore I looked for a way to copy paste waypoints directly from Google maps. Waypoints are made up as latitude (N or S) and logitude (E or W). A typical input looks like: 50.846669,4.352514  (= Brussels, Grote Markt). Southerly latitudes and Westerly longitudes are negative values

How to copy from Google maps:
  • Open Google maps, type in the wanted environment
  • Navigate on the map to the exact point
  • Rightclick on the exact location, then choose "what is here?"
  • Copy (CTRL-C) latitude,longitude info from Google maps input box.
  • Paste this coordinates in the Arduino serial input box

I decided to make a separate waypoint sketch. It works via the Arduino serial monitor and is menu driven.

Memory map:
Every waypoint occupies 10 bytes:
  • 2x  4-byte float (latitude and longitude)
  • a 2-byte integer (Forward link to next waypoint adrress).

Details:
Byte 0 to 7 contain the title of the waypoint list.
Byte 8 and 9 store an integer, that points to the first waypoint address.
The first latitude is in byte 10-13, the first longitude in 14-17.
Byte 18 and 19 store the link to the next waipoint again.
Maximum capacity is 99 waypoints.
General: latitudes start at 10k, longitudes at 10k + 4, the links to the next latitude at 10k + 8. 
A '-1' in the link indicates the last waypoint in the list.

At startup, the sketch shows following menu (is not so nice here, but is well-aligned in the monitor)

******************************************
*                                                  *
*           Choose an action:             *
*                                                  *
*   SHOW all waypoints:           s   *
*   Enter a NEW waypoint list:   n   *
*   CHANGE a waypoint:           v   *
*   DELETE a waypoint:            d   *
*   ADD a waypoint:                  a   *
*                                                  *
*   HELP:                                 h   *
*                                                  *
******************************************

Actions:
  • NEW: all previous links are overwritten with '-2'. Then the user is asked to copy a number of waypoints in the serial monitor input box. The list is closed by inputting "#", which inserts '-1' in the link field.
  • SHOW: the waypoint list is displayed. On the monitor, each waypoint is preceded by a number to allow further editing. Note that these numbers are not necessarily consecutive after some add and delete actions.
  • DELETE: a waypoint is taken out from the list.
  • ADD: an extra waypoint can be inserted after a chosen waypoint number.
  • CHANGE: action allows to change the waypoint content at a chose number.
  • HELP:displays the way to copy waypoints from GoogleMaps.

Programming details:
The sketch checks for wrong inputs of menu actions and waypoint numbers.
There is no check on the waypoint content, as it is assumed to be copied from Google.
There are routines for reading and writing floats and integers to and from Eeprom.

Below are the routines for handling float values (4 bytes) in EEprom (we got some help from an expert here).
Similar routines were used for integers (2 bytes).
union FloatBinary
{
  float f;
  byte bytes[4];
};

void EepromWriteFloat(int adres, float value) {
  FloatBinary temp;
  temp.f = value;
  for (int i=0; i< 4; i++) {
    EEPROM.write(adres +i, temp.bytes[i]);
  }
}

float EepromReadFloat(int adres){
  FloatBinary temp;
  float out;
  for (int n=0; n<4; n++) {
    temp.bytes[n] = EEPROM.read(adres+n);
  }
  out =temp.f;
  return out;
}

Step 7: Software: the Game Sketch

The different modules in the sketch:

Setup:


The obvious items are setup and initialised: Serial monitor, GpsSerial to the GPS module, the Led driving shift register, all game variables.

During field testing, the standard 1Hz GPS update rate proved to be too slow.
I had to dig into the ST22 application notes and now send a number of binary setups to the GPSmodule.
  • Serial port interface begins at 9600 baud, then 38400 baud rat is set for the module and for the Gps-Arduino interface
  • The GPS refresh rate is raised to 8 Hz
  • The pedestrian navigation mode is set, adapting the GPS internal filtering
  • All unneeded NMEA sentences from the GPS are shut down, only GPRMC is kept
To my frustration, I was not able to show the GPS ACK and NACK messages, but I got proof that my messages are wel received.
Although it is possible, I did not store the above settings permanently in the GPS.

LED Handling:

The led display can display several messages:
  • Self test: leds are lit, one by one, in a slow way, while the GPS module tries to get a fix.
  • Searching next waypoint: led corresponding with relative bearing to waypoint is lit
  • waypoint found OK: the leds execute 2 fast 'mexican wave' movements.
  • NOK, waypoint not reached yet: leds say 'no' by alternating the 90° and -90° leds.
  • Punished: series of 10 fast NOK messages.
  • Hurray, last waypoint found & Game Over: series of fast mexican waves untill switched off.
Game logic:

At startup, the self test is shown, waiting for a fix.
When a fix is available, search mode is entered; as the player gets moving, the bearing to the next waypoint is shown.
After pressing the OK button, several situations are possible:
  1. the distance to the waypoint is within limits and the last waypoint is not reached: OK is shown,  the next waypoint is loaded and search mode entered
  2. the distance to the waypoint is within limits and the last waypoint is reached: Hurray is shown, game is over
  3. the distance is nok and this is the first or second error for this waypoint: after NOK display, the search continues
  4. the distance is nok for the third time: Punished is shown, the previous waypoint is loaded and search mode entered
GPS Handling:

Most of the interface to the GPS module is handled by the nmea.h library

Three outputs are used here:
  • heading, gps.gprmc_course(), the direction of the player's movement
  • bearing, gps.gprmc_course_to(latitude_Wp,longitude_Wp), the direction to the target waypoint
  • distance, gps.gprmc_distance_to(latitude_Wp, longitude_Wp, MTR), the distance to the target waypoint
The relative bearing, shown on the led display, is calculated by substracting bearing from heading, and bringing the result between 0° and 180°.
While an NMEA sentence is decoded character by chracter by nmea.h, it should not be interrupted. therefor this action is embedded in a "while (!decoded)" loop.

Memory Handling:

Modules: getNextWaypoint,getPreviousWaypoint, integer and float read routines

getNextWaypoint calculates the next Waypoint address form the current waypoint's link, and returns latitude and longitude of the next target waypoint. It also flags the end of the waypoint list when reached.

getPreviousWaypoint follows the waypoint link chain, starting from the bottom. Remark that the waypoints in memory are not necessarily consecutive, as the game master could have deleted or inserted waypoints in the list.

The retrieving routines for integers and floats are the same as in the menu sketch.

See sketch below.

Step 8: How to Use the ReverseGeocache

Game preparation:

Before a game can be played, the game master has to store a number of waypoints in the EEPROM memory of the Arduino.
This is done by connecting the direction finder to a PC and uploading the Geocache_menu sketch.
The menu contains a help section.
The on-off switch can remain in the off position, saving the batteries.
With the help of Google maps, the route to be followed is stored in the Arduino eeprom memory.
The game master can put in 1 to 99 waypoints in the route.

Game play:

To play the game, the GeoCache sketch is uploaded.
The direction finder is then ready to be swithed on and start the game.
See the system description step and the video for the game flow.

HAVE FUN !