Bertrand Selva
Published © CC BY-NC

Minimalist Standalone GPS for Hiking, Field Work, Radio...

Offline GPS tool: track, save, and find waypoints with distance & bearing—no network, no cloud, your data, your rules.

BeginnerFull instructions provided6 hours323
Minimalist Standalone GPS for Hiking, Field Work, Radio...

Things used in this project

Story

Read more

Custom parts and enclosures

bouton_boitier_rev2_ky865N1SSj.AMF

fond_9iMLXjd0jg.AMF

boitier_fond_rev8_UM1YVa9d1M.AMF

ecran_boitier_choHhxqaq6.AMF

gerber_ehLtoXlghm.zip

Schematics

gps_fallout_TSdunDYu8u.png

Code

main arduino c code

C/C++
///***************************************************************************
//                                 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);
  }
}

Credits

Bertrand Selva
2 projects • 4 followers
I build low-power embedded systems with smart sensors and edge AI. I work on real-time firmware, data collection, and embedded deep learning

Comments