Chrisroy
Published

Kayak GPS Navigation

Kayaking GPS: speed, time, latitude, longitude, distance and azimuth to waypoints, odometer, tide clock, battery monitoring.

AdvancedWork in progress2,338
Kayak GPS Navigation

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
TinyShield GPS
TinyCircuits TinyShield GPS
×1
TinyDuino Starter Kit – Lithium Version
TinyCircuits TinyDuino Starter Kit – Lithium Version
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

YAK GPS Mk ii CASING

Schematics

circuit

Code

Kayak GPS

Arduino
Navigation GPS powered by solar energy.
/*
*/

#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>

#include <avr/pgmspace.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  //8>RS,9>E, 4-7>D4-D7,RW>0V,
SoftwareSerial gpsSerial(2, 3); //RX, TX 2>bleuTX, 3>VertRX
TinyGPS gps;

byte clo_n = 0;
boolean eco_mode = false;
boolean pro_mode = false;
static int vref = 211; // 1023/4.9 volts
byte solPanel = 3;     //pin
byte batt = 4;         //pin
byte LCD_LED = 11;
byte power_pin = 12;
byte sw_sel = 14;// select
byte sw_up = 15;// up
byte sw_dwn = 16;//down
byte fonction = 0;
int gmt;//, hr ;
long Year_Min;
long Tide_one;
unsigned long time_On;
unsigned long time_run;
unsigned long time_old;

int year;//,  vinfo;
int menu_index = 0;
int cum_n;
static float rad2deg = 0.01745;
float Odometre;
char msg[6];
byte LCD_LED_N = 220;  //OFF 0-a-255 ON
byte col, row, nb = 0, bc = 0;                            // general
byte bb[8];
byte month, day, hour, minute, second, sped; //hundredths,
long lat, lon;                 //,  latmin, lonmin; //angle
long lat2 = 0;
long lon2 = 0;
long wp_lat, wp_lon ;

const char*azimuts[] = {"N  ", "NE ", "E  ", "SE ", "S  ",  "SW ",  "W  ", "NW " };
const char custom[][8] PROGMEM = {                        // Custom character definitions
  { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 }, // char 1
  { 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 2
  { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x03 }, // char 3
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 4
  { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1C, 0x18 }, // char 5
  { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F }, // char 6
  { 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 7
  { 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 8

};
const char bigChars[][8] PROGMEM = {
  { 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Space
  { 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // !
  { 0x05, 0x05, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00 }, // "
  { 0x04, 0xFF, 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01 }, // #
  { 0x08, 0xFF, 0x06, 0x07, 0xFF, 0x05, 0x00, 0x00 }, // $
  { 0x01, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x04 }, // %
  { 0x08, 0x06, 0x02, 0x20, 0x03, 0x07, 0x02, 0x04 }, // &
  { 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // '
  { 0x08, 0x01, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 }, // (
  { 0x01, 0x02, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00 }, // )
  { 0x01, 0x04, 0x04, 0x01, 0x04, 0x01, 0x01, 0x04 }, // *
  { 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01, 0x00, 0x00 }, // +
  { 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //
  { 0x04, 0x04, 0x04, 0x20, 0x20, 0x20, 0x00, 0x00 }, // -
  { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // .
  { 0x20, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x20 }, // /
  { 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00 }, // 0
  { 0x01, 0x02, 0x20, 0x04, 0xFF, 0x04, 0x00, 0x00 }, // 1
  { 0x06, 0x06, 0x02, 0xFF, 0x07, 0x07, 0x00, 0x00 }, // 2
  { 0x01, 0x06, 0x02, 0x04, 0x07, 0x05, 0x00, 0x00 }, // 3
  { 0x03, 0x04, 0xFF, 0x20, 0x20, 0xFF, 0x00, 0x00 }, // 4
  { 0xFF, 0x06, 0x06, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 5
  { 0x08, 0x06, 0x06, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 6
  { 0x01, 0x01, 0x02, 0x20, 0x08, 0x20, 0x00, 0x00 }, // 7
  { 0x08, 0x06, 0x02, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 8
  { 0x08, 0x06, 0x02, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 9
};

const static byte gpsDefault[] PROGMEM = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x07, 0x1F, 0x9E};
const static byte gpsSave[] PROGMEM = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x31, 0xBF, 0x13};
const static byte gpsSleep[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x16, 0x74};
const static byte gpsHot[]  = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x68};
const static byte Disable_GPDTM[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x44, 0x54, 0x4d, 0x2a, 0x33, 0x42, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x0a, 0x00, 0x04, 0x23}; //->Disable_GPDTM
const static byte Disable_GPGBS[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x47, 0x42, 0x53, 0x2a, 0x33, 0x30, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x09, 0x00, 0x03, 0x21}; //->Disable_GPGBS
const static byte Disable_GPGGA[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x47, 0x47, 0x41, 0x2a, 0x32, 0x37, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x00, 0x00, 0xfa, 0x0f}; //>Disable_GPGGA
const static byte Disable_GPGLL[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x47, 0x4c, 0x4c, 0x2a, 0x32, 0x31, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x01, 0x00, 0xfb, 0x11}; //->Disable_GPGLL
const static byte Disable_GPGRS[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x47, 0x52, 0x53, 0x2a, 0x32, 0x30, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x06, 0x00, 0x00, 0x1b}; //->Disable_GPGRS
const static byte Disable_GPGSA[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x47, 0x53, 0x41, 0x2a, 0x33, 0x33, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x02, 0x00, 0xfc, 0x13}; //->DisableGPGSA
const static byte Disable_GPGST[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x47, 0x53, 0x54, 0x2a, 0x32, 0x36, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x07, 0x00, 0x01, 0x1d}; //->Disable_GPGST
const static byte Disable_GPGSV[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x47, 0x53, 0x56, 0x2a, 0x32, 0x34, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x03, 0x00, 0xfd, 0x15}; //->Disable_GPGSV
const static byte Disable_GPRMC[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x52, 0x4d, 0x43, 0x2a, 0x33, 0x41, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x04, 0x00, 0xfe, 0x17}; //->Disable_GPRMC
const static byte Disable_GPVTG[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x56, 0x54, 0x47, 0x2a, 0x32, 0x33, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x05, 0x00, 0xff, 0x19}; //->Disable_GPVTG
const static byte Disable_GPZDA[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51, 0x2c, 0x5a, 0x44, 0x41, 0x2a, 0x33, 0x39, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xf0, 0x08, 0x00, 0x02, 0x1f}; //->Disable_GPZDA

///////////////////////////////////////////////////////
//           Minute depuis debut annee               //
///////////////////////////////////////////////////////
int days[] = {0,  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // Number of days at the beginning of the month in a not leap year.
long DofY(int yr, int mo, int dy, int h, int mi)
{
  int DfY;
  long Min2Date;
  if (mo == 1 || mo == 2)
  {
    DfY = days[mo] + dy - 1;                 //for any type of year, it calculate the number of days for January or february
  }
  else if ((yr % 4 == 0 && yr % 100 != 0) ||  yr % 400 == 0)
  {
    DfY = days[mo] + dy + 1 - 1;
  }
  else
  {
    DfY = days[mo] + dy - 1;
  }
  Min2Date = (long)DfY * 1440l + (long)h * 60l + (long)mi;
  return (Min2Date);
}
///////////////////////////////////////////////////////
//                      SETUP                        //
///////////////////////////////////////////////////////
void setup()
{
  pinMode(power_pin, OUTPUT);
  digitalWrite (power_pin, HIGH);   // POWER ON!
  analogReference(DEFAULT);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  Serial.begin(9600);
  gpsSerial.begin(9600);
  pinMode(LCD_LED, OUTPUT);
  //pinMode(buz, OUTPUT);
  pinMode(sw_sel, INPUT);
  pinMode(sw_up, INPUT);
  pinMode(sw_dwn, INPUT);
  lcd.begin(16, 2);
  analogWrite(LCD_LED, 100);

  ///////////////////////////////////////////////////////
  //                    EE PROM Variable               //
  ///////////////////////////////////////////////////////
  hour = EEPROM.read(0);                //lire le gmt
  pro_mode = EEPROM.read(4);
  EEPROM.get(10, wp_lat);
  EEPROM.get(15, wp_lon);
  EEPROM.get(20, Tide_one);
  EEPROM.get(25, Odometre);
  EEPROM.get(30, time_On);
  if (isnan(Odometre)) // test if NAN value
  {
    Odometre = 0;
  }
  if (hour > 127)                       //numbre negatif
  {
    gmt =  hour - 256;
  }
  else
  {
    gmt = hour;
  }
  ///////////////////////////////////////////////////////
  ///               R E V                             ///
  ///////////////////////////////////////////////////////
  lcd.clear();
  lcd.print(F("Ultimate YAK GPS"));
  lcd.setCursor(0, 1);
  lcd.print(F("GPS_1602B rev 92.1"));                                // Revision  Version<<<<
  delay (2000);
  lcd.clear();
  lcd.print("GMT="); lcd.print(gmt);
  float vbatt = (float) analogRead(batt) / vref + .21; //
  lcd.setCursor(0, 1);
  lcd.print(F("Batterie:"));
  lcd.print(vbatt);
  lcd.print("V");
  delay (2000);
  lcd.clear();
  lcd.print(F("Odometre:"));
  lcd.print(Odometre);
  delay (2000);
  lcd.clear();
  lcd.print("WPLat:");
  lcd.print(wp_lat);
  lcd.setCursor(0, 1);
  lcd.print("WPLon:");
  lcd.print(wp_lon);
  delay (2000);
  lcd.clear();
  lcd.print("Last Time ON:");
  lcd.setCursor(0, 1);
  lcd.print(time_On / 60000); lcd.print("Min");
  delay (4000);


  /*lcd.clear();
    lcd.print("TIDE: ");
    lcd.print(Tide_one);
    float a = (float)Tide_one / 288;   //288 = 24hr * 60/ 5 min/hr)
    int tide_jr = (int)a;
    float b = (a - (float) tide_jr) * 24;
    tide_hr = (int)b;
    tide_min = (b - (float) tide_hr) * 60 ;
    lcd.setCursor(0, 1);
    lcd.print(tide_jr + 1);
    lcd.print("Days ");
    lcd.print(tide_hr);
    lcd.print(":");
    lcd.print(tide_min);
    delay(2000);
  */


  if (vbatt < 2.8)//volts
  {
    lcd.setCursor(0, 1); lcd.print("Batt. LOW!");
    delay (4000);
    //digitalWrite(power_pin, LOW); //off
  }
  analogWrite(LCD_LED, 20);

  ///////////////////////////////////////////////////////
  //                    GPS Reset                      //
  ///////////////////////////////////////////////////////
  lcd.clear();

  if (gps.encode(gpsSerial.read()))
  {
    lcd.print("GPS Reset");
    gpsSerial.write(gpsHot, sizeof(gpsHot));  gpsSerial.flush();
    gpsSerial.write( gpsDefault, sizeof( gpsDefault));  gpsSerial.flush();
    gpsSerial.write( Disable_GPDTM, sizeof( Disable_GPDTM));  gpsSerial.flush();
    gpsSerial.write( Disable_GPGBS, sizeof( Disable_GPGBS));  gpsSerial.flush();
    gpsSerial.write( Disable_GPGLL, sizeof( Disable_GPGLL));  gpsSerial.flush();
    gpsSerial.write( Disable_GPGRS, sizeof( Disable_GPGRS));  gpsSerial.flush();
    gpsSerial.write( Disable_GPGSA, sizeof( Disable_GPGSA));  gpsSerial.flush();
    gpsSerial.write( Disable_GPGSV, sizeof( Disable_GPGSV));  gpsSerial.flush();
    gpsSerial.write( Disable_GPVTG, sizeof( Disable_GPVTG));  gpsSerial.flush();
    gpsSerial.write( Disable_GPGGA, sizeof( Disable_GPGGA));  gpsSerial.flush();
  }
  lcd.setCursor(0, 1); lcd.println(F("Wait satellites."));
  ///////////////////////////////////////////////////////
  ///           create 8 custom characters            ///
  ///////////////////////////////////////////////////////
  for (nb = 0; nb < 8; nb++ )
  {
    for (bc = 0; bc < 8; bc++)
      bb[bc] = pgm_read_byte( &custom[nb][bc] );
    lcd.createChar ( nb + 1, bb );
  }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                    L O O P                                                             ///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
  while (gpsSerial.available())                       // check for gps data
  {
    if (gps.encode(gpsSerial.read()))                 // encode gps data
    {
      gps.get_position(&lat, &lon);                   // get lat and long
      gps.crack_datetime(&year, &month, &day, &hour, &minute, &second);
      lat = lat / 100; //enlever les d-secondes
      lon = lon / 100;
      //     lcd.setCursor(0, 0); lcd.print (lat); lcd.print (" "); lcd.print (lon); delay (4000);
      hour = hour + gmt;
      if (hour > 128) //        reference a gmt
      {
        hour = hour + 24;
        day = day - 1;
      }
      ////Serial.print ("DofY=");//Serial.println (DofY (year,month,day,hour,minute));
      //Serial.print (year); //Serial.print ("/"); //Serial.print (month); //Serial.print ("/"); //Serial.print (day); //Serial.print (" "); //Serial.print (hour); //Serial.print (":"); //Serial.println (minute);
      Year_Min = DofY ((int)year, (int)month, (int)day, (int)hour, (int)minute);
      //Serial.print ("Year2min ="); //Serial.println (Year_Min);


      if (digitalRead(sw_sel) == LOW) {
        lcd.clear();
        while (digitalRead(sw_sel) == 0) {} //  wait for release
        menu(0);
      }
      if (digitalRead(sw_dwn) == LOW)
      {
        lcd.clear();
        while (digitalRead(sw_dwn) == 0) {} //  wait for release
        if (pro_mode == false)
        {
          lcd.clear();  lcd.print("PRO Display        ");
          delay (1500);
          pro_mode = true;
          EEPROM.write(4, pro_mode);
        }
        else
        {
          lcd.clear();  lcd.print("Dashboard MODE  ");
          pro_mode = false;
          EEPROM.write(4, pro_mode);
          delay (1500);
        }
        lcd.clear ();
      }
      ///////////////////////////////////////////////////////
      //           LCD LED  & test de batt                 //
      ///////////////////////////////////////////////////////
      float vsol = (float) analogRead(solPanel) / vref ; //    1024/2.5voltsRef
      if (eco_mode == true) {
        LCD_LED_N = 20;
      }
      else {
        LCD_LED_N = 150;
      }
      if (vsol > 1) {//volt
        vsol = 1;//volt
      }
      LCD_LED_N = LCD_LED_N - (vsol * LCD_LED_N);
      analogWrite(LCD_LED, LCD_LED_N);

      float vbatt = (float) analogRead(batt) / vref + .21; //    1024/5voltsRef
      if (vbatt < 2.8) // Volts  2.8
      {
        lcd.clear();  lcd.print("LOW BATT   ");
        lcd.setCursor(0, 1); lcd.print(vbatt); lcd.print("Volts");
        EEPROM.put(25, Odometre); //save odometre
        delay (5000);
        digitalWrite(power_pin, LOW);// power off
      }
      if (vbatt > 4.2) // Volts
      {
        analogWrite(LCD_LED, 255);
        digitalWrite(LED_BUILTIN, HIGH);
      }
      else
      {
        digitalWrite(LED_BUILTIN, LOW);
      }
      float speedf = gps.speed() * .01852;           // 1.852 /100  knot to kmph

      if (speedf < .5)
      {
        speedf = 0;
      }
      ///////////////////////////////////////////////////////
      ///                 ODOMETRE                        ///
      ///////////////////////////////////////////////////////
      if (cum_n >= 10)
      {
        if (lat2 == 0)
        {
          lat2 = lat;
          lon2 = lon;
        }
        cum_n = 0;
        float lon2_dec = lon2 / 10000.0;
        /////////////////////convert decimal degree into radian////////////////
        float lat1_Rad = lat / 10000.0 * rad2deg;
        float lon1_Rad = lon / 10000.0 * rad2deg;
        float lat2_Rad = lat2 / 10000.0 * rad2deg;
        float lon2_Rad = lon2 / 10000.0 * rad2deg;

        //Calculate the distance  KM
        float latSin = sin((lat1_Rad - lat2_Rad) / 2);
        float lonSin = sin((lon1_Rad - lon2_Rad) / 2);

        float P2P = 2 * asin(sqrt((latSin * latSin) + cos(lat1_Rad) * cos(lat2_Rad) * (lonSin * lonSin)));
        P2P = P2P * 6371;                      //Earth radius = 6,371 km

        if (P2P < 5 && speedf != 0)  // plus de 5 km est une erreur ou speed =0kmh
        {
          Odometre += P2P;
          lat2 = lat;
          lon2 = lon;
          EEPROM.put(25, Odometre);
          time_run = time_run + (millis() - time_old);
          
          EEPROM.put(30, millis()); //future reference
        }
        time_old = millis();
      }
      else
      {
        cum_n ++;
      }
      ///////////////////////////////////////////////////////
      //                 V I T E S S E                     //
      ///////////////////////////////////////////////////////

      dtostrf (speedf, 3, 1, msg) ;
      if (pro_mode == false)
      {
        writeBigString(msg, 0, 0);
        lcd.setCursor(7, 0); lcd.print ("KM    ");
        lcd.setCursor(7, 1); lcd.print ("/H    ");
        lcd.setCursor(10, 0);
        if (Odometre < 100)
        {
          dtostrf (Odometre, 1, 1, msg) ;
        }
        else
        {
          dtostrf (Odometre, 1, 0, msg) ;
        }
        lcd.print (msg); lcd.print ("KM   ");

        horloge (10, 1);
      }
      else
      {
        lcd.setCursor(0, 0);
        lcd.print(msg); lcd.print("KMH  ");//dtostrf (speedf, 3, 1, msg) ;
        Print_Azimut(8, 0);
        horloge(0, 1) ;
        ///////////////////////////////////////////////////////
        //          Display Fonction Variable                //
        ///////////////////////////////////////////////////////
        fonction++;
        switch (fonction / 3)
        {
          case 1:
            {
              Print_wpazimut(6, 1);
              EEPROM.put(30, millis());
            }
            break;
          case 4:
            {
              Print_Tide(6, 1);
            }
            break;
          case 2:
            {
              lcd.setCursor(6, 1);
              if (Odometre < 100)
              {
                dtostrf (Odometre, 1, 1, msg) ;
              }
              else
              {
                dtostrf (Odometre, 1, 0, msg) ;
              }
              lcd.print ("Od:"); lcd.print (msg); lcd.print ("KM   ");
            }
            break;
          case 3:
            {
              lcd.setCursor(6, 1);
              lcd.print ("Run:");
              if (time_run > 10000000L)//msec
              {
                lcd.print (time_run / 3600000L);//msec
                lcd.print ("Hr   ");
              }
              else
              { 
                lcd.print (time_run / 60000L);//msec
                lcd.print ("Min   ");
              }
            }
            break;
          default:
            {
              fonction = 2;
            }
            break;
        }
        ///////////////////////////////////////////////////////
        //                  eco  mode    
        //
        ///////////////////////////////////////////////////////
        if (eco_mode == true)
        {
          //char buffer[4]; //2del
          gpsSerial.write(gpsSleep, sizeof(gpsSleep));
          gpsSerial.flush();
          for (int n = 0; n < 6 ; n++)//Sec.
          {
            lcd.setCursor(15, 0); lcd.print (n);
            Print_Tide(6, 1);
            delay (1500);
            Print_wpazimut(6, 1);
            delay (1500);
            if (digitalRead(sw_sel) == 0)
            {
              lcd.clear ();
              while (digitalRead(sw_sel) == 0) {}; delay(10); // debounce
              menu(0);
            }
          }
          gpsSerial.write(gpsHot, sizeof(gpsHot));
          gpsSerial.flush();
          delay (2000); //
          //vinfo = 1;
        }
      }
    }
  }
}

///////////////////////////////////////////////////////
//                     MENU                          //
///////////////////////////////////////////////////////
static char* menu_items [] = {"Sel-UP-down", "Power OFF", "Lat-Long & WP ", "Power Moniteur",
                              "Eco Mode",  "GMT set  ", "TIDE set" , "Display Mode", "Odometre", "Retour", "Sel-up-DOWN"
                             };
void menu(int menu_index)
{
  lcd.clear();  lcd.print(menu_items[menu_index]);
  while (digitalRead(sw_sel) == LOW) {}; delay(5);             //Debounce
  while (digitalRead(sw_sel) != LOW)// Select
  {
    if (digitalRead(sw_up) == LOW)
    {
      lcd.clear();
      while (digitalRead(sw_up) == LOW) {}; delay(10);             //Debounce
      menu_index ++;
      if (menu_index > 8)
      {
        menu_index = 0;
      }
      lcd.clear();
      //lcd.setCursor(0, 0); lcd.print(menu_items[0]);
      lcd.setCursor(0, 1);
      lcd.print(menu_items[menu_index]);
    }
    if (digitalRead(sw_dwn) == LOW)
    {
      lcd.clear();
      while (digitalRead(sw_dwn) == LOW) {}; delay(10);               //Debounce
      menu_index -= 1;
      if (menu_index < 0)
      {
        menu_index = 8;
      }
      lcd.clear();
      lcd.print(menu_items[0]);
      lcd.setCursor(0, 1);
      lcd.print(menu_items[menu_index]);
    }
  }
  lcd.clear();
  while (digitalRead(sw_sel) == LOW) {}; delay(100);               //Debounce
  switch (menu_index)
  {
    case 1:
      ///////////////////////////////////////////////////////
      //          POWER OFF                                //
      ///////////////////////////////////////////////////////
      {
        lcd.clear();
        lcd.print ("POWER OFF....");
        delay (1500);
        digitalWrite(power_pin, LOW);
        delay (50);
        asm volatile ("  jmp 0");
      }
      break;
    case 2:
      ///////////////////////////////////////////////////////
      //          LAT et LONG MEMO                         //
      ///////////////////////////////////////////////////////
      {
        lcd.clear ();
        lcd.setCursor (0, 0);
        lcd.print("Push DWN to Save") ;
        lcd.setCursor (0, 1);
        lcd.print("WayPoint  ") ;
        delay (1000); lcd.clear ();
        while (digitalRead(sw_sel) != LOW)
        {
          Print_Latitude (0, 0);
          Print_Longitude (0, 1);
          if (digitalRead(sw_dwn) == LOW)
          {
            wp_lat  = lat;
            wp_lon  = lon;
            EEPROM.put(10, lat);
            EEPROM.put(15, lon);
            lcd.clear ();
            lcd.setCursor (0, 0);
            lcd.print("WayPoint SAVED") ;
            delay (1500);
            break;
          }
          if (digitalRead(sw_up) == LOW)
          {
            lcd.clear ();
            lcd.setCursor (0, 0);
            lcd.print("Push DWN to Save") ;
            while (digitalRead(sw_up) == LOW) {};
            delay(1000);
            lcd.clear ();
          }
          gps.get_position(&lat, &lon);
          lat = lat / 100; //enlever les d-secondes
          lon = lon / 100;
        }
        lcd.clear ();
        while (digitalRead(sw_sel) == LOW) {};
      }
      break;
    case 3:
      ///////////////////////////////////////////////////////
      //          POWER MONITOR batt sol                   //
      ///////////////////////////////////////////////////////
      {
        gpsSerial.write(gpsSleep, sizeof(gpsSleep));
        while (3)
        {
          float vsol = (float) analogRead(solPanel) / 204; //    1024/5voltsRef
          dtostrf (vsol, 3, 1, msg) ;
          lcd.setCursor(0, 0);
          lcd.print ("Solaire=");
          lcd.print (msg);
          lcd.print ("V ");
          float vbatt = (float) analogRead(batt) / vref + .21; //    1024/5voltsRef
          dtostrf (vbatt, 3, 1, msg) ;
          lcd.setCursor(0, 1);
          lcd.print ("Batterie=");
          lcd.print (msg); lcd.print ("V ");
          if ((vsol - vbatt) > .4)//volts
          {
            lcd.setCursor(12, 1); lcd.print ("V Charge ");
          }
          else
          {
            lcd.setCursor(12, 1); lcd.print ("V        ");
          }
          delay (1000);
          if (digitalRead(sw_sel) == LOW)
          {
            lcd.clear();
            while (digitalRead(sw_sel) == LOW) {}              ;
            gpsSerial.write(gpsHot, sizeof(gpsHot));
            return;
          }
          delay (1000);
        }
      }
      break;
    case 4:
      ///////////////////////////////////////////////////////
      ///               ECO MODE select                   ///
      ///////////////////////////////////////////////////////
      {
        if (eco_mode == false)
        {
          lcd.setCursor(0, 0); lcd.print("ECONO MODE ON    ");
          delay (1500);
          eco_mode = true;
          analogWrite(LCD_LED, 0);              // off lcd led
        }
        else
        {
          lcd.setCursor(0, 0); lcd.print("ECONO MODE OFF    ");
          eco_mode = false;
          delay (1500);
          analogWrite(LCD_LED, LCD_LED_N);              // off lcd led
        }
        lcd.clear ();
      }
      break;
    case 5:
      ///////////////////////////////////////////////////////
      //                     GMT                           //
      ///////////////////////////////////////////////////////
      {
        //gmt = 0;
        while (digitalRead(sw_sel) != LOW)
        {
          if (digitalRead(sw_up) == LOW)
          {
            lcd.clear ();
            while (digitalRead(sw_up) == LOW) {} ;
            gmt ++;
          }
          if (digitalRead(sw_dwn) == LOW)
          {
            lcd.clear ();
            while (digitalRead(sw_dwn) == LOW) {} ;
            gmt --;
          }
          lcd.clear();
          lcd.print ("GMT");
          lcd.print(gmt);
          delay (300);
        }
        lcd.clear ();
        while (digitalRead(sw_sel) == LOW) {} ;
        lcd.setCursor (0, 1);
        lcd.print ("SET GMT");
        lcd.print(gmt);
        EEPROM.write(0, gmt);
        delay(1000);
        return;
      }
      break;
    case 6:
      ///////////////////////////////////////////////////////
      //                     SET TIDE                      //
      ///////////////////////////////////////////////////////
      {
        //int tide_min, tide_hr;
        lcd.setCursor (0, 0);
        lcd.print ("Set ");
        lcd.setCursor (0, 1);
        lcd.print ("FullMoonHighTide");
        EEPROM.get(20, Tide_one);
        int tide_mth = 1;
        //float a = (float)Tide_one / 288;   //288 = 24hr * 60/ 5 min/hr)
        int tide_jr = 12;           //(int)a;
        //float b = (a - (float) tide_jr) * 24;
        int tide_hr = 7;                // (int)b;
        int tide_min = 45;              //(b - (float) tide_hr) * 60 ;

        ///////////////////////////////////////////////////////
        lcd.clear ();
        while (digitalRead(sw_sel) != LOW)
        {
          lcd.setCursor (0, 1);
          lcd.print (tide_mth); lcd.print("/");
          lcd.setCursor (3, 1); lcd.print(tide_jr); lcd.print(" ");
          lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print("  ");
          lcd.setCursor (0, 0)  ;
          lcd.print("v--Month  ");
          delay (350);
          if (digitalRead(sw_up) == LOW)
          {
            tide_mth ++;
          }
          if (digitalRead(sw_dwn) == LOW)
          {
            tide_mth --;
          }
        }
        ///////////////////////////////////////////////////////
        lcd.clear ();
        while (digitalRead(sw_sel) == LOW) {}; delay (100);
        while (digitalRead(sw_sel) != LOW)
        {
          lcd.setCursor (0, 1);
          lcd.print (tide_mth); lcd.print("/");
          lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" ");
          lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print("  ");
          lcd.setCursor (3, 0);
          delay (350);
          lcd.print("v--Day  ");
          if (digitalRead(sw_up) == LOW)
          {
            tide_jr ++;
          }
          if (digitalRead(sw_dwn) == LOW)
          {
            tide_jr --;
          }
        }
        ///////////////////////////////////////////////////////

        lcd.clear ();
        while (digitalRead(sw_sel) == LOW) {}; delay (100);
        while (digitalRead(sw_sel) != LOW)
        {
          lcd.setCursor (0, 1);
          lcd.print (tide_mth); lcd.print("/");
          lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" ");
          lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print("  ");
          lcd.setCursor (8, 0);
          lcd.print("v--Hr  ");
          delay (350);
          if (digitalRead(sw_up) == LOW)
          {
            tide_hr ++;
          }
          if (digitalRead(sw_dwn) == LOW)
          {
            tide_hr --;
          }
        }
        ///////////////////////////////////////////////////////
        lcd.clear ();
        while (digitalRead(sw_sel) == LOW) {}; delay (100);
        while (digitalRead(sw_sel) != LOW)
        {
          lcd.setCursor (0, 1);
          lcd.print (tide_mth); lcd.print("/");
          lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" ");
          lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print("  ");
          lcd.setCursor (5, 0);
          lcd.print("Min--v  ");
          delay (350);
          if (digitalRead(sw_up) == LOW)
          {
            tide_min += 5;
          }
          if (digitalRead(sw_dwn) == LOW)
          {
            tide_min -= 5;
          }
          if (tide_min < 1) {
            tide_min = 1; // prevention 0/5
          }
        }
        lcd.clear ();
        while (digitalRead(sw_sel) == LOW) {}
        Tide_one =  DofY (year, tide_mth, tide_jr, tide_hr, tide_min);
        lcd.setCursor (0, 0);
        lcd.print ("Tide_one="); lcd.print (Tide_one); lcd.print ("  ");
        lcd.setCursor (0, 1);
        lcd.print (tide_mth); lcd.print("/"); lcd.print (tide_jr ); lcd.print (" "); lcd.print (tide_hr); lcd.print (":"); lcd.print (tide_min);
        delay (3500);
        while (digitalRead(sw_sel) == LOW) { }
        lcd.clear ();
        lcd.print ("Push Dwn to Save");
        while (digitalRead(sw_sel) != LOW)
        {
          if (digitalRead(sw_dwn) == LOW)
          {
            if (Tide_one > 0)
            {
              EEPROM.put(20, Tide_one);
              lcd.clear ();
              lcd.print ("TIDE SAVED");
              lcd.setCursor (0, 1);
              lcd.print (Tide_one);
              delay (2000);
              while (digitalRead(sw_dwn) == LOW) { }
              lcd.clear ();
              return;
            }
            else
            {
              lcd.clear ();
              lcd.print ("TIDE E R R O R");
              lcd.setCursor (0, 1);
              lcd.print (Tide_one);
              delay (2500);
              lcd.clear ();
              return;
            }
          }
          delay (50);
        }
        lcd.clear ();
        return;
      }
      break;
    case 7:
      ///////////////////////////////////////////////////////
      //                    PRO MODE                       //
      ///////////////////////////////////////////////////////
      {
        if (pro_mode == false)
        {
          lcd.clear();  lcd.print("PRO Display ");
          delay (1500);
          pro_mode = true;
          EEPROM.write(4, pro_mode);
        }
        else
        {
          lcd.clear();  lcd.print("Dashboard    ");
          pro_mode = false;
          EEPROM.write(4, pro_mode);
          delay (1500);
        }
        lcd.clear ();
      }
      break;
    case 8:
      ///////////////////////////////////////////////////////
      //                     ODOMETRE                      //
      ///////////////////////////////////////////////////////
      {
        Odometre = 0;
        time_run = 0;
        lat2 = lat;
        lon2 = lon;
        lcd.clear();  lcd.print("Odometre Reset");
        delay (1500); lcd.clear ();
      }
      break;
    default:
      {
      }
      return;
  }
}
/////////////////////////////////////////////////////////////////////////////////////
//                              SUBROUTINES                                        //
/////////////////////////////////////////////////////////////////////////////////////
// writeBigChar: writes big character 'ch' to column x, row y; returns number of columns used by 'ch'
int writeBigChar(char ch, byte x, byte y) {
  if (ch < ' ' || ch > '_') return 0;               // If outside table range, do nothing
  nb = 0;                                           // character byte counter
  for (bc = 0; bc < 8; bc++) {
    bb[bc] = pgm_read_byte( &bigChars[ch - ' '][bc] ); // read 8 bytes from PROGMEM
    if (bb[bc] != 0) nb++;
  }
  bc = 0;
  for (row = y; row < y + 2; row++) {
    for (col = x; col < x + nb / 2; col++ ) {
      lcd.setCursor(col, row);                      // move to position
      lcd.write(bb[bc++]);                          // write byte and increment to next
    }
  }
  return nb / 2 - 1;                                  // returns number of columns used by char
}
// writeBigString: writes out each letter of string
void writeBigString(char *str, byte x, byte y)
{
  char c;
  while ((c = *str++))
    x += writeBigChar(c, x, y) + 1;
}
///////////////////////////////////////////////////////
//                  HORLOGE                          //
///////////////////////////////////////////////////////
void horloge(int C, int R)
{
  lcd.setCursor(C, R);
  lcd.print(hour); lcd.print(":");
  if (minute < 10)
  {
    lcd.print("0");
  }
  lcd.print(minute);
  lcd.print(" ");
}
///////////////////////////////////////////////////////
//                    LATITUDE                       //
///////////////////////////////////////////////////////
void Print_Latitude(int C, int R)
{
  long latdeg = (lat / 10000);
  lcd.setCursor(C, R);
  lcd.print("Lat:");
  lcd.print(abs(latdeg));
  lcd.print((char)223);
  float x = (float)(lat - latdeg * 10000) * .6 / 100;
  lcd.print(x); lcd.print("'");
  if (lat > 0)
  {
    lcd.print ("N");
  }
  else
  {
    lcd.print("S");
  }
}
///////////////////////////////////////////////////////
//            PRINT  LONGITUDE                      //
///////////////////////////////////////////////////////
void Print_Longitude(int C, int R)
{
  long londeg = (lon / 10000);
  lcd.setCursor(C, R);
  lcd.print("Lon:");
  lcd.print(abs(londeg));
  lcd.print((char)223);
  float x = (float) (abs(lon) - abs(londeg) * 10000) * .6 / 100;
  lcd.print(x); lcd.print("'");
  if (lon > 0) {
    lcd.print("E");
  }
  else {
    lcd.print("W");
  }
}

///////////////////////////////////////////////////////
//               TIDE CLOCK display                  //
///////////////////////////////////////////////////////
void Print_Tide(int C, int R)
{
  EEPROM.get(20, Tide_one);
  const char*tideclock [] {"HIGH   ", "L 5Hr  ", "L 4Hr  ", "L 3Hr  ", "L 2Hr  ", "L 1Hr  ", "LOW    ", "H 5Hr  ", "H 4Hr  ", "H 3Hr  ", "H 2Hr  ", "H 1Hr  ", "HIGH   ", "ERR   "};
  //Serial.print ("y min="); //Serial.println (Year_Min);
  //Serial.print ("tide 1="); //Serial.println (Tide_one);
  long tide_cycle = (Year_Min - Tide_one);
  //Serial.print ("tide cycle="); //Serial.println (tide_cycle);
  float tide_cyclef = (float)tide_cycle / 745.233333f;        //Tide 12h25m14sec (745.23 min)
  dtostrf (tide_cyclef, 1, 6, msg) ;
  //Serial.print ("tide cyclef="); //Serial.println (msg);
  tide_cyclef = tide_cyclef - int(tide_cyclef);
  dtostrf (tide_cyclef, 1, 6, msg) ;
  //Serial.print ("tide cyclefraction="); //Serial.println (msg);
  tide_cyclef = tide_cyclef * 12;
  dtostrf (tide_cyclef, 1, 6, msg) ;
  tide_cycle = round (tide_cyclef);
  lcd.setCursor(C, R);
  lcd.print ("Tide:");
  lcd.print (tideclock[tide_cycle]);
  //; break;
...

This file has been truncated, please download it to see its full contents.

Credits

Chrisroy

Chrisroy

1 project • 1 follower

Comments

Add projectSign up / Login