GPS bike computer/navigator

Been working on a GPS based bike computer with the overall objective of creating and implementing everything with what's wrong with my current device, the Garmin Forerunner 405CX.

Current specs:
GPS: VK2828U7G5LF
LCD: 2.2" ILI9341 (320x240)
Micro: Arduino Due
1x 25Q128FVSG (16 megabyte) SPI flash, soon to be 1x25Q256FV (32MB)
2GB micro and 128mb standard SD cards.
4x micro-switches for buttons.
Powered from 2x18650 batteries.

10hz internal GPS update rate with 1second or less interval datalogging (Forerunner records once per 6 to 9 seconds) to SD once a predetermined quantity has been reached.
Outputs logs via SerialUSB in either raw form and CSV for processing PC side, or a usable TCX file. Fo r example; for uploading direct to Strava.

Currently there is only one display view but this will change once the buttons (micro switches) are added.

TODO (hardware):
Add a dedicated micro SD reader.
Add the Mag and Gyro sensors for both internal use and data logging.
Investigate using an accelerometer for cadence
Shove a Temp sensor in somewhere.
Bluetooth HC-05 module for Heartrate and/or Andriod accessibility. Could possibly use nRF24AP2 If I want to go the more expensive ANT+ route.
Wifi integration via ESP8266-G (because thats what I've got).

PC side software is in a much more completed state than the hardware, given its longer (and previous) development time, as can be viewed from the snapshot images.

Battery:
Originally I was using a battery taken from a Samsung Galaxy phone (the one with the self-contained NFC coil on the back) with a charge controller and boost converter added. This provided around 2hrs usage on a full charge but with nothing in the way of power management implemented.
Now I'm using two new and rather expensive 18650 2400mah Unicross batteries, which are providing over 10hrs always on (non idle) runtime.
Also have a few 18650 8.4v battery packs to try out.

Notes on attachments:
On the display, the green trace is the route I've just cycled today, in 3 second intervals with a 15 sample (1.5s) rolling sample bucket.
Yellow/Red circles are the currently tracked Satellites.
The Red '3d' means I have a 3D Sat fix and that datapoints will not be logged. 2D for 2D fix and green indicates datalogging is enabled. (what not moving logging is disabled).
6.x below that is the accuracy in meters (usually around 0.4 - 0.5m when outdoors).
0 is speed in km/h

Update:
Implemented SD storage, using both a 2gb Micro card and an old 128mb (x2 the performance of the 2gb!) SD card.
Improved route rendering; now down to less than 10ms per render pass.

External libs in use:
ILI9341_Due modified for improved single point write ops.
TinyGPSPlus extensively modified and supplemented with my own ublox specific library.
SDFat unmodified (using fat32 here as anything else seemed unstable).

Other:
SerialUSB internal buffer increased to 2048bytes, which helped improve XML route/activity transfers to PC.
Now powered from a single cell 18650.



amazing project, congratulations!
Appears to work excellent - or do you encounter issues?

I'm working with a GPS Modul GY-NEO-6M V2 + TinyGPS libs which is also working fine to me (not for a bike bur for an autonomous robot).

For my own purposes I was thinking about a way to download street maps for a screen overlay (e.g., Google maps or OSM maps) ? - what do you think about this idea?

Cheers.

Totally new to the world of microcontrollers and Arduinos, so everything is an issue :slight_smile:

The overall outstanding issue for the project, as a whole, has been and continues to be, how to both encase and mount the device. Currently it's stuffed inside a pink anti-static bag which is affixed to stem/bar (bike) via black insulating tape.
Would love to create a bespoke enclosure but that might involved stepping far outside of my technical ability.

One issue could be 'render flicker' (i'm sure its probably known as something else). Internally, rendering occurs once per second, whether there is something new to display, or not. This brings with it the issue of refresh flicker (erasing old/writing new), particularly where text is involved. An 8bit (256 colour) 320x240 display mode would help here, but supported by the ILI9341. Will investigate using a Pio display.

Having looked in to this already, IMO street maps is more than feasible and image downloading rudimentary. My preference is for having dynamic (somewhat realtime) zoom levels and its uncomplicated nature. With maps you're restricted to 1 of ~20 zoom levels with a map set per level. Could be quite expensive in terms or storage, processing and rendering.

This snippet might be useful if going the map route:

These were working the last time I checked
 static const char *mapURL = "%s http://www.openstreetmap.org/?mlat=%f&mlon=%f#map=%.1f/%f/%f";
//static const char *mapURL = "%s http://qa.poole.ch/?zoom=%.1f&lat=%f&lon=%f&layers=FFFF0B";
//static const char *mapURL = "%s http://www.google.co.uk/maps/place/%f+%f/@%f,%f,%.1fz?force=lite";



static inline void locationToWorldGrid (const int zoom, const double latitude, const double longitude, int *x, int *y)
{
 *x = (int)(256.0 * ((longitude + 180.0) / 360.0 * (1<<zoom)));
 *y = (int)(256.0 * ((1.0 - log(tan(latitude * M_PI / 180.0) +  1.0 / cos(latitude * M_PI / 180.0)) / M_PI) / 2.0 * (1<<zoom)));
}

static inline void worldGridToLocation (const int zoom, int x, int y, double *latitude, double *longitude)
{
 const double n = M_PI - ((2.0 * M_PI * y / 256.0) / pow(2.0, zoom));
 *latitude = (double)(180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))));
 *longitude = (double)(((x / 256.0) / pow(2.0, zoom) * 360.0) - 180.0);
}

static inline void locationToImageGrid (const int zoom, const double latitude, const double longitude, int *x, int *y)
{
 *x = (int)(/*256.0 * */((longitude + 180.0) / 360.0 * (1<<zoom)));
 *y = (int)(/*256.0 * */((1.0 - log(tan(latitude * M_PI / 180.0) +  1.0 / cos(latitude * M_PI / 180.0)) / M_PI) / 2.0 * (1<<zoom)));
}

static inline void imageGridToLocation (const int zoom, int x, int y, double *latitude, double *longitude)
{
 const double n = M_PI - ((2.0 * M_PI * y /*/ 256.0*/) / pow(2.0, zoom));
 *latitude = (double)(180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))));
 *longitude = (double)(((x /*/ 256.0*/) / pow(2.0, zoom) * 360.0) - 180.0);
}

Created a small bank switch (sic) on some prototype board, ready for install:
(4 wire and one common to VSS)


you do know these ones too, don't you?
http://www.ebay.de/itm/2pcs-1x4-4-Key-Matrix-Membrane-Switch-Keypad-Keyboard-Super-Slim-for-Arduino-uno-/191682279895?hash=item2ca12779d7:g:iIYAAOSwLVZV6XGE

http://www.ebay.de/itm/Matrix-Array-12-Key-Folientastatur-Schalter-Keypad-Fur-Arduino-AVR-4-x-3-Gut-Top-/261653490955?hash=item3cebc36d0b:g:VFIAAOSwDk5UFqsU

Discovered those after having ordered 100 micro switches for ~£1. After you posted those ebay links I then found these: http://www.aliexpress.com/item/8pcs-Push-Button-Switch-4-Keyboard-Module-key-Board-Keypad-for-Arduino-DUE-Breadboard-Leonardo-ZERO/32281455411.html

Hi!

Excellent project.

I've made a similar project with Atmega1284 and later with another platform (NavSpark), It's still developing

http://www.navsparkforum.com.tw/viewtopic.php?f=22&t=166&start=30

I use downloaded tiles from openstreetmap and use a similar function to show maps into screen.

Interesting project indeed if not a tad difficult to follow as everyone is called "Administrator" :). Similar is a slight understatement as we seem to be heading down almost identical paths', from layout to hardware (Bluetooth, compass, etc..) to navigation and what not.
At present I'm heading down a somewhat modular & configurable software implementation allowing one to select from a factory of stats; what to display, where, when and perhaps how, with emphasis towards fitness - as opposed to navigation, user configurable from file and SPI flash.

I see that you're using the Nokia battery, but no sign of battery protection/charge controller in sight. I'm curious how you're handling this.
How do you plan on encasing and/or mounting the device?

@iceman: is your OSM downloaded online in real-time or did you store it on your SD or flash offline?

Okio:
Interesting project indeed if not a tad difficult to follow as everyone is called "Administrator" :). Similar is a slight understatement as we seem to be heading down almost identical paths', from layout to hardware (Bluetooth, compass, etc..) to navigation and what not.
At present I'm heading down a somewhat modular & configurable software implementation allowing one to select from a factory of stats; what to display, where, when and perhaps how, with emphasis towards fitness - as opposed to navigation, user configurable from file and SPI flash.

I see that you're using the Nokia battery, but no sign of battery protection/charge controller in sight. I'm curious how you're handling this.
How do you plan on encasing and/or mounting the device?

Hi! Yes all are administrator because the forum was migrated, :slight_smile:

Yes it's a nokia battery and charger it's at PCB LCD bottom (middle PCB)

Yes , i hope on encasing it, maybe with a 3dprinted case, but some software code isn't finished

How its looking client side:
Displaying Route, Altitude, Speed, Heartrate and Cadence.

Okio:
How its looking client side:
Displaying Route, Altitude, Speed, Heartrate and Cadence.

Cool :slight_smile:

Installed on to MTB bike:

About to port this to the Teensy 3.6 so this is current state and final status with the Due.

Shouldn't forget about the battery.

Using two 18650's in parallel which were extracted from a 10 year old laptop.
Charging is via a micro USB connector from the underside in to this charge controller, which connects to this boost converter (connector removed) for the 5v supply.

For anyone interested, here is the complete source for this project: GitHub - MichaelMCE/GPS_NavMk1: Bespoke Bicycle GPS Navigator
It's named Mk1 because I've long since moved on to version 2, Mk2
WIP Video of Mk2: Vector map rendering for custom GPS navigaator/bike computer (1/2) - YouTube
and Bike Navigator/computer: Display 2km viewport and POI rendering - YouTube