Hardware components | ||||||
  | × | 1 | ||||
![]()  | 
  | × | 1 | |||
  | × | 1 | ||||
![]()  | 
  | × | 1 | |||
  | × | 1 | ||||
Need to find, mark, or return to a precise spot—without relying on your smartphone or any kind of network?Want a tool that works completely offline, protects your data, and keeps running far from digital civilization?
This is a standalone GPS device, ultra-compact, that shows distance and bearing (azimuth) to your saved waypoints, stores positions in permanent memory, and runs for days on a single battery.
No cloud, no accounts, no data leaving your device.It’s the perfect navigation instrument for hiking, field ops, ham radio, mapping, expeditions, or technical field notes.
Hiking / Trekking: Mark a summit, a shelter, a spring, and find your way back—precisely, even with no map or phone.
Ham radio / SOTA / Field Day: Pinpoint antenna or relay sites, navigate between key locations, prepare field operations anywhere.
Geology, forestry, archaeology: Log and revisit sampling points or areas of interest, with zero data leakage.
DIY & Maker: Perfect base for your own open-source, modifiable, standalone positioning tool.
- Fully offline: Works with no GSM, no WiFi, no connection—100% autonomous.
 - Data privacy: Nothing leaves the device. Your waypoints are yours only.
 - Real-time distance & bearing: Instantly see how far and which direction to any of your 16 stored points.
 - GPS-based compass: Get the exact direction and ETA to any waypoint, using a user-defined speed (walk, drive, etc).
 - Manual entry: Type in or delete GPS coordinate directly
 - Readable LCD: 16x2 backlit display, clear in full sunlight or night.
 - Simple interface: 3 button interface and the use of touch combinations to access menus
 
1. Navigate to a Saved Waypoint (Azimuth & Distance)Select any of the 8 memory slots using the intuitive 3-button interface. The device instantly calculates and displays:* Distance (meters/kilometers) to the selected waypoint.* Azimuth (bearing): the precise direction you need to go.All information is shown in real time on the LCD at 1 fps, helping you stay on course—perfect for hiking, field radio, or finding a saved spot.
2. Save Your Current GPS CoordinatesSwitch on the device using the sliding switch (save mode or read mode), press the main button to select the current function, and confirm your action with the validation button—the current GPS coordinate is then saved to memory.Data is stored in non-volatile EEPROM—so your waypoints are safe, even after power-off.
3. Manual Entry of GPS Coordinates (Slot 8)Enter latitude and longitude manually for memory slot 8, using touch combinations on the 3-button interface.Great for pre-loading a destination, a meeting point, or for any scenario where you want to input coordinates ahead of time.
4. Read Live GPS Data: Time, Date, Position, Altitude, SatellitesView real-time GPS information (current latitude/longitude, date, time, altitude, satellites in view) directly on the LCD.Instantly accessible—no phone or extra device needed.
5. Automatic Battery Level Check at StartupOn startup, the device measures and displays the battery voltage.
- Microcontroller: Arduino Uno
 - GPS Receiver: NMEA (Neo-6M, 9600 baud)
 - Display: 16x2 I2C LCD (backlit)
 - User input: 3 buttons (OK, up, down)
 - Permanent storage: Onboard EEPROM for GPS coordinates
 - Precise battery monitoring (ADC with internal Vref)
 - Power: Flexible (battery, powerbank, USB)
 - Single-sided PCB (Gerber files included)
 
All code open-source and well-commented
///***************************************************************************
//                                 LIBRAIRIES
//***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <EEPROM.h>
#include <SoftwareSerial.h>
#include <Wire.h>    // Bibliothque pour l'I2C
#include <VirtualWire.h> // gestion comminucation srie
#include <VirtualWire_Config.h> // gestion com. srie
#include <LiquidCrystal_I2C.h> // librairie pour l'cran
#include <avr/wdt.h>            // library for default watchdog functions
#include <avr/interrupt.h>      // library for interrupts handling
#include <avr/sleep.h>          // library for sleep
#include <avr/power.h>          // library for power control
#include <TinyGPS++.h> // librairie pour le GPS
#define PI 3.14159265
/***************************************************************************
                                 CONSTANTS
***************************************************************************/
static const int RXPin = 2, TXPin = 3;
static const uint32_t GPSBaud = 9600; //Replace with your baud rate
const int SLEEPdelay = 7000; // dlai avant de passer en veille
const int MISEAJOURBOUTONdelay = 4000; // dlai aprs press bouton pour ractualiser GPS
const int MISEAJOURAFFICHAGEdelay = 4000; // dlai aprs press bouton pour ractualiser GPS
const int LECTpin = 11; // pin du bouton MENU
const int HAUTpin = 9; // pin du bouton MENU
const int BASpin = 10; // pin du bouton VALI
const int VALIpin = 8; // pin du bouton BATT
const byte BROCHE_CAPTEUR_VIN = A3; // pin pour la mesure de la tension de la batterie
const int GPS_CYCLE = 25;
const int ATTENTE_CYCLE = 50;
const int AFFICHAGE_CYCLE = 25;
/***************************************************************************
                                 VARIABLES
***************************************************************************/
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
// variables pour le GPS
boolean GPS_DISPO = false;
char lati[10]; //pour affichage
char longi[10]; //pour affichage
// sauvegarde info GPS
double latitude_cible, longitude_cible, latitude, longitude, alti;
float vitesse;
byte heur, minu, seco, mois, jour;
byte nbst = 0;
// variable menu orientation
char variable1[10] = "+000.000000"; //coordonnes LAT et LONG
char variable2[10] = "+000.000000";
char * endPtr;
double latitude_saisi;
double longitude_saisi;
// variable pour corps du programme
long timer = 0; // timer pour le dpart en veille
byte curseur = 0;
int GPS_COMPTEUR = 0;
int AFFICHAGE_COMPTEUR = 0;
int nbr_remaining;
volatile int f_wdt = 1;
char tempsc[5] = "HH:MM";
char temp1[2];
uint8_t PLEIN[8]  = {31, 31, 31, 31, 31, 31, 31, 31};
// variable sauvegard en EEPROM
int temp = EEPROM.read(0);
byte pointeur_lecture = temp >> 8;
byte pointeur_sauvegarde = temp - pointeur_lecture << 8;
byte pointeur_fenetre = 0;
//////////////////////////////////////////////////////////////////
/***************************************************************************
                                 FUNCTIONS
***************************************************************************/
/** Mesure la rfrence interne  1.1 volts */
unsigned int analogReadReference(void) {
  /* Elimine toutes charges rsiduelles */
  ADMUX = 0x4F;
  delayMicroseconds(5);
  /* Slectionne la rfrence interne  1.1 volts comme point de mesure, avec comme limite haute VCC */
  ADMUX = 0x4E;
  delayMicroseconds(200);
  /* Active le convertisseur analogique -> numrique */
  ADCSRA |= (1 << ADEN);
  /* Lance une conversion analogique -> numrique */
  ADCSRA |= (1 << ADSC);
  /* Attend la fin de la conversion */
  while (ADCSRA & (1 << ADSC));
  /* Rcupre le rsultat de la conversion */
  return ADCL | (ADCH << 8);
}
//////////////////////////////////////////////////////////////////
void affichage_tension() {
  lcd.clear();
  lcd.print(F("Tension batt. :"));
  power_adc_enable();
  lcd.setCursor(4, 1);
  unsigned int raw_vin = analogRead(BROCHE_CAPTEUR_VIN);
  unsigned int raw_ref = analogReadReference();
  power_adc_disable();
  float real_vin = 2.2 * raw_vin / raw_ref;
  lcd.print(real_vin, 1);
  lcd.setCursor(9, 1);
  lcd.print(F(" V"));
  delay(1000);
}
//////////////////////////////////////////////////////////////////
void affichage_fenetre_lecture(byte pointeur_lecture, byte pointeur_fenetre) {
  double x;
  double y;
  double distance;
  double azimut;
  double temps;
  byte variable;
  //XXXXXXXXXXXXXXXXXXXXXXXX
  if (pointeur_fenetre == 0) { // calcul cap
    EEPROM.get(2 + 8 * pointeur_lecture, latitude_cible); // sauvegarde latitude
    EEPROM.get(130 + 8 * pointeur_lecture, longitude_cible); // sauvegarde longitude
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX DISTANCE
    x = 111319 * ((longitude_cible - longitude) * cos(PI * (latitude_cible + latitude) / 360));
    y = 111319 * (latitude_cible - latitude);
    distance = sqrt(x * x + y * y);
    // 40075110 m perimetre terre
    // distance = angle * perimetre / 360
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CLACUL AZIMUT
    if (x > 0) {
      azimut = 90 - (180 / PI) * atan(y / x);
    }
    else {
      azimut = 270 + (180 / PI) * atan(y / abs(x));
    }
    lcd.clear();
    lcd.setCursor(0, 0);
    // Memoire en cours
    lcd.print(F("Mem:"));
    lcd.print(pointeur_lecture);
    lcd.setCursor(7, 0);
    // Azimut coord memoire en cours
    lcd.print(F("Azmt:"));
    lcd.print(azimut, 0);
    lcd.write((char)223);
    lcd.setCursor(0, 1);
    lcd.print(F("d:"));
    if (distance > 1000) {
      lcd.print(distance / 1000, 2);
      lcd.print(F("km"));
    }
    else
    {
      lcd.print(distance, 0);
      lcd.print(F(" m"));
    }
    lcd.setCursor(11, 1);
    lcd.print("     ");
    lcd.setCursor(11, 1);
    // affichage heure arriv estime
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CLACUL HEURE D ARRIVE
    temps = distance / (vitesse / 3.6 );
    if (temps > 3600) {
      variable = floor(temps / 3600);
      lcd.print(variable);
      lcd.print(F("h"));
      temps = temps / 3600 - variable;
      temps = temps * 60;
      //variable = (temps - 3600 * variable) / 60;
      if (temps < 10)
        lcd.print("0");
      lcd.print(temps, 0);
    }
    else
    {
      variable = floor(temps / 60);
      lcd.print(variable);
      lcd.print(F(":"));
      variable = floor(temps - 60 * variable);
      if (variable < 10)
        lcd.print("0");
      lcd.print(variable);
    }
  }
  else if (pointeur_fenetre == 1) { // affichage_coordonnees
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(F("LAT: "));
    lcd.print(lati);
    lcd.setCursor(0, 1);
    lcd.print(F("LONGI:"));
    lcd.print(longi);
  }
  else if (pointeur_fenetre == 2) { // affichage date et satellite
    lcd.clear();
    lcd.setCursor(0, 0);
    // affichage heure
    temp = heur;
    if (temp == 24) {
      temp = 0;
    }
    itoa(temp, temp1, 10);
    if (temp < 10) {
      tempsc[1] = temp1[0];
      tempsc[0] = 48;
    }
    else
    {
      tempsc[0] = temp1[0];
      tempsc[1] = temp1[1];
    }
    temp = minu;
    itoa(temp, temp1, 10);
    if (temp < 10) {
      tempsc[4] = temp1[0];
      tempsc[3] = 48;
    }
    else
    {
      tempsc[4] = temp1[1];
      tempsc[3] = temp1[0];
    }
    lcd.print(tempsc);
    // affichage date
    lcd.setCursor(5, 0);
    lcd.print("  ");
    lcd.print(jour);
    lcd.print(F("/"));
    lcd.print(mois);
    // affichage nb. sat et altitude
    lcd.setCursor(0, 1);
    lcd.print(F("Sat:    "));
    lcd.setCursor(4, 1);
    lcd.print(nbst);
    lcd.setCursor(8, 1);
    lcd.print(F("Alt:"));
    lcd.print(alti, 0);
  }
  else if (pointeur_fenetre == 3) { // affichage tension batterie
    lcd.clear();
    lcd.print(F("Tension batt. :"));
    power_adc_enable();
    lcd.setCursor(4, 1);
    unsigned int raw_vin = analogRead(BROCHE_CAPTEUR_VIN);
    unsigned int raw_ref = analogReadReference();
    power_adc_disable();
    float real_vin = 2.2 * raw_vin / raw_ref;
    lcd.print(real_vin, 1);
    lcd.setCursor(9, 1);
    lcd.print(F(" V"));
  }
}
void affichage_fenetre_sauvegarde(byte pointeur_sauvegarde) {
  byte heur_sauv;
  byte minu_sauv;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Mem.:"));
  lcd.print(pointeur_sauvegarde);
  lcd.print(F(" S."));
  // affichage heure
  EEPROM.get(258 + pointeur_sauvegarde, heur_sauv); // sauvegarde longitude
  EEPROM.get(274 + pointeur_sauvegarde, minu_sauv); // sauvegarde longitude
  temp = heur_sauv;
  if (temp == 24) {
    temp = 0;
  }
  itoa(temp, temp1, 10);
  if (temp < 10) {
    tempsc[1] = temp1[0];
    tempsc[0] = 48;
  }
  else
  {
    tempsc[0] = temp1[0];
    tempsc[1] = temp1[1];
  }
  temp = minu_sauv;
  itoa(temp, temp1, 10);
  if (temp < 10) {
    tempsc[4] = temp1[0];
    tempsc[3] = 48;
  }
  else
  {
    tempsc[4] = temp1[1];
    tempsc[3] = temp1[0];
  }
  for (byte i = 0; i < 5; i++)
    lcd.print(tempsc[i]);
  lcd.setCursor(0, 1);
  lcd.print(F("VALID(V)ANNUL(B)"));
}
void affichage_confirmation_sauvegarde(byte pointeur_sauvegarde) {
  lcd.clear();
  lcd.setCursor(0, 0);
  if (pointeur_sauvegarde == 15) {
    saisi_coord();
  }
  else {
    lcd.print(F("Sauv. Mem. ? "));
    lcd.print(pointeur_sauvegarde);
    lcd.setCursor(0, 1);
    lcd.print(F("VALID(V)ANNUL(B)"));
  }
}
void affichage_execution_sauvegarde(byte pointeur_sauvegarde) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Confirm. Sauv. "));
  lcd.setCursor(0, 1);
  lcd.print(F("Mem:"));
  lcd.print(pointeur_sauvegarde);
  lcd.print(" ");
  // affichage heure
  temp = heur;
  if (temp == 24) {
    temp = 0;
  }
  itoa(temp, temp1, 10);
  if (temp < 10) {
    tempsc[1] = temp1[0];
    tempsc[0] = 48;
  }
  else
  {
    tempsc[0] = temp1[0];
    tempsc[1] = temp1[1];
  }
  temp = minu;
  itoa(temp, temp1, 10);
  if (temp < 10) {
    tempsc[4] = temp1[0];
    tempsc[3] = 48;
  }
  else
  {
    tempsc[4] = temp1[1];
    tempsc[3] = temp1[0];
  }
  for (byte i = 0; i < 5; i++)
    lcd.print(tempsc[i]);
}
// allumage du rtroclairage de l'cran
void eteindre_ecran() {
  lcd.noBacklight(); //eteindre le retro-eclairage
  //lcd.noDisplay();   //eteind le cristaux liquide
}
// extinction du rtroclairage de l'cran
void allumer_ecran() {
  lcd.backlight(); // allumer le retro-eclairage
  lcd.display();   //eteind cristaux liquides
}
// prend les coordonnes GPS si dispo
void prendre_coord() {
  double temp;
  long timer_gps = millis();
  while ((millis() - timer_gps) < 500) {
    if (ss.available() > 0) {
      if (gps.encode(ss.read())) {
        if (gps.location.isValid()) {
          GPS_DISPO = true;
          // affichage de la latitude et stockage dans message 1
          latitude = gps.location.lat();
          dtostrf(latitude, 9, 6, lati);
          longitude = gps.location.lng();
          dtostrf(longitude, 9, 6, longi);
          alti = gps.altitude.meters();
          nbst = gps.satellites.value();
          heur = gps.time.hour();
          minu = gps.time.minute();
          seco = gps.time.second();
          mois = gps.date.month();
          jour = gps.date.day();
          heur++; //heure hiver
        }
        else
        {
          GPS_DISPO = false;
        }
      }
    }
  }
}
// interrupt raised by the watchdog firing
// when the watchdog fires during sleep, this function will be executed
// remember that interrupts are disabled in ISR functions
ISR(WDT_vect)
{
  // not hanging, just waiting
  // reset the watchdog
  wdt_reset();
}
// function to configure the watchdog: let it sleep 8 seconds before firing
// when firing, configure it for resuming program execution
void configure_wdt(void)
{
  cli();                           // disable interrupts for changing the registers
  MCUSR = 0;                       // reset status register flags
  // Put timer in interrupt-only mode:
  WDTCSR |= 0b00011000;            // Set WDCE (5th from left) and WDE (4th from left) to enter config mode,
  // using bitwise OR assignment (leaves other bits unchanged).
  WDTCSR =  0b01000000 | 0b000000; // set WDIE: interrupt enabled
  // clr WDE: reset disabled
  // and set delay interval (right side of bar) to 8 seconds
  sei();                           // re-enable interrupts
  // reminder of the definitions for the time before firing
  // delay interval patterns:
  //  16 ms:     0b000000
  //  500 ms:    0b000101
  //  1 second:  0b000110
  //  2 seconds: 0b000111
  //  4 seconds: 0b100000
  //  8 seconds: 0b100001
}
void sleep(int ncycles)
{
  nbr_remaining = ncycles; // defines how many cycles should sleep
  // Set sleep to full power down.  Only external interrupts or
  // the watchdog timer can wake the CPU!
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  // Turn off the ADC while asleep.
  power_adc_disable();
  while (nbr_remaining > 0) { // while some cycles left, sleep!
    // Enable sleep and enter sleep mode.
    sleep_mode();
    // CPU is now asleep and program execution completely halts!
    // Once awake, execution will resume at this point if the
    // watchdog is configured for resume rather than restart
    // When awake, disable sleep mode
    sleep_disable();
    // we have slept one time more
    nbr_remaining = nbr_remaining - 1;
  }
  // put everything on again
  power_all_enable();
}
void reglage_vitesse() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Vitesse (km/h) ?"));
  EEPROM.get(290, vitesse);
  lcd.setCursor(0, 1);
  lcd.print(vitesse);
  while (digitalRead(VALIpin) == 1) {
    if (digitalRead(BASpin) == 0) {
      while (digitalRead(BASpin) == 0) {
        // attendre qu'on relache bouton
      }
      if (vitesse > 0.2) {
        vitesse = vitesse - 0.1;
      }
      lcd.setCursor(0, 1);
      lcd.print(vitesse);
    }
    if (digitalRead(HAUTpin) == 0) {
      while (digitalRead(HAUTpin) == 0) {
        // attendre qu'on relache bouton
      }
      if (vitesse < 1000) {
        vitesse = vitesse + 0.1;
      }
      lcd.setCursor(0, 1);
      lcd.print(vitesse);
    }
  }
  EEPROM.put(290, vitesse);
}
void attendre_GPS() {
  allumer_ecran;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F(" Attente signal"));
  lcd.setCursor(0, 1);
  lcd.print(F("GPS..."));
  GPS_COMPTEUR = 0;
  while (GPS_DISPO == false) {
    prendre_coord();
    GPS_COMPTEUR++;
    if (GPS_COMPTEUR == ATTENTE_CYCLE)
      eteindre_ecran();
  }
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Signal detecte !"));
  for (byte i = 0; i < 4; i++)
  {
    allumer_ecran();
    delay(200);
    eteindre_ecran();
    delay(200);
  }
}
/////////////////////////////////////////
void saisi_coord() {
  byte temp;
  lcd.clear();
  lcd.setCursor(0, 0);
  byte curseur = 0;
  for (int i = 0; i < 10; i++) {
    lcd.setCursor(i, 0);
    lcd.print(variable1[i]);
    lcd.setCursor(i, 1);
    lcd.print(variable2[i]);
  }
  lcd.setCursor(12, 0);
  lcd.print(F("LAT."));
  lcd.setCursor(11, 1);
  lcd.print(F("LONG."));
  lcd.setCursor(0, 0);
  lcd.blink();
  while (digitalRead(VALIpin) == 1) {
    if (digitalRead(BASpin) == 0) {
      while (digitalRead(BASpin) == 0) {
        // attendre qu'on relache bouton
      }
      curseur++;
      if (curseur > 19)
        curseur = 0;
      if ((curseur == 4) | (curseur == 14)) {
        curseur++;
      }
      if (curseur < 10) {
        lcd.setCursor(curseur, 0);
      }
      else {
        lcd.setCursor(curseur - 10, 1);
      }
      delay(200);
    }
    if (digitalRead(HAUTpin) == 0) {
      while (digitalRead(HAUTpin) == 0) {
        // attendre qu'on relache bouton
      }
      if (curseur < 10) {
        if (curseur == 0)
        {
          if (variable1[0] == 43)
          {
            variable1[0] = 45;
          }
          else
          {
            variable1[0] = 43;
          }
        }
        else
        {
          variable1[curseur]++;
          if (variable1[curseur] == 58) {
            variable1[curseur] = 48;
          }
        }
        lcd.print(variable1[curseur]);
        lcd.setCursor(curseur, 0);
      }
      else {
        if (curseur == 10)
        {
          if (variable2[0] == 43)
          {
            variable2[0] = 45;
          }
          else
          {
            variable2[0] = 43;
          }
        }
        else
        {
          variable2[curseur - 10]++;
          if (variable2[curseur - 10] == 58) {
            variable2[curseur - 10] = 48;
          }
        }
        lcd.print(variable2[curseur - 10]);
        lcd.setCursor(curseur - 10, 1);
      }
      delay(200);
    }
  }
  
  latitude_saisi = strtod(variable1, &endPtr);
  longitude_saisi = strtod(variable2, &endPtr);
  EEPROM.put(2 + 8 * (pointeur_sauvegarde - 8), latitude_saisi); // sauvegarde latitude
  EEPROM.put(130 + 8 * (pointeur_sauvegarde - 8), longitude_saisi); // sauvegarde longitude
  EEPROM.put(258 + (pointeur_sauvegarde - 8), heur); // sauvegarde heure
  EEPROM.put(274 + (pointeur_sauvegarde - 8), minu); // sauvegarde minute
  EEPROM.put(290, vitesse);
  lcd.noBlink();
  timer = millis();
}
void effacement_coord() {
  while ((digitalRead(VALIpin) == 0) || (digitalRead(HAUTpin) == 0) || (digitalRead(BASpin) == 0)) {
    //attente bouton lach
  }
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Eff. coord. ?"));
  lcd.setCursor(0, 1);
  lcd.print(F("ANNUL(H)VALID(B)"));
  while ((digitalRead(BASpin) == 1) && (digitalRead(HAUTpin) == 1)) {
    // attente saisi bouton
  }
  if (digitalRead(HAUTpin) == 1)
    return;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Eff. coordonnees"));
  lcd.setCursor(0, 1);
  byte valeuraleatoire;
  byte ind = 0;
  for (byte j = 0; j < 2 ; j++) { // effaage mmoire EEPROM coord
    for (byte i = 0; i < 16 ; i++) { // effaage mmoire EEPROM coord
      valeuraleatoire = rand();
      EEPROM.put(2 + 8 * i, (double)valeuraleatoire); // sauvegarde latitude
      valeuraleatoire = rand();
      EEPROM.put(130 + 8 * i, (double)valeuraleatoire); // sauvegarde longitude
      valeuraleatoire = rand();
      EEPROM.put(258 + i, (byte)valeuraleatoire); // sauvegarde heure
      valeuraleatoire = rand();
      EEPROM.put(274 + i, (byte)valeuraleatoire); // sauvegarde minute
      ind++;
      if ((ind & B1) == 0)
        lcd.write(byte(0));
      //u8g2.drawBox(2, 40, ind, 20);
      //u8g2.sendBuffer();
    }
  }
  for (byte i = 0; i < 16 ; i++) { // effaage mmoire EEPROM coord
    EEPROM.put(2 + 8 * i, (double)45); // sauvegarde latitude
    EEPROM.put(130 + 8 * i, (double)2); // sauvegarde longitude
    EEPROM.put(258 + i, (byte)0); // sauvegarde heure
    EEPROM.put(274 + i, (byte)0); // sauvegarde minute
  }
  EEPROM.put(266, (byte)0); // sauvegarde heure
  EEPROM.put(282, (byte)0); // sauvegarde minute
  lcd.setCursor(4, 1);
  lcd.print(F("Fait..."));
  delay(500);
}
/***************************************************************************
                                 CORPS PROGRAMME
***************************************************************************/
void setup() {
  lcd.createChar(0, PLEIN);
  lcd.begin(16, 2); lcd.clear();// Initialise l'cran
  pinMode(HAUTpin, INPUT_PULLUP); // Initialise la broche du bouton HAUT
  pinMode(BASpin, INPUT_PULLUP); // Initialise la broche de VALIDATIONpinMode(VALIpin, INPUT); // Initialise la broche de VALIDATION
  pinMode(VALIpin, INPUT_PULLUP); // Initialise la broche du menu BATTERIE
  pinMode(LECTpin, INPUT_PULLUP); // Initialise la broche du bouton HAUT
  ss.begin(GPSBaud);
  Serial.begin(9600); // Pour Debug
  // configure the watchdog
  configure_wdt();
  power_adc_disable();
  power_usart0_disable();
  //power_timer1_disable();
  power_timer2_disable();
  // rglage de la vitesse de marche
  vitesse = 3.6;
  EEPROM.put(290, vitesse);
  affichage_tension();
  attendre_GPS();
  eteindre_ecran();
}
/*
  PINS sur arduino UNO :
  13  :  bouton LECTURE
  12  : bouton HAUT
  11 : bouton BAS
  10 : bouton VALIDATION
  3 : TX GPS
  A3 : pin statut batterie
  A4 et A5 port I2C cran (clock sur A5)
*/
void loop() {
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  ////////////// MODE LECTURE////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  if (digitalRead(LECTpin) == 1) {
    while (digitalRead(LECTpin) == 1) { //mode lecture
      // si dlai fini et plus de porteuse, on rentre en veille
      if ((millis() - timer) > SLEEPdelay) {  // pas de porteuse depuis SLEEPdelay ms, on peut commencer cycle endormissement/reveil
        eteindre_ecran();
        pointeur_fenetre = 0;
        while ((digitalRead(VALIpin) == 1) && (digitalRead(HAUTpin) == 1) && (digitalRead(BASpin) == 1) && (digitalRead(LECTpin) == 1)) { // cycle endormissement / reveil tant que porteuse absente et que bouton menu ou bouton batterie non press
          sleep(3); // dors 32 ms
          GPS_COMPTEUR++;
          AFFICHAGE_COMPTEUR++;
          if (GPS_COMPTEUR > GPS_CYCLE) { // tous les gps_cycle, on lit les coordonnes du gps
            prendre_coord();
            GPS_COMPTEUR = 0;
          }
          if (AFFICHAGE_COMPTEUR > AFFICHAGE_CYCLE) {
            affichage_fenetre_lecture(pointeur_lecture, pointeur_fenetre);
            AFFICHAGE_COMPTEUR = 0;
          }
        }
      }
      allumer_ecran();
      // si on appui sur validation
      if (digitalRead(VALIpin) == 0) {
        while (digitalRead(VALIpin) == 0) {
          // attendre qu'on relache bouton
        }
        timer = millis();
        affichage_fenetre_lecture(pointeur_lecture, pointeur_fenetre);
        pointeur_fenetre++;
        pointeur_fenetre = pointeur_fenetre & 0b00000011;
        ///////////////////////////////////////////////////////////////////
      }
      // si bouton haut
      if (digitalRead(HAUTpin) == 0) {
        //                while (digitalRead(HAUTpin) == 0) {
        //                  if (digitalRead(BASpin) == 0) {
        //                    reglage_vitesse();
        //                  }
        //
        //                }
        timer = millis();
        affichage_fenetre_lecture(pointeur_lecture, pointeur_fenetre);
        // ractualisation du pointeur
        pointeur_fenetre = 0;
        pointeur_lecture++;
        pointeur_lecture = pointeur_lecture & 0b00001111;
        affichage_fenetre_lecture(pointeur_lecture, pointeur_fenetre);
        delay(150);
        // affichage fenetre
        ////////////////////////////////////////////////////////////////////
      }
      // si bouton bas
      if (digitalRead(BASpin) == 0) {
        //                while (digitalRead(BASpin) == 0) {
        //                  if (digitalRead(HAUTpin) == 0) {
        //                    reglage_vitesse();
        //                  }
        //
        //        // attendre qu'on relache bouton
        //                }
        timer = millis();
        affichage_fenetre_lecture(pointeur_lecture, pointeur_fenetre);
        pointeur_fenetre = 0;
        pointeur_lecture--;
        pointeur_lecture = pointeur_lecture & 0b00001111;
        affichage_fenetre_lecture(pointeur_lecture, pointeur_fenetre);
        delay(150);
        // affichage fenetre
        ///////////////////////////////////////////////////////////////////
      }
      if (millis() - timer > MISEAJOURBOUTONdelay)
        GPS_COMPTEUR++;
      if (GPS_COMPTEUR > GPS_CYCLE) { // tous les gps_cycle, on lit les coordonnes du gps
        prendre_coord();
        GPS_COMPTEUR = 0;
      }
      temp = pointeur_lecture >> 8 + pointeur_sauvegarde;
      EEPROM.put(0, temp);
    }
    affichage_fenetre_sauvegarde(pointeur_sauvegarde);
  }
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  ////////////// MODE SAUVEGARDE ////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  if (digitalRead(LECTpin) == 0) { //mode sauvegarde
    while (digitalRead(LECTpin) == 0) { //mode sauvegarde
      allumer_ecran();
      // si bouton haut
      if (digitalRead(HAUTpin) == 0) {
        while (digitalRead(HAUTpin) == 0) {
          if (digitalRead(BASpin) == 0) {
            reglage_vitesse();
          }
          if (digitalRead(VALIpin) == 0) {
            effacement_coord();
          }
          // attendre qu'on relache bouton
        }
        timer = millis();
        // ractualisation du pointeur
        pointeur_sauvegarde++;
        pointeur_sauvegarde = pointeur_sauvegarde & 0b00001111;
        affichage_fenetre_sauvegarde(pointeur_sauvegarde);
        // affichage fenetre
        ////////////////////////////////////////////////////////////////////
      }
      // si bouton bas
      if (digitalRead(BASpin) == 0) {
        while (digitalRead(BASpin) == 0) {
          if (digitalRead(HAUTpin) == 0) {
            reglage_vitesse();
          }
          // attendre qu'on relache bouton
        }
        timer = millis();
        pointeur_sauvegarde--;
        pointeur_sauvegarde = pointeur_sauvegarde & 0b00001111;
        affichage_fenetre_sauvegarde(pointeur_sauvegarde);
        delay(50);
        // affichage fenetre
        ///////////////////////////////////////////////////////////////////
      }
      // si on appui sur validation
      if (digitalRead(VALIpin) == 0) {
        while (digitalRead(VALIpin) == 0) {
          // attendre qu'on relache bouton
        }
        // affichage demande confirmation ?
        affichage_confirmation_sauvegarde(pointeur_sauvegarde);
        while ((digitalRead(VALIpin) == 1) && (digitalRead(BASpin) == 1) && (digitalRead(HAUTpin) == 1) && (digitalRead(LECTpin) == 0)) {
        } // attente qu'on appuie sur une touche
        if ((digitalRead(VALIpin) == 0) &&  (digitalRead(LECTpin) == 0)) {
          temp = pointeur_lecture >> 8 + pointeur_sauvegarde;
          EEPROM.put(0, temp);
          if (pointeur_sauvegarde == 15) {
            EEPROM.put(2 + 8 * pointeur_sauvegarde, latitude_saisi); // sauvegarde latitude
            EEPROM.put(130 + 8 * pointeur_sauvegarde, longitude_saisi); // sauvegarde longitude
          }
          else
          {
            EEPROM.put(2 + 8 * pointeur_sauvegarde, latitude); // sauvegarde latitude
            EEPROM.put(130 + 8 * pointeur_sauvegarde, longitude); // sauvegarde longitude
          }
          EEPROM.put(258 + pointeur_sauvegarde, heur); // sauvegarde longitude
          EEPROM.put(274 + pointeur_sauvegarde, minu); // sauvegarde longitude
          EEPROM.put(290, vitesse);
          timer = millis();
          affichage_execution_sauvegarde(pointeur_sauvegarde);
          if (pointeur_sauvegarde == 15) {
            pointeur_sauvegarde = 0;
          }
          while (digitalRead(VALIpin) == 0) {
            // attente
          }
          delay(200);
        }
        ///////////////////////////////////////////////////////////////////
      }
    }
    pointeur_fenetre = 0;
    affichage_fenetre_lecture(pointeur_lecture, pointeur_fenetre);
  }
}


_ztBMuBhMHo.jpg?auto=compress%2Cformat&w=48&h=48&fit=fill&bg=ffffff)





Comments