Introduction: GoFly - Paragliding/hangliding/gliding Altimeter-variometer From Your Car Navigation

GoFly is a project based on PNA (car navigation devices with Windows CE), LK8000 tactical fligh computer software and variometer (altimeter) external input based on Arduino board and pressure sensor.

Why?
   -You can build this for about 150$, 
   -Your ordinary PNA (Personal Navigation Assistant) changes to really nice, high end flying computer, with lot of features and Arduino based altimeter and variometer let You see in real time your altitude, vertical and horizontal speed,
    -Software let You log your flight in logfile, that is approved by FAI, so You can always claim Your flights in any competition,
    -most PNA devices are much cheaper than dedicated flying devices
    -GoFly gives You also nice altitude changing sound so You dont need to look into screen all the time to see what is going on in the air
    -easily support competition tasks, with easy to understand user interface
    -your PNA is still very good car navigation system, so it will be peace of cake to come back from any XC flying

Short film with my 3rd version of device.

Step 1: How This Project Works

So basically, device is based on two devices. First one is a PNA (car navigation) device which let You run extra software (LK8000 in that case) and second one is Arduino based altimeter/variomter.
Most PNA devices on the market works under Windows CE environment. When You turn on PNA, device is booting up and autostart navigation software. There is a lot of information over the internet how to "unlock" PNA devices to be able to run other software.
Other important thing is that we need physical interface to connect Your unlocked PNA do Arduino board. Many PNA devices has built in USB interface, but unfortunately we are not able to connect PNA with Arduino over typical USB pna port. But some devices (like few Mio models) also support serial interface (TTL logic, 3.3V) over usb port.
Second device is an Arduino board (Pro, Mini Pro, Nano) based on 3.3V logic with Atmega328 microcontroller, with pressure sensor board, speaker and extra battery holder. Arduino board is processing in real time air pressure, temperature, vertical speed (m/s) and pushing those values few times per second over dedicated protocol to PNA device running LK8000 software. LK8000 is taking those values and present in nice form on PNA screen during flight. Also very nice feature of every altitude/variometer is beeping noise sound. Arduino, when pilot is gaining altitude is beeping faster and faster letting You know that You are inside rising air. Rising hot air is what we called thermalls. During great flyable weather day pilots are able to soar hours, that is why we need extra battery pack. Average PNA device is capable to run without external power around 2 hours (about 300-400mAh power consumption with average 750-900mAh battery inside). Providing extra power let You fly few more hours with highest lcd brightness.
If anybody ask why doing all that if there is a lot of different devices for flying, new palmphones, iphones, android devices with dedicated software. The answer is easy for me. Most dedicated flying devices price range is around 500-1500$, user interface is miserable, with gray-scale LCD screens, with lack of information and less features. Iphone/Android devices cost also a lot, and flying software is using GPS based altitude to measure Your speed and altitude change. Unfortunately this is not enough. GPS latency is to big for usable real time thermalling.
So,basically  the idea is to find cheap, nice looking PNA device, with good lcd screen, that we can see even in direct sunlight, unclock it, put LK8000 software on it, build small altitude/variometer device based on Arduino board with serial and sound output and connect everything together.
Also even without PNA navigation connected to GoFly, this is still full functional sound variometer device.

Step 2: What We Need?

1. Mio Moov s501, s401 or Mio M400 car navigation system (You can do research over the internet to find other suitable devices). You can find those devices on ebay for around 35-70$ (You can also use other pna, but remember, we need good lcd screen and serial TTL 3.3v input). Mio is already tested by many paraglider/glider pilots.

2. Arduino Microcontroller board (look at your local Radioshack or SparkFun.com). You can start with ful size board, but if You feel confortable with small Arduino Mini and Nano board after some experience I think is a better choice.

3. Pressure sensor board
Those are very sensitive devices (resolution is about 25cm of altitude change) bt ou have to use some good algorithms to filter noise from those sensors.

4. Good rechargeable batteries are very important. I think eneloops are one of the best on the market and using rechargeable is also environmental friendly :)

5. To be able to program Arduino boards we need USB-serial programming interface (or cable).

6. Good to have is 6xAA or 4xAA battery enclosure. I used 4xAA but later I found 6xAA battery enclosure

7. To be able to connect arduino with PNA navigation we need 5 wire angle usb cable (available at argentdata.com)

8. To here some sound we need small speaker (available also at Radioshack.com)

9. And the last most important part is enclosure. You can find those at Digikey.com or Mouser.com. Remember that enclosure has to be big enough to fit batteries, arduino board, pressure sensor and speaker.


Check out my project site to find out more about parts, ideas and ways you can do that.
https://sites.google.com/site/jarosrwebsite/para-nav

Step 3: Unlocking PNA Device...

On the beginning I'm not responsible for any damage of Your device. Always do backup. Keep manufacturer recovery software/CD/DVD in case of emergency. Do some research first about unlocking navigation devices. Remember You will loose Your warranty.

Unlocking software (this software will let you enable hidden Windows CE environment).
Unlock is based on some scripts http://projects.lanik.org/GPSProject_00.htm and http://www.glidertools.com/

DOWNLOAD M400_LK8000_UNLOCK_16.11.2011v.zip

DOWNLOAD MIO_S501_S401_LK8000_UNLOCK_16.11.2011v.zip

This Mio unlock version is prepared for Mio S501/S401 (with Navman map folder) and M400 (not tested personally by me)
This Mio unlock contain LK8000 v2.2e, S-E part of USA maps, paragliders polars and USA airspace maps.
There is also device manager to quick check under which serial port GPS unit works, mp3 player to play some music during parawaiting, desktop rotating app for LK8000.  All software is free. You can access to system files using files explorer
(extra apps and games are not part of the unlock software).

LK8000 and all necessary files for unlock software are installed on build in memory (not SD card).
You can put extra programs, and other files to SD card if You want to. (Mio S-devices have integrated SD card slot)
Anytime You can upgrade LK8000 just overwriting LK8000 folder, but always keep your profile and setting files to avoid setting up LK8000 again from the beginning.
This unlock is tested only on Mio S501/S401. I don't know how this unlock will work on others Mios. There are small differences between different Mio models (folders structure, backlight control, etc.) so I AM NOT RESPONSIBLE if you'll brick your Mio.
At Mio support website I found recovery software (SmartST_S501_v6_10_0056.exe) for my Mio S501 to bring Mio device to manufacture state (software recovers all folders content). Because I was playing a lot with files, I had to recover my mio few times before I finished Unlock software. It is good to have this recovery software and backup You entire data from Mio memory before You attempt to do some changes. Of course You need also Mio user application to recover Your maps.

How to install unlock:
    Preparing:
    1. Backup Your entire memory content from Your mio to Your harddrive. If something will go wrong, You can always recover mio system drive do original state. One important file during unlock is changed so after unlock if You do not have backup there will be only hard way to recover Your Mio to manufacture state. The most important thing is to have usb connectivity. I've never lost usb, but I've read that some folks bricked mio forever.
    Installing:
    2. Connect Mio using usb to Your computer. Restart Mio. You should get usb connectivity and removable media should show up on Your computer.
    3. Download and Unpack S501_LK8000_UNLOCK software to Your computer
    4. Copy all folders to Your Mio S501 memory, During copy process some files have to be overwritten. All files must be copy direct to the root folder of mio memory.
    5. Turn off the device into the reset position, wait a few seconds and then switch on again (Hard Reset)
    6. After 10-30 seconds You should get new nice looking mio desktop :) with GoFly wallpaper.
    7. USB connection works only if You connect Mio to usb cable first and do hard reset.

If You are familiar with folders, settings files, some scripting, I think after few short nights You should be able to move this unlock software to any m,s-series mio...
Good luck.

Step 4: How to Build This Project?

Take Your soldering gun and ready, set, go....On this step I will show You how my first GoFly project was build. After some time I was changing enclosures, ideas and schematics, but this instructable is the easiest approach to make final project.
1. Some explanation to schematic
- I used speaker instead of piezo to get louder sound. Also put small transistor to make amplifier. Up there is windy sometimes...
- In that scenario I used full size Arduino board, but feel free to use other Atmega328 based arduino boards.
- To save some money I used pressure sensor without breakoutboard. It was really hard to solder this microchip, so buy pressure sensor board, it is much easier...
- To enable Serial Interface inside PNA device You have to short Pin 4 and Pin 5 inside usb port.  Check cables colors with pins before You start soldering
- Integrated voltage regulator on Arduino Pro board let You use voltage range from 3.7 to 12 volts.
- As You can see, battery pack is providing power to Arduino and to PNA device over USB port.
-Of course we need power switch between power source and device. You can use different switches to turn on/off power and which can easly  fit Your enclosure.

3. After some investigation, plastic enclosure with battery slot is not good. Better option will be to buy enclosure with bigger battery door.


4. Velcro tape is doing really nice job. Also use some piece of rope to make Your project more handy and harder to loose during flight.


5. Assembled and ready to fly. As You can see, even without PNA navigation, GoFly project is still full functional sound variometer device

Step 5: Programming Your Arduino...

So finally we have project ready to put some code inside.

How to setup programming environment?
You can find everything on this page.
http://arduino.cc/en/Guide/Windows

Program listing.
You need Arduino 1.0 environment to compile this program. You also need few extra libraries.
http://code.google.com/p/bmp085driver/
http://code.google.com/p/rogue-code/
I did some programming long time ago (over 10 years ago) so this program is not perfect. Based on what I found on the internet, some learning, trying and references websites.
There is a lot of comments to let You understand how this program is working.

/*
Arduino Vario by Jaros, 2012 (dedicated to atmega328 based arduinos)
Part of the "GoFly" project
https://sites.google.com/site/jarosrwebsite/para-nav
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

Arduino board creates NMEA like protocol with variometer output and beping sound.
LK8000 EXTERNAL INSTRUMENT SERIES 1 - NMEA SENTENCE: LK8EX1
VERSION A, 110217

$LK8EX1,pressure,altitude,vario,temperature,battery,*checksum

Field 0, raw pressure in hPascal:hPA*100 (example for 1013.25 becomes 101325)
no padding (987.25 becomes 98725, NOT 098725)
If no pressure available, send 999999 (6 times 9)
If pressure is available, field 1 altitude will be ignored
Field 1, altitude in meters, relative to QNH 1013.25
If raw pressure is available, this value will be IGNORED (you can set it to 99999
but not really needed)!(if you want to use this value, set raw pressure to 999999)
This value is relative to sea level (QNE). We are assuming that currently at 0m
altitude pressure is standard 1013.25.If you cannot send raw altitude, then send
what you have but then you must NOT adjust it from Basic Setting in LK.
Altitude can be negative. If altitude not available, and Pressure not available, set Altitude
to 99999. LK will say "Baro altitude available" if one of fields 0 and 1 is available.
Field 2, vario in cm/s
If vario not available, send 9999. Value can also be negative.
Field 3, temperature in C , can be also negative.If not available, send 99
Field 4, battery voltage or charge percentage.Cannot be negative.If not available, send 999.
Voltage is sent as float value like: 0.1 1.4 2.3 11.2. To send percentage, add 1000.
Example 0% = 1000. 14% = 1014 . Do not send float values for percentages.
Percentage should be 0 to 100, with no decimals, added by 1000!
Credits:
(1) http://code.google.com/p/bmp085driver/                             //bmp085 library
(2) http://mbed.org/users/tkreyche/notebook/bmp085-pressure-sensor/    //more about bmp085 and average filter
(3) http://code.google.com/p/rogue-code/                               //helpfull tone library to make nice beeping without using delay
(4) http://www.daqq.eu/index.php?show=prj_sanity_nullifier             //how to make loud piezo speaker
(5) http://lk8000.it                                                   //everything because of that
(6) http://taturno.com/2011/10/30/variometro-la-rivincita/             //huge thanks for Vario algorithm
(7) http://code.google.com/p/tinkerit/wiki/SecretVoltmeter             //how to measure battery level using AVR ucontroller
*/

#include <Wire.h>                      //i2c library
#include <BMP085.h>                    //bmp085 library, download from url link (1)
#include <Tone.h>                      //tone library, download from url link (3)
#include<stdlib.h>                     //we need that to use dtostrf() and convert float to string
/////////////////////////////////////////
///////////////////////////////////////// variables that You can test and try
short speaker_pin1 = 8;                //arduino speaker output -
short speaker_pin2 = 9;                //arduino speaker output +
float vario_climb_rate_start = 0.4;    //minimum climb beeping value(ex. start climbing beeping at 0.4m/s)
float vario_sink_rate_start = -1.1;    //maximum sink beeping value (ex. start sink beep at -1.1m/s)
#define SAMPLES_ARR 6                  //define moving average filter array size (2->30), more means vario is less sensitive and slower
#define UART_SPEED 9600                //define serial transmision speed (9600,19200, etc...)
/////////////////////////////////////////
/////////////////////////////////////////
BMP085   bmp085 = BMP085();            //set up bmp085 sensor
Tone     tone_out1;
Tone     tone_out2;
long     Temperature = 0;
long     Pressure = 101325;
float    Altitude;
int      Battery_Vcc = 0;             //variable to hold the value of Vcc from battery
const float p0 = 101325;              //Pressure at sea level (Pa)
unsigned long get_time1 = millis();
unsigned long get_time2 = millis();
unsigned long get_time3 = millis();
boolean  thermalling = false;
int      my_temperature = 1;
char     altitude_arr[6];            //wee need this array to translate float to string
char     vario_arr[5];               //wee need this array to translate float to string
int      samples=40;
int      maxsamples=50;
float    alt[51];
float    tim[51];
float    beep;
float    Beep_period;
static long k[SAMPLES_ARR];

static long Averaging_Filter(long input);
static long Averaging_Filter(long input) // moving average filter function
{
  long sum = 0;
  for (int i = 0; i < SAMPLES_ARR; i++) {
    k[i] = k[i+1];
  }
  k[SAMPLES_ARR - 1] = input;
  for (int i = 0; i < SAMPLES_ARR; i++) {
    sum += k[i];
  }
  return ( sum / SAMPLES_ARR ) ;
}

void play_welcome_beep()                 //play only once welcome beep after turning on arduino vario
{
  for (int aa=300;aa<=1500;aa=aa+100)
  {
    tone_out1.play(aa,200);             // play beep on pin 8 (note,duration)
    tone_out2.play(aa+3,200);           // play beep on pin 9 (note,duration), it is louder if we move aplitude phase
    delay(100);
  }
  for (int aa=1500;aa>=100;aa=aa-100)
  {
    tone_out1.play(aa,200);             // play beep on pin 8 (note,duration)
    tone_out2.play(aa+3,200);           // play beep on pin 8 (note,duration)
    delay(100);
  }
}

long readVcc()                         // function to read battery value - still in developing phase
{
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1126400L / result; // Back-calculate AVcc in mV
  return result;
}

void setup()                // setup() function to setup all necessary parameters before we go to endless loop() function
{
  Serial.begin(UART_SPEED);       // set up arduino serial port
  Wire.begin();             // lets init i2c protocol
  tone_out1.begin(speaker_pin1);       // piezo speaker output pin8 -
  tone_out2.begin(speaker_pin2);       // piezo speaker output pin9 +
  bmp085.init(MODE_ULTRA_HIGHRES, p0, false);
                            // BMP085 ultra-high-res mode, 101325Pa = 1013.25hPa, false = using Pa units
                            // this initialization is useful for normalizing pressure to specific datum.
                            // OR setting current local hPa information from a weather station/local airport (QNH).
  play_welcome_beep();      //everything is ready, play "welcome" sound
}

void loop(void)
{
  float tempo=millis();
  float vario=0;
  float N1=0;
  float N2=0;
  float N3=0;
  float D1=0;
  float D2=0;
  bmp085.calcTruePressure(&Pressure);                                   //get one sample from BMP085 in every loop
  long average_pressure = Averaging_Filter(Pressure);                   //put it in filter and take average
  Altitude = (float)44330 * (1 - pow(((float)Pressure/p0), 0.190295));  //take new altitude in meters
  //Serial.println(Battery_Vcc);
  for(int cc=1;cc<=maxsamples;cc++){                                   //samples averaging and vario algorithm
    alt[(cc-1)]=alt[cc];
    tim[(cc-1)]=tim[cc];
  };
  alt[maxsamples]=Altitude;
  tim[maxsamples]=tempo;
  float stime=tim[maxsamples-samples];
  for(int cc=(maxsamples-samples);cc<maxsamples;cc++){
    N1+=(tim[cc]-stime)*alt[cc];
    N2+=(tim[cc]-stime);
    N3+=(alt[cc]);
    D1+=(tim[cc]-stime)*(tim[cc]-stime);
    D2+=(tim[cc]-stime);
  };

  vario=1000*((samples*N1)-N2*N3)/(samples*D1-D2*D2);
  if ((tempo-beep)>Beep_period)                          // make some beep
  {
    beep=tempo;
    if (vario>vario_climb_rate_start && vario<15 )
    {
      Beep_period=350-(vario*5);
      tone_out1.play((1000+(100*vario)),300-(vario*5)); //when climbing make faster and shorter beeps
      tone_out2.play((1003+(100*vario)),300-(vario*5));
      thermalling = true;                               //ok,we have thermall in our hands
    } else if ((vario < 0 ) && (thermalling == true))   //looks like we jump out the thermall
    {
      //Beep_period=200;
     // play_siren();                                   //oo, we lost thermall play alarm
      thermalling = false;
    } else if (vario< vario_sink_rate_start){           //if you have high performace glider you can change sink beep to -0.95m/s ;)
      Beep_period=200;
      tone_out1.play(300,340);
      tone_out2.play(303,340);
      thermalling = false;
    }
  }

  if (millis() >= (get_time2+1000))      //every second get temperature and battery level
  {
    bmp085.getTemperature(&Temperature); // get temperature in celsius from time to time, we have to divide that by 10 to get XY.Z
    my_temperature = Temperature/10;
    Battery_Vcc =(readVcc()/42)+1000;    // get voltage and prepare in percentage
    get_time2 = millis();
  }

if (millis() >= (get_time3+333))       //every 1/3 second send NMEA output over serial port
  {
    String str_out =                                                                 //combine all values and create part of NMEA data string output
      String("LK8EX1"+String(",")+String(average_pressure,DEC)+ String(",")+String(dtostrf(Altitude,0,0,altitude_arr))+String(",")+
      String(dtostrf((vario*100),0,0,vario_arr))+String(",")+String(my_temperature,DEC)+String(",")+String(Battery_Vcc,DEC)+String(","));
    unsigned int checksum_end,ai,bi;                                                 // Calculating checksum for data string
    for (checksum_end = 0, ai = 0; ai < str_out.length(); ai++)
    {
      bi = (unsigned char)str_out[ai];
      checksum_end ^= bi;
    }
    //creating now NMEA serial output for LK8000. LK8EX1 protocol format:
    //$LK8EX1,pressure,altitude,vario,temperature,battery,*checksum
    Serial.print("$");                     //print first sign of NMEA protocol
    Serial.print(str_out);                 // print data string
    Serial.print("*");                     //end of protocol string
    Serial.println(checksum_end,HEX);      //print calculated checksum on the end of the string in HEX
    get_time3 = millis();
}
}
//The End

Step 6: What Next...

Last thing to do is setup LK8000, to be able to understand what Arduino is saying. Also we have to setup few things to meet our flying requirements.
All details how to setup LK8000 software are available on my project website
https://sites.google.com/site/jarosrwebsite/para-nav

Step 7: New Ideas...

Later I was improving my project. So I will show You different approach...

Step 8: And Another One...

Third approach using Arduino mini boards. After some changes inside original Mio enclosure You can fit everything inside and make really nice, handy Altitude/Variometer for Paragliding / Hangliding / Glider pilots.

THANKS everyone for Your time.
Jarek