Components and supplies
Arduino Nano R3
TinyShield GPS
TinyDuino Starter Kit – Lithium Version
Tools and machines
Soldering iron (generic)
Apps and platforms
Arduino IDE
Project description
Code
Kayak GPS
arduino
Navigation GPS powered by solar energy.
1/* 2*/ 3 4#include <SoftwareSerial.h> 5#include <TinyGPS.h> 6#include <LiquidCrystal.h> 7#include <EEPROM.h> 8 9#include <avr/pgmspace.h> 10LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //8>RS,9>E, 4-7>D4-D7,RW>0V, 11SoftwareSerial gpsSerial(2, 3); //RX, TX 2>bleuTX, 3>VertRX 12TinyGPS gps; 13 14byte clo_n = 0; 15boolean eco_mode = false; 16boolean pro_mode = false; 17static int vref = 211; // 1023/4.9 volts 18byte solPanel = 3; //pin 19byte batt = 4; //pin 20byte LCD_LED = 11; 21byte power_pin = 12; 22byte sw_sel = 14;// select 23byte sw_up = 15;// up 24byte sw_dwn = 16;//down 25byte fonction = 0; 26int gmt;//, hr ; 27long Year_Min; 28long Tide_one; 29unsigned long time_On; 30unsigned long time_run; 31unsigned long time_old; 32 33int year;//, vinfo; 34int menu_index = 0; 35int cum_n; 36static float rad2deg = 0.01745; 37float Odometre; 38char msg[6]; 39byte LCD_LED_N = 220; //OFF 0-a-255 ON 40byte col, row, nb = 0, bc = 0; // general 41byte bb[8]; 42byte month, day, hour, minute, second, sped; //hundredths, 43long lat, lon; //, latmin, lonmin; //angle 44long lat2 = 0; 45long lon2 = 0; 46long wp_lat, wp_lon ; 47 48const char*azimuts[] = {"N ", "NE ", "E ", "SE ", "S ", "SW ", "W ", "NW " }; 49const char custom[][8] PROGMEM = { // Custom character definitions 50 { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 }, // char 1 51 { 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 2 52 { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x03 }, // char 3 53 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 4 54 { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1C, 0x18 }, // char 5 55 { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F }, // char 6 56 { 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 7 57 { 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 8 58 59}; 60const char bigChars[][8] PROGMEM = { 61 { 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Space 62 { 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ! 63 { 0x05, 0x05, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00 }, // " 64 { 0x04, 0xFF, 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01 }, // # 65 { 0x08, 0xFF, 0x06, 0x07, 0xFF, 0x05, 0x00, 0x00 }, // $ 66 { 0x01, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x04 }, // % 67 { 0x08, 0x06, 0x02, 0x20, 0x03, 0x07, 0x02, 0x04 }, // & 68 { 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' 69 { 0x08, 0x01, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 }, // ( 70 { 0x01, 0x02, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00 }, // ) 71 { 0x01, 0x04, 0x04, 0x01, 0x04, 0x01, 0x01, 0x04 }, // * 72 { 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01, 0x00, 0x00 }, // + 73 { 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 74 { 0x04, 0x04, 0x04, 0x20, 0x20, 0x20, 0x00, 0x00 }, // - 75 { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // . 76 { 0x20, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x20 }, // / 77 { 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00 }, // 0 78 { 0x01, 0x02, 0x20, 0x04, 0xFF, 0x04, 0x00, 0x00 }, // 1 79 { 0x06, 0x06, 0x02, 0xFF, 0x07, 0x07, 0x00, 0x00 }, // 2 80 { 0x01, 0x06, 0x02, 0x04, 0x07, 0x05, 0x00, 0x00 }, // 3 81 { 0x03, 0x04, 0xFF, 0x20, 0x20, 0xFF, 0x00, 0x00 }, // 4 82 { 0xFF, 0x06, 0x06, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 5 83 { 0x08, 0x06, 0x06, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 6 84 { 0x01, 0x01, 0x02, 0x20, 0x08, 0x20, 0x00, 0x00 }, // 7 85 { 0x08, 0x06, 0x02, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 8 86 { 0x08, 0x06, 0x02, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 9 87}; 88 89const 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}; 90const 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}; 91const static byte gpsSleep[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x16, 0x74}; 92const static byte gpsHot[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x68}; 93const 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 94const 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 95const 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 96const 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 97const 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 98const 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 99const 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 100const 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 101const 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 102const 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 103const 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 104 105/////////////////////////////////////////////////////// 106// Minute depuis debut annee // 107/////////////////////////////////////////////////////// 108int 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. 109long DofY(int yr, int mo, int dy, int h, int mi) 110{ 111 int DfY; 112 long Min2Date; 113 if (mo == 1 || mo == 2) 114 { 115 DfY = days[mo] + dy - 1; //for any type of year, it calculate the number of days for January or february 116 } 117 else if ((yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0) 118 { 119 DfY = days[mo] + dy + 1 - 1; 120 } 121 else 122 { 123 DfY = days[mo] + dy - 1; 124 } 125 Min2Date = (long)DfY * 1440l + (long)h * 60l + (long)mi; 126 return (Min2Date); 127} 128/////////////////////////////////////////////////////// 129// SETUP // 130/////////////////////////////////////////////////////// 131void setup() 132{ 133 pinMode(power_pin, OUTPUT); 134 digitalWrite (power_pin, HIGH); // POWER ON! 135 analogReference(DEFAULT); 136 pinMode(LED_BUILTIN, OUTPUT); 137 digitalWrite(LED_BUILTIN, LOW); 138 Serial.begin(9600); 139 gpsSerial.begin(9600); 140 pinMode(LCD_LED, OUTPUT); 141 //pinMode(buz, OUTPUT); 142 pinMode(sw_sel, INPUT); 143 pinMode(sw_up, INPUT); 144 pinMode(sw_dwn, INPUT); 145 lcd.begin(16, 2); 146 analogWrite(LCD_LED, 100); 147 148 /////////////////////////////////////////////////////// 149 // EE PROM Variable // 150 /////////////////////////////////////////////////////// 151 hour = EEPROM.read(0); //lire le gmt 152 pro_mode = EEPROM.read(4); 153 EEPROM.get(10, wp_lat); 154 EEPROM.get(15, wp_lon); 155 EEPROM.get(20, Tide_one); 156 EEPROM.get(25, Odometre); 157 EEPROM.get(30, time_On); 158 if (isnan(Odometre)) // test if NAN value 159 { 160 Odometre = 0; 161 } 162 if (hour > 127) //numbre negatif 163 { 164 gmt = hour - 256; 165 } 166 else 167 { 168 gmt = hour; 169 } 170 /////////////////////////////////////////////////////// 171 /// R E V /// 172 /////////////////////////////////////////////////////// 173 lcd.clear(); 174 lcd.print(F("Ultimate YAK GPS")); 175 lcd.setCursor(0, 1); 176 lcd.print(F("GPS_1602B rev 92.1")); // Revision Version<<<< 177 delay (2000); 178 lcd.clear(); 179 lcd.print("GMT="); lcd.print(gmt); 180 float vbatt = (float) analogRead(batt) / vref + .21; // 181 lcd.setCursor(0, 1); 182 lcd.print(F("Batterie:")); 183 lcd.print(vbatt); 184 lcd.print("V"); 185 delay (2000); 186 lcd.clear(); 187 lcd.print(F("Odometre:")); 188 lcd.print(Odometre); 189 delay (2000); 190 lcd.clear(); 191 lcd.print("WPLat:"); 192 lcd.print(wp_lat); 193 lcd.setCursor(0, 1); 194 lcd.print("WPLon:"); 195 lcd.print(wp_lon); 196 delay (2000); 197 lcd.clear(); 198 lcd.print("Last Time ON:"); 199 lcd.setCursor(0, 1); 200 lcd.print(time_On / 60000); lcd.print("Min"); 201 delay (4000); 202 203 204 /*lcd.clear(); 205 lcd.print("TIDE: "); 206 lcd.print(Tide_one); 207 float a = (float)Tide_one / 288; //288 = 24hr * 60/ 5 min/hr) 208 int tide_jr = (int)a; 209 float b = (a - (float) tide_jr) * 24; 210 tide_hr = (int)b; 211 tide_min = (b - (float) tide_hr) * 60 ; 212 lcd.setCursor(0, 1); 213 lcd.print(tide_jr + 1); 214 lcd.print("Days "); 215 lcd.print(tide_hr); 216 lcd.print(":"); 217 lcd.print(tide_min); 218 delay(2000); 219 */ 220 221 222 if (vbatt < 2.8)//volts 223 { 224 lcd.setCursor(0, 1); lcd.print("Batt. LOW!"); 225 delay (4000); 226 //digitalWrite(power_pin, LOW); //off 227 } 228 analogWrite(LCD_LED, 20); 229 230 /////////////////////////////////////////////////////// 231 // GPS Reset // 232 /////////////////////////////////////////////////////// 233 lcd.clear(); 234 235 if (gps.encode(gpsSerial.read())) 236 { 237 lcd.print("GPS Reset"); 238 gpsSerial.write(gpsHot, sizeof(gpsHot)); gpsSerial.flush(); 239 gpsSerial.write( gpsDefault, sizeof( gpsDefault)); gpsSerial.flush(); 240 gpsSerial.write( Disable_GPDTM, sizeof( Disable_GPDTM)); gpsSerial.flush(); 241 gpsSerial.write( Disable_GPGBS, sizeof( Disable_GPGBS)); gpsSerial.flush(); 242 gpsSerial.write( Disable_GPGLL, sizeof( Disable_GPGLL)); gpsSerial.flush(); 243 gpsSerial.write( Disable_GPGRS, sizeof( Disable_GPGRS)); gpsSerial.flush(); 244 gpsSerial.write( Disable_GPGSA, sizeof( Disable_GPGSA)); gpsSerial.flush(); 245 gpsSerial.write( Disable_GPGSV, sizeof( Disable_GPGSV)); gpsSerial.flush(); 246 gpsSerial.write( Disable_GPVTG, sizeof( Disable_GPVTG)); gpsSerial.flush(); 247 gpsSerial.write( Disable_GPGGA, sizeof( Disable_GPGGA)); gpsSerial.flush(); 248 } 249 lcd.setCursor(0, 1); lcd.println(F("Wait satellites.")); 250 /////////////////////////////////////////////////////// 251 /// create 8 custom characters /// 252 /////////////////////////////////////////////////////// 253 for (nb = 0; nb < 8; nb++ ) 254 { 255 for (bc = 0; bc < 8; bc++) 256 bb[bc] = pgm_read_byte( &custom[nb][bc] ); 257 lcd.createChar ( nb + 1, bb ); 258 } 259} 260////////////////////////////////////////////////////////////////////////////////////////////////////////////// 261/// L O O P /// 262////////////////////////////////////////////////////////////////////////////////////////////////////////////// 263void loop() 264{ 265 while (gpsSerial.available()) // check for gps data 266 { 267 if (gps.encode(gpsSerial.read())) // encode gps data 268 { 269 gps.get_position(&lat, &lon); // get lat and long 270 gps.crack_datetime(&year, &month, &day, &hour, &minute, &second); 271 lat = lat / 100; //enlever les d-secondes 272 lon = lon / 100; 273 // lcd.setCursor(0, 0); lcd.print (lat); lcd.print (" "); lcd.print (lon); delay (4000); 274 hour = hour + gmt; 275 if (hour > 128) // reference a gmt 276 { 277 hour = hour + 24; 278 day = day - 1; 279 } 280 ////Serial.print ("DofY=");//Serial.println (DofY (year,month,day,hour,minute)); 281 //Serial.print (year); //Serial.print ("/"); //Serial.print (month); //Serial.print ("/"); //Serial.print (day); //Serial.print (" "); //Serial.print (hour); //Serial.print (":"); //Serial.println (minute); 282 Year_Min = DofY ((int)year, (int)month, (int)day, (int)hour, (int)minute); 283 //Serial.print ("Year2min ="); //Serial.println (Year_Min); 284 285 286 if (digitalRead(sw_sel) == LOW) { 287 lcd.clear(); 288 while (digitalRead(sw_sel) == 0) {} // wait for release 289 menu(0); 290 } 291 if (digitalRead(sw_dwn) == LOW) 292 { 293 lcd.clear(); 294 while (digitalRead(sw_dwn) == 0) {} // wait for release 295 if (pro_mode == false) 296 { 297 lcd.clear(); lcd.print("PRO Display "); 298 delay (1500); 299 pro_mode = true; 300 EEPROM.write(4, pro_mode); 301 } 302 else 303 { 304 lcd.clear(); lcd.print("Dashboard MODE "); 305 pro_mode = false; 306 EEPROM.write(4, pro_mode); 307 delay (1500); 308 } 309 lcd.clear (); 310 } 311 /////////////////////////////////////////////////////// 312 // LCD LED & test de batt // 313 /////////////////////////////////////////////////////// 314 float vsol = (float) analogRead(solPanel) / vref ; // 1024/2.5voltsRef 315 if (eco_mode == true) { 316 LCD_LED_N = 20; 317 } 318 else { 319 LCD_LED_N = 150; 320 } 321 if (vsol > 1) {//volt 322 vsol = 1;//volt 323 } 324 LCD_LED_N = LCD_LED_N - (vsol * LCD_LED_N); 325 analogWrite(LCD_LED, LCD_LED_N); 326 327 float vbatt = (float) analogRead(batt) / vref + .21; // 1024/5voltsRef 328 if (vbatt < 2.8) // Volts 2.8 329 { 330 lcd.clear(); lcd.print("LOW BATT "); 331 lcd.setCursor(0, 1); lcd.print(vbatt); lcd.print("Volts"); 332 EEPROM.put(25, Odometre); //save odometre 333 delay (5000); 334 digitalWrite(power_pin, LOW);// power off 335 } 336 if (vbatt > 4.2) // Volts 337 { 338 analogWrite(LCD_LED, 255); 339 digitalWrite(LED_BUILTIN, HIGH); 340 } 341 else 342 { 343 digitalWrite(LED_BUILTIN, LOW); 344 } 345 float speedf = gps.speed() * .01852; // 1.852 /100 knot to kmph 346 347 if (speedf < .5) 348 { 349 speedf = 0; 350 } 351 /////////////////////////////////////////////////////// 352 /// ODOMETRE /// 353 /////////////////////////////////////////////////////// 354 if (cum_n >= 10) 355 { 356 if (lat2 == 0) 357 { 358 lat2 = lat; 359 lon2 = lon; 360 } 361 cum_n = 0; 362 float lon2_dec = lon2 / 10000.0; 363 /////////////////////convert decimal degree into radian//////////////// 364 float lat1_Rad = lat / 10000.0 * rad2deg; 365 float lon1_Rad = lon / 10000.0 * rad2deg; 366 float lat2_Rad = lat2 / 10000.0 * rad2deg; 367 float lon2_Rad = lon2 / 10000.0 * rad2deg; 368 369 //Calculate the distance KM 370 float latSin = sin((lat1_Rad - lat2_Rad) / 2); 371 float lonSin = sin((lon1_Rad - lon2_Rad) / 2); 372 373 float P2P = 2 * asin(sqrt((latSin * latSin) + cos(lat1_Rad) * cos(lat2_Rad) * (lonSin * lonSin))); 374 P2P = P2P * 6371; //Earth radius = 6,371 km 375 376 if (P2P < 5 && speedf != 0) // plus de 5 km est une erreur ou speed =0kmh 377 { 378 Odometre += P2P; 379 lat2 = lat; 380 lon2 = lon; 381 EEPROM.put(25, Odometre); 382 time_run = time_run + (millis() - time_old); 383 384 EEPROM.put(30, millis()); //future reference 385 } 386 time_old = millis(); 387 } 388 else 389 { 390 cum_n ++; 391 } 392 /////////////////////////////////////////////////////// 393 // V I T E S S E // 394 /////////////////////////////////////////////////////// 395 396 dtostrf (speedf, 3, 1, msg) ; 397 if (pro_mode == false) 398 { 399 writeBigString(msg, 0, 0); 400 lcd.setCursor(7, 0); lcd.print ("KM "); 401 lcd.setCursor(7, 1); lcd.print ("/H "); 402 lcd.setCursor(10, 0); 403 if (Odometre < 100) 404 { 405 dtostrf (Odometre, 1, 1, msg) ; 406 } 407 else 408 { 409 dtostrf (Odometre, 1, 0, msg) ; 410 } 411 lcd.print (msg); lcd.print ("KM "); 412 413 horloge (10, 1); 414 } 415 else 416 { 417 lcd.setCursor(0, 0); 418 lcd.print(msg); lcd.print("KMH ");//dtostrf (speedf, 3, 1, msg) ; 419 Print_Azimut(8, 0); 420 horloge(0, 1) ; 421 /////////////////////////////////////////////////////// 422 // Display Fonction Variable // 423 /////////////////////////////////////////////////////// 424 fonction++; 425 switch (fonction / 3) 426 { 427 case 1: 428 { 429 Print_wpazimut(6, 1); 430 EEPROM.put(30, millis()); 431 } 432 break; 433 case 4: 434 { 435 Print_Tide(6, 1); 436 } 437 break; 438 case 2: 439 { 440 lcd.setCursor(6, 1); 441 if (Odometre < 100) 442 { 443 dtostrf (Odometre, 1, 1, msg) ; 444 } 445 else 446 { 447 dtostrf (Odometre, 1, 0, msg) ; 448 } 449 lcd.print ("Od:"); lcd.print (msg); lcd.print ("KM "); 450 } 451 break; 452 case 3: 453 { 454 lcd.setCursor(6, 1); 455 lcd.print ("Run:"); 456 if (time_run > 10000000L)//msec 457 { 458 lcd.print (time_run / 3600000L);//msec 459 lcd.print ("Hr "); 460 } 461 else 462 { 463 lcd.print (time_run / 60000L);//msec 464 lcd.print ("Min "); 465 } 466 } 467 break; 468 default: 469 { 470 fonction = 2; 471 } 472 break; 473 } 474 /////////////////////////////////////////////////////// 475 // eco mode 476 // 477 /////////////////////////////////////////////////////// 478 if (eco_mode == true) 479 { 480 //char buffer[4]; //2del 481 gpsSerial.write(gpsSleep, sizeof(gpsSleep)); 482 gpsSerial.flush(); 483 for (int n = 0; n < 6 ; n++)//Sec. 484 { 485 lcd.setCursor(15, 0); lcd.print (n); 486 Print_Tide(6, 1); 487 delay (1500); 488 Print_wpazimut(6, 1); 489 delay (1500); 490 if (digitalRead(sw_sel) == 0) 491 { 492 lcd.clear (); 493 while (digitalRead(sw_sel) == 0) {}; delay(10); // debounce 494 menu(0); 495 } 496 } 497 gpsSerial.write(gpsHot, sizeof(gpsHot)); 498 gpsSerial.flush(); 499 delay (2000); // 500 //vinfo = 1; 501 } 502 } 503 } 504 } 505} 506 507/////////////////////////////////////////////////////// 508// MENU // 509/////////////////////////////////////////////////////// 510static char* menu_items [] = {"Sel-UP-down", "Power OFF", "Lat-Long & WP ", "Power Moniteur", 511 "Eco Mode", "GMT set ", "TIDE set" , "Display Mode", "Odometre", "Retour", "Sel-up-DOWN" 512 }; 513void menu(int menu_index) 514{ 515 lcd.clear(); lcd.print(menu_items[menu_index]); 516 while (digitalRead(sw_sel) == LOW) {}; delay(5); //Debounce 517 while (digitalRead(sw_sel) != LOW)// Select 518 { 519 if (digitalRead(sw_up) == LOW) 520 { 521 lcd.clear(); 522 while (digitalRead(sw_up) == LOW) {}; delay(10); //Debounce 523 menu_index ++; 524 if (menu_index > 8) 525 { 526 menu_index = 0; 527 } 528 lcd.clear(); 529 //lcd.setCursor(0, 0); lcd.print(menu_items[0]); 530 lcd.setCursor(0, 1); 531 lcd.print(menu_items[menu_index]); 532 } 533 if (digitalRead(sw_dwn) == LOW) 534 { 535 lcd.clear(); 536 while (digitalRead(sw_dwn) == LOW) {}; delay(10); //Debounce 537 menu_index -= 1; 538 if (menu_index < 0) 539 { 540 menu_index = 8; 541 } 542 lcd.clear(); 543 lcd.print(menu_items[0]); 544 lcd.setCursor(0, 1); 545 lcd.print(menu_items[menu_index]); 546 } 547 } 548 lcd.clear(); 549 while (digitalRead(sw_sel) == LOW) {}; delay(100); //Debounce 550 switch (menu_index) 551 { 552 case 1: 553 /////////////////////////////////////////////////////// 554 // POWER OFF // 555 /////////////////////////////////////////////////////// 556 { 557 lcd.clear(); 558 lcd.print ("POWER OFF...."); 559 delay (1500); 560 digitalWrite(power_pin, LOW); 561 delay (50); 562 asm volatile (" jmp 0"); 563 } 564 break; 565 case 2: 566 /////////////////////////////////////////////////////// 567 // LAT et LONG MEMO // 568 /////////////////////////////////////////////////////// 569 { 570 lcd.clear (); 571 lcd.setCursor (0, 0); 572 lcd.print("Push DWN to Save") ; 573 lcd.setCursor (0, 1); 574 lcd.print("WayPoint ") ; 575 delay (1000); lcd.clear (); 576 while (digitalRead(sw_sel) != LOW) 577 { 578 Print_Latitude (0, 0); 579 Print_Longitude (0, 1); 580 if (digitalRead(sw_dwn) == LOW) 581 { 582 wp_lat = lat; 583 wp_lon = lon; 584 EEPROM.put(10, lat); 585 EEPROM.put(15, lon); 586 lcd.clear (); 587 lcd.setCursor (0, 0); 588 lcd.print("WayPoint SAVED") ; 589 delay (1500); 590 break; 591 } 592 if (digitalRead(sw_up) == LOW) 593 { 594 lcd.clear (); 595 lcd.setCursor (0, 0); 596 lcd.print("Push DWN to Save") ; 597 while (digitalRead(sw_up) == LOW) {}; 598 delay(1000); 599 lcd.clear (); 600 } 601 gps.get_position(&lat, &lon); 602 lat = lat / 100; //enlever les d-secondes 603 lon = lon / 100; 604 } 605 lcd.clear (); 606 while (digitalRead(sw_sel) == LOW) {}; 607 } 608 break; 609 case 3: 610 /////////////////////////////////////////////////////// 611 // POWER MONITOR batt sol // 612 /////////////////////////////////////////////////////// 613 { 614 gpsSerial.write(gpsSleep, sizeof(gpsSleep)); 615 while (3) 616 { 617 float vsol = (float) analogRead(solPanel) / 204; // 1024/5voltsRef 618 dtostrf (vsol, 3, 1, msg) ; 619 lcd.setCursor(0, 0); 620 lcd.print ("Solaire="); 621 lcd.print (msg); 622 lcd.print ("V "); 623 float vbatt = (float) analogRead(batt) / vref + .21; // 1024/5voltsRef 624 dtostrf (vbatt, 3, 1, msg) ; 625 lcd.setCursor(0, 1); 626 lcd.print ("Batterie="); 627 lcd.print (msg); lcd.print ("V "); 628 if ((vsol - vbatt) > .4)//volts 629 { 630 lcd.setCursor(12, 1); lcd.print ("V Charge "); 631 } 632 else 633 { 634 lcd.setCursor(12, 1); lcd.print ("V "); 635 } 636 delay (1000); 637 if (digitalRead(sw_sel) == LOW) 638 { 639 lcd.clear(); 640 while (digitalRead(sw_sel) == LOW) {} ; 641 gpsSerial.write(gpsHot, sizeof(gpsHot)); 642 return; 643 } 644 delay (1000); 645 } 646 } 647 break; 648 case 4: 649 /////////////////////////////////////////////////////// 650 /// ECO MODE select /// 651 /////////////////////////////////////////////////////// 652 { 653 if (eco_mode == false) 654 { 655 lcd.setCursor(0, 0); lcd.print("ECONO MODE ON "); 656 delay (1500); 657 eco_mode = true; 658 analogWrite(LCD_LED, 0); // off lcd led 659 } 660 else 661 { 662 lcd.setCursor(0, 0); lcd.print("ECONO MODE OFF "); 663 eco_mode = false; 664 delay (1500); 665 analogWrite(LCD_LED, LCD_LED_N); // off lcd led 666 } 667 lcd.clear (); 668 } 669 break; 670 case 5: 671 /////////////////////////////////////////////////////// 672 // GMT // 673 /////////////////////////////////////////////////////// 674 { 675 //gmt = 0; 676 while (digitalRead(sw_sel) != LOW) 677 { 678 if (digitalRead(sw_up) == LOW) 679 { 680 lcd.clear (); 681 while (digitalRead(sw_up) == LOW) {} ; 682 gmt ++; 683 } 684 if (digitalRead(sw_dwn) == LOW) 685 { 686 lcd.clear (); 687 while (digitalRead(sw_dwn) == LOW) {} ; 688 gmt --; 689 } 690 lcd.clear(); 691 lcd.print ("GMT"); 692 lcd.print(gmt); 693 delay (300); 694 } 695 lcd.clear (); 696 while (digitalRead(sw_sel) == LOW) {} ; 697 lcd.setCursor (0, 1); 698 lcd.print ("SET GMT"); 699 lcd.print(gmt); 700 EEPROM.write(0, gmt); 701 delay(1000); 702 return; 703 } 704 break; 705 case 6: 706 /////////////////////////////////////////////////////// 707 // SET TIDE // 708 /////////////////////////////////////////////////////// 709 { 710 //int tide_min, tide_hr; 711 lcd.setCursor (0, 0); 712 lcd.print ("Set "); 713 lcd.setCursor (0, 1); 714 lcd.print ("FullMoonHighTide"); 715 EEPROM.get(20, Tide_one); 716 int tide_mth = 1; 717 //float a = (float)Tide_one / 288; //288 = 24hr * 60/ 5 min/hr) 718 int tide_jr = 12; //(int)a; 719 //float b = (a - (float) tide_jr) * 24; 720 int tide_hr = 7; // (int)b; 721 int tide_min = 45; //(b - (float) tide_hr) * 60 ; 722 723 /////////////////////////////////////////////////////// 724 lcd.clear (); 725 while (digitalRead(sw_sel) != LOW) 726 { 727 lcd.setCursor (0, 1); 728 lcd.print (tide_mth); lcd.print("/"); 729 lcd.setCursor (3, 1); lcd.print(tide_jr); lcd.print(" "); 730 lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" "); 731 lcd.setCursor (0, 0) ; 732 lcd.print("v--Month "); 733 delay (350); 734 if (digitalRead(sw_up) == LOW) 735 { 736 tide_mth ++; 737 } 738 if (digitalRead(sw_dwn) == LOW) 739 { 740 tide_mth --; 741 } 742 } 743 /////////////////////////////////////////////////////// 744 lcd.clear (); 745 while (digitalRead(sw_sel) == LOW) {}; delay (100); 746 while (digitalRead(sw_sel) != LOW) 747 { 748 lcd.setCursor (0, 1); 749 lcd.print (tide_mth); lcd.print("/"); 750 lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" "); 751 lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" "); 752 lcd.setCursor (3, 0); 753 delay (350); 754 lcd.print("v--Day "); 755 if (digitalRead(sw_up) == LOW) 756 { 757 tide_jr ++; 758 } 759 if (digitalRead(sw_dwn) == LOW) 760 { 761 tide_jr --; 762 } 763 } 764 /////////////////////////////////////////////////////// 765 766 lcd.clear (); 767 while (digitalRead(sw_sel) == LOW) {}; delay (100); 768 while (digitalRead(sw_sel) != LOW) 769 { 770 lcd.setCursor (0, 1); 771 lcd.print (tide_mth); lcd.print("/"); 772 lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" "); 773 lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" "); 774 lcd.setCursor (8, 0); 775 lcd.print("v--Hr "); 776 delay (350); 777 if (digitalRead(sw_up) == LOW) 778 { 779 tide_hr ++; 780 } 781 if (digitalRead(sw_dwn) == LOW) 782 { 783 tide_hr --; 784 } 785 } 786 /////////////////////////////////////////////////////// 787 lcd.clear (); 788 while (digitalRead(sw_sel) == LOW) {}; delay (100); 789 while (digitalRead(sw_sel) != LOW) 790 { 791 lcd.setCursor (0, 1); 792 lcd.print (tide_mth); lcd.print("/"); 793 lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" "); 794 lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" "); 795 lcd.setCursor (5, 0); 796 lcd.print("Min--v "); 797 delay (350); 798 if (digitalRead(sw_up) == LOW) 799 { 800 tide_min += 5; 801 } 802 if (digitalRead(sw_dwn) == LOW) 803 { 804 tide_min -= 5; 805 } 806 if (tide_min < 1) { 807 tide_min = 1; // prevention 0/5 808 } 809 } 810 lcd.clear (); 811 while (digitalRead(sw_sel) == LOW) {} 812 Tide_one = DofY (year, tide_mth, tide_jr, tide_hr, tide_min); 813 lcd.setCursor (0, 0); 814 lcd.print ("Tide_one="); lcd.print (Tide_one); lcd.print (" "); 815 lcd.setCursor (0, 1); 816 lcd.print (tide_mth); lcd.print("/"); lcd.print (tide_jr ); lcd.print (" "); lcd.print (tide_hr); lcd.print (":"); lcd.print (tide_min); 817 delay (3500); 818 while (digitalRead(sw_sel) == LOW) { } 819 lcd.clear (); 820 lcd.print ("Push Dwn to Save"); 821 while (digitalRead(sw_sel) != LOW) 822 { 823 if (digitalRead(sw_dwn) == LOW) 824 { 825 if (Tide_one > 0) 826 { 827 EEPROM.put(20, Tide_one); 828 lcd.clear (); 829 lcd.print ("TIDE SAVED"); 830 lcd.setCursor (0, 1); 831 lcd.print (Tide_one); 832 delay (2000); 833 while (digitalRead(sw_dwn) == LOW) { } 834 lcd.clear (); 835 return; 836 } 837 else 838 { 839 lcd.clear (); 840 lcd.print ("TIDE E R R O R"); 841 lcd.setCursor (0, 1); 842 lcd.print (Tide_one); 843 delay (2500); 844 lcd.clear (); 845 return; 846 } 847 } 848 delay (50); 849 } 850 lcd.clear (); 851 return; 852 } 853 break; 854 case 7: 855 /////////////////////////////////////////////////////// 856 // PRO MODE // 857 /////////////////////////////////////////////////////// 858 { 859 if (pro_mode == false) 860 { 861 lcd.clear(); lcd.print("PRO Display "); 862 delay (1500); 863 pro_mode = true; 864 EEPROM.write(4, pro_mode); 865 } 866 else 867 { 868 lcd.clear(); lcd.print("Dashboard "); 869 pro_mode = false; 870 EEPROM.write(4, pro_mode); 871 delay (1500); 872 } 873 lcd.clear (); 874 } 875 break; 876 case 8: 877 /////////////////////////////////////////////////////// 878 // ODOMETRE // 879 /////////////////////////////////////////////////////// 880 { 881 Odometre = 0; 882 time_run = 0; 883 lat2 = lat; 884 lon2 = lon; 885 lcd.clear(); lcd.print("Odometre Reset"); 886 delay (1500); lcd.clear (); 887 } 888 break; 889 default: 890 { 891 } 892 return; 893 } 894} 895///////////////////////////////////////////////////////////////////////////////////// 896// SUBROUTINES // 897///////////////////////////////////////////////////////////////////////////////////// 898// writeBigChar: writes big character 'ch' to column x, row y; returns number of columns used by 'ch' 899int writeBigChar(char ch, byte x, byte y) { 900 if (ch < ' ' || ch > '_') return 0; // If outside table range, do nothing 901 nb = 0; // character byte counter 902 for (bc = 0; bc < 8; bc++) { 903 bb[bc] = pgm_read_byte( &bigChars[ch - ' '][bc] ); // read 8 bytes from PROGMEM 904 if (bb[bc] != 0) nb++; 905 } 906 bc = 0; 907 for (row = y; row < y + 2; row++) { 908 for (col = x; col < x + nb / 2; col++ ) { 909 lcd.setCursor(col, row); // move to position 910 lcd.write(bb[bc++]); // write byte and increment to next 911 } 912 } 913 return nb / 2 - 1; // returns number of columns used by char 914} 915// writeBigString: writes out each letter of string 916void writeBigString(char *str, byte x, byte y) 917{ 918 char c; 919 while ((c = *str++)) 920 x += writeBigChar(c, x, y) + 1; 921} 922/////////////////////////////////////////////////////// 923// HORLOGE // 924/////////////////////////////////////////////////////// 925void horloge(int C, int R) 926{ 927 lcd.setCursor(C, R); 928 lcd.print(hour); lcd.print(":"); 929 if (minute < 10) 930 { 931 lcd.print("0"); 932 } 933 lcd.print(minute); 934 lcd.print(" "); 935} 936/////////////////////////////////////////////////////// 937// LATITUDE // 938/////////////////////////////////////////////////////// 939void Print_Latitude(int C, int R) 940{ 941 long latdeg = (lat / 10000); 942 lcd.setCursor(C, R); 943 lcd.print("Lat:"); 944 lcd.print(abs(latdeg)); 945 lcd.print((char)223); 946 float x = (float)(lat - latdeg * 10000) * .6 / 100; 947 lcd.print(x); lcd.print("'"); 948 if (lat > 0) 949 { 950 lcd.print ("N"); 951 } 952 else 953 { 954 lcd.print("S"); 955 } 956} 957/////////////////////////////////////////////////////// 958// PRINT LONGITUDE // 959/////////////////////////////////////////////////////// 960void Print_Longitude(int C, int R) 961{ 962 long londeg = (lon / 10000); 963 lcd.setCursor(C, R); 964 lcd.print("Lon:"); 965 lcd.print(abs(londeg)); 966 lcd.print((char)223); 967 float x = (float) (abs(lon) - abs(londeg) * 10000) * .6 / 100; 968 lcd.print(x); lcd.print("'"); 969 if (lon > 0) { 970 lcd.print("E"); 971 } 972 else { 973 lcd.print("W"); 974 } 975} 976 977/////////////////////////////////////////////////////// 978// TIDE CLOCK display // 979/////////////////////////////////////////////////////// 980void Print_Tide(int C, int R) 981{ 982 EEPROM.get(20, Tide_one); 983 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 "}; 984 //Serial.print ("y min="); //Serial.println (Year_Min); 985 //Serial.print ("tide 1="); //Serial.println (Tide_one); 986 long tide_cycle = (Year_Min - Tide_one); 987 //Serial.print ("tide cycle="); //Serial.println (tide_cycle); 988 float tide_cyclef = (float)tide_cycle / 745.233333f; //Tide 12h25m14sec (745.23 min) 989 dtostrf (tide_cyclef, 1, 6, msg) ; 990 //Serial.print ("tide cyclef="); //Serial.println (msg); 991 tide_cyclef = tide_cyclef - int(tide_cyclef); 992 dtostrf (tide_cyclef, 1, 6, msg) ; 993 //Serial.print ("tide cyclefraction="); //Serial.println (msg); 994 tide_cyclef = tide_cyclef * 12; 995 dtostrf (tide_cyclef, 1, 6, msg) ; 996 tide_cycle = round (tide_cyclef); 997 lcd.setCursor(C, R); 998 lcd.print ("Tide:"); 999 lcd.print (tideclock[tide_cycle]); 1000 //; break; 1001 //delay (1000); lcd.setCursor(C, R); lcd.print ("Tide:"); lcd.print (tide_cyclef); delay (700); 1002} 1003/////////////////////////////////////////////////////// 1004// Azimut // 1005/////////////////////////////////////////////////////// 1006void Print_Azimut(int C, int R) 1007{ 1008 int azimut = gps.course() / 100; 1009 lcd.setCursor(C, R); 1010 lcd.print(azimut); 1011 lcd.print((char)223); 1012 azimut = (int)((azimut + 22.5f) / 45); 1013 lcd.print (azimuts[azimut % 8]); lcd.print (" "); 1014} 1015/////////////////////////////////////////////////////// 1016// Print DISTANCE et azimut to wp // 1017/////////////////////////////////////////////////////// 1018void Print_wpazimut(int C, int R) 1019{ 1020 1021 float lat_Rad = lat / 10000.0 * rad2deg;// convert decimal degree into radian 1022 float lon_Rad = lon / 10000.0 * rad2deg; 1023 float wp_lat_Rad = wp_lat / 10000.0 * rad2deg; 1024 float wp_lon_Rad = wp_lon / 10000.0 * rad2deg; 1025 float latSin = sin((lat_Rad - wp_lat_Rad) / 2);// Calculate the distance KM 1026 float lonSin = sin((lon_Rad - wp_lon_Rad) / 2); 1027 float distancekm = 2 * asin(sqrt((latSin * latSin) + cos(lat_Rad) * cos(wp_lat_Rad) * (lonSin * lonSin))); 1028 distancekm *= 6371; //Earth radius = 6,371 km 1029 float yy = sin(wp_lon_Rad - lon_Rad) * cos(wp_lat_Rad); 1030 float xx = cos(lat_Rad) * sin(wp_lat_Rad) - sin(lat_Rad) * cos(wp_lat_Rad) * cos(wp_lon_Rad - lon_Rad); 1031 float fwd_azimut = atan2(yy, xx); 1032 fwd_azimut = round(fwd_azimut * 57.2958); //rad 2 deg 1033 if (fwd_azimut < 0 ) 1034 { 1035 fwd_azimut = 360 + fwd_azimut; 1036 } 1037 if (distancekm < 10) 1038 { 1039 dtostrf (distancekm, 2, 2, msg) ; 1040 } 1041 else 1042 { 1043 dtostrf (distancekm, 2, 0, msg) ; 1044 } 1045 lcd.setCursor(C, R); lcd.print (msg); lcd.print ("km"); 1046 dtostrf (fwd_azimut, 2, 0, msg) ; 1047 lcd.print (msg); lcd.print((char)223); lcd.print (" "); 1048} 1049 1050 1051
Kayak GPS
arduino
Navigation GPS powered by solar energy.
1/* 2*/ 3 4#include <SoftwareSerial.h> 5#include <TinyGPS.h> 6#include <LiquidCrystal.h> 7#include <EEPROM.h> 8 9#include <avr/pgmspace.h> 10LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //8>RS,9>E, 4-7>D4-D7,RW>0V, 11SoftwareSerial gpsSerial(2, 3); //RX, TX 2>bleuTX, 3>VertRX 12TinyGPS gps; 13 14byte clo_n = 0; 15boolean eco_mode = false; 16boolean pro_mode = false; 17static int vref = 211; // 1023/4.9 volts 18byte solPanel = 3; //pin 19byte batt = 4; //pin 20byte LCD_LED = 11; 21byte power_pin = 12; 22byte sw_sel = 14;// select 23byte sw_up = 15;// up 24byte sw_dwn = 16;//down 25byte fonction = 0; 26int gmt;//, hr ; 27long Year_Min; 28long Tide_one; 29unsigned long time_On; 30unsigned long time_run; 31unsigned long time_old; 32 33int year;//, vinfo; 34int menu_index = 0; 35int cum_n; 36static float rad2deg = 0.01745; 37float Odometre; 38char msg[6]; 39byte LCD_LED_N = 220; //OFF 0-a-255 ON 40byte col, row, nb = 0, bc = 0; // general 41byte bb[8]; 42byte month, day, hour, minute, second, sped; //hundredths, 43long lat, lon; //, latmin, lonmin; //angle 44long lat2 = 0; 45long lon2 = 0; 46long wp_lat, wp_lon ; 47 48const char*azimuts[] = {"N ", "NE ", "E ", "SE ", "S ", "SW ", "W ", "NW " }; 49const char custom[][8] PROGMEM = { // Custom character definitions 50 { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 }, // char 1 51 { 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 2 52 { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x03 }, // char 3 53 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 4 54 { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1C, 0x18 }, // char 5 55 { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F }, // char 6 56 { 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 7 57 { 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 8 58 59}; 60const char bigChars[][8] PROGMEM = { 61 { 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Space 62 { 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ! 63 { 0x05, 0x05, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00 }, // " 64 { 0x04, 0xFF, 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01 }, // # 65 { 0x08, 0xFF, 0x06, 0x07, 0xFF, 0x05, 0x00, 0x00 }, // $ 66 { 0x01, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x04 }, // % 67 { 0x08, 0x06, 0x02, 0x20, 0x03, 0x07, 0x02, 0x04 }, // & 68 { 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' 69 { 0x08, 0x01, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 }, // ( 70 { 0x01, 0x02, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00 }, // ) 71 { 0x01, 0x04, 0x04, 0x01, 0x04, 0x01, 0x01, 0x04 }, // * 72 { 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01, 0x00, 0x00 }, // + 73 { 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 74 { 0x04, 0x04, 0x04, 0x20, 0x20, 0x20, 0x00, 0x00 }, // - 75 { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // . 76 { 0x20, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x20 }, // / 77 { 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00 }, // 0 78 { 0x01, 0x02, 0x20, 0x04, 0xFF, 0x04, 0x00, 0x00 }, // 1 79 { 0x06, 0x06, 0x02, 0xFF, 0x07, 0x07, 0x00, 0x00 }, // 2 80 { 0x01, 0x06, 0x02, 0x04, 0x07, 0x05, 0x00, 0x00 }, // 3 81 { 0x03, 0x04, 0xFF, 0x20, 0x20, 0xFF, 0x00, 0x00 }, // 4 82 { 0xFF, 0x06, 0x06, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 5 83 { 0x08, 0x06, 0x06, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 6 84 { 0x01, 0x01, 0x02, 0x20, 0x08, 0x20, 0x00, 0x00 }, // 7 85 { 0x08, 0x06, 0x02, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 8 86 { 0x08, 0x06, 0x02, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 9 87}; 88 89const 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}; 90const 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}; 91const static byte gpsSleep[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x16, 0x74}; 92const static byte gpsHot[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x68}; 93const 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 94const 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 95const 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 96const 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 97const 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 98const 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 99const 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 100const 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 101const 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 102const 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 103const 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 104 105/////////////////////////////////////////////////////// 106// Minute depuis debut annee // 107/////////////////////////////////////////////////////// 108int 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. 109long DofY(int yr, int mo, int dy, int h, int mi) 110{ 111 int DfY; 112 long Min2Date; 113 if (mo == 1 || mo == 2) 114 { 115 DfY = days[mo] + dy - 1; //for any type of year, it calculate the number of days for January or february 116 } 117 else if ((yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0) 118 { 119 DfY = days[mo] + dy + 1 - 1; 120 } 121 else 122 { 123 DfY = days[mo] + dy - 1; 124 } 125 Min2Date = (long)DfY * 1440l + (long)h * 60l + (long)mi; 126 return (Min2Date); 127} 128/////////////////////////////////////////////////////// 129// SETUP // 130/////////////////////////////////////////////////////// 131void setup() 132{ 133 pinMode(power_pin, OUTPUT); 134 digitalWrite (power_pin, HIGH); // POWER ON! 135 analogReference(DEFAULT); 136 pinMode(LED_BUILTIN, OUTPUT); 137 digitalWrite(LED_BUILTIN, LOW); 138 Serial.begin(9600); 139 gpsSerial.begin(9600); 140 pinMode(LCD_LED, OUTPUT); 141 //pinMode(buz, OUTPUT); 142 pinMode(sw_sel, INPUT); 143 pinMode(sw_up, INPUT); 144 pinMode(sw_dwn, INPUT); 145 lcd.begin(16, 2); 146 analogWrite(LCD_LED, 100); 147 148 /////////////////////////////////////////////////////// 149 // EE PROM Variable // 150 /////////////////////////////////////////////////////// 151 hour = EEPROM.read(0); //lire le gmt 152 pro_mode = EEPROM.read(4); 153 EEPROM.get(10, wp_lat); 154 EEPROM.get(15, wp_lon); 155 EEPROM.get(20, Tide_one); 156 EEPROM.get(25, Odometre); 157 EEPROM.get(30, time_On); 158 if (isnan(Odometre)) // test if NAN value 159 { 160 Odometre = 0; 161 } 162 if (hour > 127) //numbre negatif 163 { 164 gmt = hour - 256; 165 } 166 else 167 { 168 gmt = hour; 169 } 170 /////////////////////////////////////////////////////// 171 /// R E V /// 172 /////////////////////////////////////////////////////// 173 lcd.clear(); 174 lcd.print(F("Ultimate YAK GPS")); 175 lcd.setCursor(0, 1); 176 lcd.print(F("GPS_1602B rev 92.1")); // Revision Version<<<< 177 delay (2000); 178 lcd.clear(); 179 lcd.print("GMT="); lcd.print(gmt); 180 float vbatt = (float) analogRead(batt) / vref + .21; // 181 lcd.setCursor(0, 1); 182 lcd.print(F("Batterie:")); 183 lcd.print(vbatt); 184 lcd.print("V"); 185 delay (2000); 186 lcd.clear(); 187 lcd.print(F("Odometre:")); 188 lcd.print(Odometre); 189 delay (2000); 190 lcd.clear(); 191 lcd.print("WPLat:"); 192 lcd.print(wp_lat); 193 lcd.setCursor(0, 1); 194 lcd.print("WPLon:"); 195 lcd.print(wp_lon); 196 delay (2000); 197 lcd.clear(); 198 lcd.print("Last Time ON:"); 199 lcd.setCursor(0, 1); 200 lcd.print(time_On / 60000); lcd.print("Min"); 201 delay (4000); 202 203 204 /*lcd.clear(); 205 lcd.print("TIDE: "); 206 lcd.print(Tide_one); 207 float a = (float)Tide_one / 288; //288 = 24hr * 60/ 5 min/hr) 208 int tide_jr = (int)a; 209 float b = (a - (float) tide_jr) * 24; 210 tide_hr = (int)b; 211 tide_min = (b - (float) tide_hr) * 60 ; 212 lcd.setCursor(0, 1); 213 lcd.print(tide_jr + 1); 214 lcd.print("Days "); 215 lcd.print(tide_hr); 216 lcd.print(":"); 217 lcd.print(tide_min); 218 delay(2000); 219 */ 220 221 222 if (vbatt < 2.8)//volts 223 { 224 lcd.setCursor(0, 1); lcd.print("Batt. LOW!"); 225 delay (4000); 226 //digitalWrite(power_pin, LOW); //off 227 } 228 analogWrite(LCD_LED, 20); 229 230 /////////////////////////////////////////////////////// 231 // GPS Reset // 232 /////////////////////////////////////////////////////// 233 lcd.clear(); 234 235 if (gps.encode(gpsSerial.read())) 236 { 237 lcd.print("GPS Reset"); 238 gpsSerial.write(gpsHot, sizeof(gpsHot)); gpsSerial.flush(); 239 gpsSerial.write( gpsDefault, sizeof( gpsDefault)); gpsSerial.flush(); 240 gpsSerial.write( Disable_GPDTM, sizeof( Disable_GPDTM)); gpsSerial.flush(); 241 gpsSerial.write( Disable_GPGBS, sizeof( Disable_GPGBS)); gpsSerial.flush(); 242 gpsSerial.write( Disable_GPGLL, sizeof( Disable_GPGLL)); gpsSerial.flush(); 243 gpsSerial.write( Disable_GPGRS, sizeof( Disable_GPGRS)); gpsSerial.flush(); 244 gpsSerial.write( Disable_GPGSA, sizeof( Disable_GPGSA)); gpsSerial.flush(); 245 gpsSerial.write( Disable_GPGSV, sizeof( Disable_GPGSV)); gpsSerial.flush(); 246 gpsSerial.write( Disable_GPVTG, sizeof( Disable_GPVTG)); gpsSerial.flush(); 247 gpsSerial.write( Disable_GPGGA, sizeof( Disable_GPGGA)); gpsSerial.flush(); 248 } 249 lcd.setCursor(0, 1); lcd.println(F("Wait satellites.")); 250 /////////////////////////////////////////////////////// 251 /// create 8 custom characters /// 252 /////////////////////////////////////////////////////// 253 for (nb = 0; nb < 8; nb++ ) 254 { 255 for (bc = 0; bc < 8; bc++) 256 bb[bc] = pgm_read_byte( &custom[nb][bc] ); 257 lcd.createChar ( nb + 1, bb ); 258 } 259} 260////////////////////////////////////////////////////////////////////////////////////////////////////////////// 261/// L O O P /// 262////////////////////////////////////////////////////////////////////////////////////////////////////////////// 263void loop() 264{ 265 while (gpsSerial.available()) // check for gps data 266 { 267 if (gps.encode(gpsSerial.read())) // encode gps data 268 { 269 gps.get_position(&lat, &lon); // get lat and long 270 gps.crack_datetime(&year, &month, &day, &hour, &minute, &second); 271 lat = lat / 100; //enlever les d-secondes 272 lon = lon / 100; 273 // lcd.setCursor(0, 0); lcd.print (lat); lcd.print (" "); lcd.print (lon); delay (4000); 274 hour = hour + gmt; 275 if (hour > 128) // reference a gmt 276 { 277 hour = hour + 24; 278 day = day - 1; 279 } 280 ////Serial.print ("DofY=");//Serial.println (DofY (year,month,day,hour,minute)); 281 //Serial.print (year); //Serial.print ("/"); //Serial.print (month); //Serial.print ("/"); //Serial.print (day); //Serial.print (" "); //Serial.print (hour); //Serial.print (":"); //Serial.println (minute); 282 Year_Min = DofY ((int)year, (int)month, (int)day, (int)hour, (int)minute); 283 //Serial.print ("Year2min ="); //Serial.println (Year_Min); 284 285 286 if (digitalRead(sw_sel) == LOW) { 287 lcd.clear(); 288 while (digitalRead(sw_sel) == 0) {} // wait for release 289 menu(0); 290 } 291 if (digitalRead(sw_dwn) == LOW) 292 { 293 lcd.clear(); 294 while (digitalRead(sw_dwn) == 0) {} // wait for release 295 if (pro_mode == false) 296 { 297 lcd.clear(); lcd.print("PRO Display "); 298 delay (1500); 299 pro_mode = true; 300 EEPROM.write(4, pro_mode); 301 } 302 else 303 { 304 lcd.clear(); lcd.print("Dashboard MODE "); 305 pro_mode = false; 306 EEPROM.write(4, pro_mode); 307 delay (1500); 308 } 309 lcd.clear (); 310 } 311 /////////////////////////////////////////////////////// 312 // LCD LED & test de batt // 313 /////////////////////////////////////////////////////// 314 float vsol = (float) analogRead(solPanel) / vref ; // 1024/2.5voltsRef 315 if (eco_mode == true) { 316 LCD_LED_N = 20; 317 } 318 else { 319 LCD_LED_N = 150; 320 } 321 if (vsol > 1) {//volt 322 vsol = 1;//volt 323 } 324 LCD_LED_N = LCD_LED_N - (vsol * LCD_LED_N); 325 analogWrite(LCD_LED, LCD_LED_N); 326 327 float vbatt = (float) analogRead(batt) / vref + .21; // 1024/5voltsRef 328 if (vbatt < 2.8) // Volts 2.8 329 { 330 lcd.clear(); lcd.print("LOW BATT "); 331 lcd.setCursor(0, 1); lcd.print(vbatt); lcd.print("Volts"); 332 EEPROM.put(25, Odometre); //save odometre 333 delay (5000); 334 digitalWrite(power_pin, LOW);// power off 335 } 336 if (vbatt > 4.2) // Volts 337 { 338 analogWrite(LCD_LED, 255); 339 digitalWrite(LED_BUILTIN, HIGH); 340 } 341 else 342 { 343 digitalWrite(LED_BUILTIN, LOW); 344 } 345 float speedf = gps.speed() * .01852; // 1.852 /100 knot to kmph 346 347 if (speedf < .5) 348 { 349 speedf = 0; 350 } 351 /////////////////////////////////////////////////////// 352 /// ODOMETRE /// 353 /////////////////////////////////////////////////////// 354 if (cum_n >= 10) 355 { 356 if (lat2 == 0) 357 { 358 lat2 = lat; 359 lon2 = lon; 360 } 361 cum_n = 0; 362 float lon2_dec = lon2 / 10000.0; 363 /////////////////////convert decimal degree into radian//////////////// 364 float lat1_Rad = lat / 10000.0 * rad2deg; 365 float lon1_Rad = lon / 10000.0 * rad2deg; 366 float lat2_Rad = lat2 / 10000.0 * rad2deg; 367 float lon2_Rad = lon2 / 10000.0 * rad2deg; 368 369 //Calculate the distance KM 370 float latSin = sin((lat1_Rad - lat2_Rad) / 2); 371 float lonSin = sin((lon1_Rad - lon2_Rad) / 2); 372 373 float P2P = 2 * asin(sqrt((latSin * latSin) + cos(lat1_Rad) * cos(lat2_Rad) * (lonSin * lonSin))); 374 P2P = P2P * 6371; //Earth radius = 6,371 km 375 376 if (P2P < 5 && speedf != 0) // plus de 5 km est une erreur ou speed =0kmh 377 { 378 Odometre += P2P; 379 lat2 = lat; 380 lon2 = lon; 381 EEPROM.put(25, Odometre); 382 time_run = time_run + (millis() - time_old); 383 384 EEPROM.put(30, millis()); //future reference 385 } 386 time_old = millis(); 387 } 388 else 389 { 390 cum_n ++; 391 } 392 /////////////////////////////////////////////////////// 393 // V I T E S S E // 394 /////////////////////////////////////////////////////// 395 396 dtostrf (speedf, 3, 1, msg) ; 397 if (pro_mode == false) 398 { 399 writeBigString(msg, 0, 0); 400 lcd.setCursor(7, 0); lcd.print ("KM "); 401 lcd.setCursor(7, 1); lcd.print ("/H "); 402 lcd.setCursor(10, 0); 403 if (Odometre < 100) 404 { 405 dtostrf (Odometre, 1, 1, msg) ; 406 } 407 else 408 { 409 dtostrf (Odometre, 1, 0, msg) ; 410 } 411 lcd.print (msg); lcd.print ("KM "); 412 413 horloge (10, 1); 414 } 415 else 416 { 417 lcd.setCursor(0, 0); 418 lcd.print(msg); lcd.print("KMH ");//dtostrf (speedf, 3, 1, msg) ; 419 Print_Azimut(8, 0); 420 horloge(0, 1) ; 421 /////////////////////////////////////////////////////// 422 // Display Fonction Variable // 423 /////////////////////////////////////////////////////// 424 fonction++; 425 switch (fonction / 3) 426 { 427 case 1: 428 { 429 Print_wpazimut(6, 1); 430 EEPROM.put(30, millis()); 431 } 432 break; 433 case 4: 434 { 435 Print_Tide(6, 1); 436 } 437 break; 438 case 2: 439 { 440 lcd.setCursor(6, 1); 441 if (Odometre < 100) 442 { 443 dtostrf (Odometre, 1, 1, msg) ; 444 } 445 else 446 { 447 dtostrf (Odometre, 1, 0, msg) ; 448 } 449 lcd.print ("Od:"); lcd.print (msg); lcd.print ("KM "); 450 } 451 break; 452 case 3: 453 { 454 lcd.setCursor(6, 1); 455 lcd.print ("Run:"); 456 if (time_run > 10000000L)//msec 457 { 458 lcd.print (time_run / 3600000L);//msec 459 lcd.print ("Hr "); 460 } 461 else 462 { 463 lcd.print (time_run / 60000L);//msec 464 lcd.print ("Min "); 465 } 466 } 467 break; 468 default: 469 { 470 fonction = 2; 471 } 472 break; 473 } 474 /////////////////////////////////////////////////////// 475 // eco mode 476 // 477 /////////////////////////////////////////////////////// 478 if (eco_mode == true) 479 { 480 //char buffer[4]; //2del 481 gpsSerial.write(gpsSleep, sizeof(gpsSleep)); 482 gpsSerial.flush(); 483 for (int n = 0; n < 6 ; n++)//Sec. 484 { 485 lcd.setCursor(15, 0); lcd.print (n); 486 Print_Tide(6, 1); 487 delay (1500); 488 Print_wpazimut(6, 1); 489 delay (1500); 490 if (digitalRead(sw_sel) == 0) 491 { 492 lcd.clear (); 493 while (digitalRead(sw_sel) == 0) {}; delay(10); // debounce 494 menu(0); 495 } 496 } 497 gpsSerial.write(gpsHot, sizeof(gpsHot)); 498 gpsSerial.flush(); 499 delay (2000); // 500 //vinfo = 1; 501 } 502 } 503 } 504 } 505} 506 507/////////////////////////////////////////////////////// 508// MENU // 509/////////////////////////////////////////////////////// 510static char* menu_items [] = {"Sel-UP-down", "Power OFF", "Lat-Long & WP ", "Power Moniteur", 511 "Eco Mode", "GMT set ", "TIDE set" , "Display Mode", "Odometre", "Retour", "Sel-up-DOWN" 512 }; 513void menu(int menu_index) 514{ 515 lcd.clear(); lcd.print(menu_items[menu_index]); 516 while (digitalRead(sw_sel) == LOW) {}; delay(5); //Debounce 517 while (digitalRead(sw_sel) != LOW)// Select 518 { 519 if (digitalRead(sw_up) == LOW) 520 { 521 lcd.clear(); 522 while (digitalRead(sw_up) == LOW) {}; delay(10); //Debounce 523 menu_index ++; 524 if (menu_index > 8) 525 { 526 menu_index = 0; 527 } 528 lcd.clear(); 529 //lcd.setCursor(0, 0); lcd.print(menu_items[0]); 530 lcd.setCursor(0, 1); 531 lcd.print(menu_items[menu_index]); 532 } 533 if (digitalRead(sw_dwn) == LOW) 534 { 535 lcd.clear(); 536 while (digitalRead(sw_dwn) == LOW) {}; delay(10); //Debounce 537 menu_index -= 1; 538 if (menu_index < 0) 539 { 540 menu_index = 8; 541 } 542 lcd.clear(); 543 lcd.print(menu_items[0]); 544 lcd.setCursor(0, 1); 545 lcd.print(menu_items[menu_index]); 546 } 547 } 548 lcd.clear(); 549 while (digitalRead(sw_sel) == LOW) {}; delay(100); //Debounce 550 switch (menu_index) 551 { 552 case 1: 553 /////////////////////////////////////////////////////// 554 // POWER OFF // 555 /////////////////////////////////////////////////////// 556 { 557 lcd.clear(); 558 lcd.print ("POWER OFF...."); 559 delay (1500); 560 digitalWrite(power_pin, LOW); 561 delay (50); 562 asm volatile (" jmp 0"); 563 } 564 break; 565 case 2: 566 /////////////////////////////////////////////////////// 567 // LAT et LONG MEMO // 568 /////////////////////////////////////////////////////// 569 { 570 lcd.clear (); 571 lcd.setCursor (0, 0); 572 lcd.print("Push DWN to Save") ; 573 lcd.setCursor (0, 1); 574 lcd.print("WayPoint ") ; 575 delay (1000); lcd.clear (); 576 while (digitalRead(sw_sel) != LOW) 577 { 578 Print_Latitude (0, 0); 579 Print_Longitude (0, 1); 580 if (digitalRead(sw_dwn) == LOW) 581 { 582 wp_lat = lat; 583 wp_lon = lon; 584 EEPROM.put(10, lat); 585 EEPROM.put(15, lon); 586 lcd.clear (); 587 lcd.setCursor (0, 0); 588 lcd.print("WayPoint SAVED") ; 589 delay (1500); 590 break; 591 } 592 if (digitalRead(sw_up) == LOW) 593 { 594 lcd.clear (); 595 lcd.setCursor (0, 0); 596 lcd.print("Push DWN to Save") ; 597 while (digitalRead(sw_up) == LOW) {}; 598 delay(1000); 599 lcd.clear (); 600 } 601 gps.get_position(&lat, &lon); 602 lat = lat / 100; //enlever les d-secondes 603 lon = lon / 100; 604 } 605 lcd.clear (); 606 while (digitalRead(sw_sel) == LOW) {}; 607 } 608 break; 609 case 3: 610 /////////////////////////////////////////////////////// 611 // POWER MONITOR batt sol // 612 /////////////////////////////////////////////////////// 613 { 614 gpsSerial.write(gpsSleep, sizeof(gpsSleep)); 615 while (3) 616 { 617 float vsol = (float) analogRead(solPanel) / 204; // 1024/5voltsRef 618 dtostrf (vsol, 3, 1, msg) ; 619 lcd.setCursor(0, 0); 620 lcd.print ("Solaire="); 621 lcd.print (msg); 622 lcd.print ("V "); 623 float vbatt = (float) analogRead(batt) / vref + .21; // 1024/5voltsRef 624 dtostrf (vbatt, 3, 1, msg) ; 625 lcd.setCursor(0, 1); 626 lcd.print ("Batterie="); 627 lcd.print (msg); lcd.print ("V "); 628 if ((vsol - vbatt) > .4)//volts 629 { 630 lcd.setCursor(12, 1); lcd.print ("V Charge "); 631 } 632 else 633 { 634 lcd.setCursor(12, 1); lcd.print ("V "); 635 } 636 delay (1000); 637 if (digitalRead(sw_sel) == LOW) 638 { 639 lcd.clear(); 640 while (digitalRead(sw_sel) == LOW) {} ; 641 gpsSerial.write(gpsHot, sizeof(gpsHot)); 642 return; 643 } 644 delay (1000); 645 } 646 } 647 break; 648 case 4: 649 /////////////////////////////////////////////////////// 650 /// ECO MODE select /// 651 /////////////////////////////////////////////////////// 652 { 653 if (eco_mode == false) 654 { 655 lcd.setCursor(0, 0); lcd.print("ECONO MODE ON "); 656 delay (1500); 657 eco_mode = true; 658 analogWrite(LCD_LED, 0); // off lcd led 659 } 660 else 661 { 662 lcd.setCursor(0, 0); lcd.print("ECONO MODE OFF "); 663 eco_mode = false; 664 delay (1500); 665 analogWrite(LCD_LED, LCD_LED_N); // off lcd led 666 } 667 lcd.clear (); 668 } 669 break; 670 case 5: 671 /////////////////////////////////////////////////////// 672 // GMT // 673 /////////////////////////////////////////////////////// 674 { 675 //gmt = 0; 676 while (digitalRead(sw_sel) != LOW) 677 { 678 if (digitalRead(sw_up) == LOW) 679 { 680 lcd.clear (); 681 while (digitalRead(sw_up) == LOW) {} ; 682 gmt ++; 683 } 684 if (digitalRead(sw_dwn) == LOW) 685 { 686 lcd.clear (); 687 while (digitalRead(sw_dwn) == LOW) {} ; 688 gmt --; 689 } 690 lcd.clear(); 691 lcd.print ("GMT"); 692 lcd.print(gmt); 693 delay (300); 694 } 695 lcd.clear (); 696 while (digitalRead(sw_sel) == LOW) {} ; 697 lcd.setCursor (0, 1); 698 lcd.print ("SET GMT"); 699 lcd.print(gmt); 700 EEPROM.write(0, gmt); 701 delay(1000); 702 return; 703 } 704 break; 705 case 6: 706 /////////////////////////////////////////////////////// 707 // SET TIDE // 708 /////////////////////////////////////////////////////// 709 { 710 //int tide_min, tide_hr; 711 lcd.setCursor (0, 0); 712 lcd.print ("Set "); 713 lcd.setCursor (0, 1); 714 lcd.print ("FullMoonHighTide"); 715 EEPROM.get(20, Tide_one); 716 int tide_mth = 1; 717 //float a = (float)Tide_one / 288; //288 = 24hr * 60/ 5 min/hr) 718 int tide_jr = 12; //(int)a; 719 //float b = (a - (float) tide_jr) * 24; 720 int tide_hr = 7; // (int)b; 721 int tide_min = 45; //(b - (float) tide_hr) * 60 ; 722 723 /////////////////////////////////////////////////////// 724 lcd.clear (); 725 while (digitalRead(sw_sel) != LOW) 726 { 727 lcd.setCursor (0, 1); 728 lcd.print (tide_mth); lcd.print("/"); 729 lcd.setCursor (3, 1); lcd.print(tide_jr); lcd.print(" "); 730 lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" "); 731 lcd.setCursor (0, 0) ; 732 lcd.print("v--Month "); 733 delay (350); 734 if (digitalRead(sw_up) == LOW) 735 { 736 tide_mth ++; 737 } 738 if (digitalRead(sw_dwn) == LOW) 739 { 740 tide_mth --; 741 } 742 } 743 /////////////////////////////////////////////////////// 744 lcd.clear (); 745 while (digitalRead(sw_sel) == LOW) {}; delay (100); 746 while (digitalRead(sw_sel) != LOW) 747 { 748 lcd.setCursor (0, 1); 749 lcd.print (tide_mth); lcd.print("/"); 750 lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" "); 751 lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" "); 752 lcd.setCursor (3, 0); 753 delay (350); 754 lcd.print("v--Day "); 755 if (digitalRead(sw_up) == LOW) 756 { 757 tide_jr ++; 758 } 759 if (digitalRead(sw_dwn) == LOW) 760 { 761 tide_jr --; 762 } 763 } 764 /////////////////////////////////////////////////////// 765 766 lcd.clear (); 767 while (digitalRead(sw_sel) == LOW) {}; delay (100); 768 while (digitalRead(sw_sel) != LOW) 769 { 770 lcd.setCursor (0, 1); 771 lcd.print (tide_mth); lcd.print("/"); 772 lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" "); 773 lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" "); 774 lcd.setCursor (8, 0); 775 lcd.print("v--Hr "); 776 delay (350); 777 if (digitalRead(sw_up) == LOW) 778 { 779 tide_hr ++; 780 } 781 if (digitalRead(sw_dwn) == LOW) 782 { 783 tide_hr --; 784 } 785 } 786 /////////////////////////////////////////////////////// 787 lcd.clear (); 788 while (digitalRead(sw_sel) == LOW) {}; delay (100); 789 while (digitalRead(sw_sel) != LOW) 790 { 791 lcd.setCursor (0, 1); 792 lcd.print (tide_mth); lcd.print("/"); 793 lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" "); 794 lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" "); 795 lcd.setCursor (5, 0); 796 lcd.print("Min--v "); 797 delay (350); 798 if (digitalRead(sw_up) == LOW) 799 { 800 tide_min += 5; 801 } 802 if (digitalRead(sw_dwn) == LOW) 803 { 804 tide_min -= 5; 805 } 806 if (tide_min < 1) { 807 tide_min = 1; // prevention 0/5 808 } 809 } 810 lcd.clear (); 811 while (digitalRead(sw_sel) == LOW) {} 812 Tide_one = DofY (year, tide_mth, tide_jr, tide_hr, tide_min); 813 lcd.setCursor (0, 0); 814 lcd.print ("Tide_one="); lcd.print (Tide_one); lcd.print (" "); 815 lcd.setCursor (0, 1); 816 lcd.print (tide_mth); lcd.print("/"); lcd.print (tide_jr ); lcd.print (" "); lcd.print (tide_hr); lcd.print (":"); lcd.print (tide_min); 817 delay (3500); 818 while (digitalRead(sw_sel) == LOW) { } 819 lcd.clear (); 820 lcd.print ("Push Dwn to Save"); 821 while (digitalRead(sw_sel) != LOW) 822 { 823 if (digitalRead(sw_dwn) == LOW) 824 { 825 if (Tide_one > 0) 826 { 827 EEPROM.put(20, Tide_one); 828 lcd.clear (); 829 lcd.print ("TIDE SAVED"); 830 lcd.setCursor (0, 1); 831 lcd.print (Tide_one); 832 delay (2000); 833 while (digitalRead(sw_dwn) == LOW) { } 834 lcd.clear (); 835 return; 836 } 837 else 838 { 839 lcd.clear (); 840 lcd.print ("TIDE E R R O R"); 841 lcd.setCursor (0, 1); 842 lcd.print (Tide_one); 843 delay (2500); 844 lcd.clear (); 845 return; 846 } 847 } 848 delay (50); 849 } 850 lcd.clear (); 851 return; 852 } 853 break; 854 case 7: 855 /////////////////////////////////////////////////////// 856 // PRO MODE // 857 /////////////////////////////////////////////////////// 858 { 859 if (pro_mode == false) 860 { 861 lcd.clear(); lcd.print("PRO Display "); 862 delay (1500); 863 pro_mode = true; 864 EEPROM.write(4, pro_mode); 865 } 866 else 867 { 868 lcd.clear(); lcd.print("Dashboard "); 869 pro_mode = false; 870 EEPROM.write(4, pro_mode); 871 delay (1500); 872 } 873 lcd.clear (); 874 } 875 break; 876 case 8: 877 /////////////////////////////////////////////////////// 878 // ODOMETRE // 879 /////////////////////////////////////////////////////// 880 { 881 Odometre = 0; 882 time_run = 0; 883 lat2 = lat; 884 lon2 = lon; 885 lcd.clear(); lcd.print("Odometre Reset"); 886 delay (1500); lcd.clear (); 887 } 888 break; 889 default: 890 { 891 } 892 return; 893 } 894} 895///////////////////////////////////////////////////////////////////////////////////// 896// SUBROUTINES // 897///////////////////////////////////////////////////////////////////////////////////// 898// writeBigChar: writes big character 'ch' to column x, row y; returns number of columns used by 'ch' 899int writeBigChar(char ch, byte x, byte y) { 900 if (ch < ' ' || ch > '_') return 0; // If outside table range, do nothing 901 nb = 0; // character byte counter 902 for (bc = 0; bc < 8; bc++) { 903 bb[bc] = pgm_read_byte( &bigChars[ch - ' '][bc] ); // read 8 bytes from PROGMEM 904 if (bb[bc] != 0) nb++; 905 } 906 bc = 0; 907 for (row = y; row < y + 2; row++) { 908 for (col = x; col < x + nb / 2; col++ ) { 909 lcd.setCursor(col, row); // move to position 910 lcd.write(bb[bc++]); // write byte and increment to next 911 } 912 } 913 return nb / 2 - 1; // returns number of columns used by char 914} 915// writeBigString: writes out each letter of string 916void writeBigString(char *str, byte x, byte y) 917{ 918 char c; 919 while ((c = *str++)) 920 x += writeBigChar(c, x, y) + 1; 921} 922/////////////////////////////////////////////////////// 923// HORLOGE // 924/////////////////////////////////////////////////////// 925void horloge(int C, int R) 926{ 927 lcd.setCursor(C, R); 928 lcd.print(hour); lcd.print(":"); 929 if (minute < 10) 930 { 931 lcd.print("0"); 932 } 933 lcd.print(minute); 934 lcd.print(" "); 935} 936/////////////////////////////////////////////////////// 937// LATITUDE // 938/////////////////////////////////////////////////////// 939void Print_Latitude(int C, int R) 940{ 941 long latdeg = (lat / 10000); 942 lcd.setCursor(C, R); 943 lcd.print("Lat:"); 944 lcd.print(abs(latdeg)); 945 lcd.print((char)223); 946 float x = (float)(lat - latdeg * 10000) * .6 / 100; 947 lcd.print(x); lcd.print("'"); 948 if (lat > 0) 949 { 950 lcd.print ("N"); 951 } 952 else 953 { 954 lcd.print("S"); 955 } 956} 957/////////////////////////////////////////////////////// 958// PRINT LONGITUDE // 959/////////////////////////////////////////////////////// 960void Print_Longitude(int C, int R) 961{ 962 long londeg = (lon / 10000); 963 lcd.setCursor(C, R); 964 lcd.print("Lon:"); 965 lcd.print(abs(londeg)); 966 lcd.print((char)223); 967 float x = (float) (abs(lon) - abs(londeg) * 10000) * .6 / 100; 968 lcd.print(x); lcd.print("'"); 969 if (lon > 0) { 970 lcd.print("E"); 971 } 972 else { 973 lcd.print("W"); 974 } 975} 976 977/////////////////////////////////////////////////////// 978// TIDE CLOCK display // 979/////////////////////////////////////////////////////// 980void Print_Tide(int C, int R) 981{ 982 EEPROM.get(20, Tide_one); 983 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 "}; 984 //Serial.print ("y min="); //Serial.println (Year_Min); 985 //Serial.print ("tide 1="); //Serial.println (Tide_one); 986 long tide_cycle = (Year_Min - Tide_one); 987 //Serial.print ("tide cycle="); //Serial.println (tide_cycle); 988 float tide_cyclef = (float)tide_cycle / 745.233333f; //Tide 12h25m14sec (745.23 min) 989 dtostrf (tide_cyclef, 1, 6, msg) ; 990 //Serial.print ("tide cyclef="); //Serial.println (msg); 991 tide_cyclef = tide_cyclef - int(tide_cyclef); 992 dtostrf (tide_cyclef, 1, 6, msg) ; 993 //Serial.print ("tide cyclefraction="); //Serial.println (msg); 994 tide_cyclef = tide_cyclef * 12; 995 dtostrf (tide_cyclef, 1, 6, msg) ; 996 tide_cycle = round (tide_cyclef); 997 lcd.setCursor(C, R); 998 lcd.print ("Tide:"); 999 lcd.print (tideclock[tide_cycle]); 1000 //; break; 1001 //delay (1000); lcd.setCursor(C, R); lcd.print ("Tide:"); lcd.print (tide_cyclef); delay (700); 1002} 1003/////////////////////////////////////////////////////// 1004// Azimut // 1005/////////////////////////////////////////////////////// 1006void Print_Azimut(int C, int R) 1007{ 1008 int azimut = gps.course() / 100; 1009 lcd.setCursor(C, R); 1010 lcd.print(azimut); 1011 lcd.print((char)223); 1012 azimut = (int)((azimut + 22.5f) / 45); 1013 lcd.print (azimuts[azimut % 8]); lcd.print (" "); 1014} 1015/////////////////////////////////////////////////////// 1016// Print DISTANCE et azimut to wp // 1017/////////////////////////////////////////////////////// 1018void Print_wpazimut(int C, int R) 1019{ 1020 1021 float lat_Rad = lat / 10000.0 * rad2deg;// convert decimal degree into radian 1022 float lon_Rad = lon / 10000.0 * rad2deg; 1023 float wp_lat_Rad = wp_lat / 10000.0 * rad2deg; 1024 float wp_lon_Rad = wp_lon / 10000.0 * rad2deg; 1025 float latSin = sin((lat_Rad - wp_lat_Rad) / 2);// Calculate the distance KM 1026 float lonSin = sin((lon_Rad - wp_lon_Rad) / 2); 1027 float distancekm = 2 * asin(sqrt((latSin * latSin) + cos(lat_Rad) * cos(wp_lat_Rad) * (lonSin * lonSin))); 1028 distancekm *= 6371; //Earth radius = 6,371 km 1029 float yy = sin(wp_lon_Rad - lon_Rad) * cos(wp_lat_Rad); 1030 float xx = cos(lat_Rad) * sin(wp_lat_Rad) - sin(lat_Rad) * cos(wp_lat_Rad) * cos(wp_lon_Rad - lon_Rad); 1031 float fwd_azimut = atan2(yy, xx); 1032 fwd_azimut = round(fwd_azimut * 57.2958); //rad 2 deg 1033 if (fwd_azimut < 0 ) 1034 { 1035 fwd_azimut = 360 + fwd_azimut; 1036 } 1037 if (distancekm < 10) 1038 { 1039 dtostrf (distancekm, 2, 2, msg) ; 1040 } 1041 else 1042 { 1043 dtostrf (distancekm, 2, 0, msg) ; 1044 } 1045 lcd.setCursor(C, R); lcd.print (msg); lcd.print ("km"); 1046 dtostrf (fwd_azimut, 2, 0, msg) ; 1047 lcd.print (msg); lcd.print((char)223); lcd.print (" "); 1048} 1049 1050 1051
Downloadable files
circuit
circuit
Documentation
YAK GPS Mk ii CASING
YAK GPS Mk ii CASING
YAK GPS Mk ii CASING
YAK GPS Mk ii CASING
Comments
Only logged in users can leave comments
Chrisroy
0 Followers
•0 Projects
Table of contents
Intro
13
0