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);
}
}
Comments