Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
Hand tools and fabrication machines | ||||||
|
I make this GPS for my kayak. I want to be sufficiently robust to permanently attached to it (sea condition) and can be run forever for long sea kayak excursions.
-GPS is powered only by solar energy and can run 1-2 days without sun if need with a integrate lithium-ion battery (if the battery is full).
-Screen can be read in the sunlight or night with back light LED. On sunlight the back light LED is turns OFF for reduce the consumption.
-Waterproof, epoxy sealed .
-Tide clock base on moon rotation 12 heures 25 minutes and 14 secondes. hours until low or high tide are display has a count-down of hours from 5 to 1
-The GPS doesn't have integrate map and should be use in conjunction with paper map for route planning or can simply use for to see speed, time and odometer as a dashboard.
-GPS Info available: Time, Latitude and Longitude, Speed, Tide Clock, Azimuth compass rose, Azimuth Returns/distance and Odometer,
-Pro mode display; Display Speed, Time, Azimuth/compass rose , and alternatively Azimuth/distance, Tide clock and Odometer
-Dashboard mode display; Big character speed, odometer, time.
-controlled by 4 push buttons (select, Up, Down and Power ON)
-the power on / off are controlled by the MCU and the MCU can turn off if the battery voltage is too low (battery protection).
-low energy mode, the GPS module is put in sleeping mode for 10 sec and Hot Start to get data and back on Sleeping Mode...
Next generation will use Arduino Nano pro, GPS module and LCD display at 3.3 volts, more efficient with 3.7 battery. Controlled by tree push buttons (select/PowerON, Up and Down) , It will be smaller. better box design, new option Navigation flashing light (Red and Green). may be a integrate a buzzer for alarm clock. temperature info... I will need more Mem or help for optimise the code.
Sorry my English is not my first langage :(
/*
*/
#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.
Comments