I have been trying to make this reverse geo cache with multiple locations and messages that displayed. But I am struggling all of this is pretty new for me. I think I am having problems getting the gps to connect I am using a neo 6 and an Arduino uno r4 wifi. I hope everything attaches correctly. Right now I get the longitude and latitude and the numbers change and do not stay consistent. I have gone outside with the same result.
#include <TinyGPS++.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <ArduinoBLE.h>
#include <SoftwareSerial.h>
// GPS setup
#define GPS_BAUD 9600 // Set the GPS baud rate to 9600
// Create a SoftwareSerial object for GPS
SoftwareSerial gpsSerial(2, 3); // RX, TX for GPS (use pins 2 and 3)
TinyGPSPlus gps; // Create an instance of the GPS
// Initialize the LiquidCrystal library with the pins connected to the LCD
LiquidCrystal lcd(12, 11, 5, 4, 6, 7); // RS, E, D4, D5, D6, D7
const int servoPin = 9; // Pin for the servo
bool unlocked = false;
int foundLocations = 0; // Counter for found locations
// Define maximum number of locations
const int maxLocations = 3;
double locations[maxLocations][2] = {
{38.309705, -104.623113}, // Location 1
{38.320914, -104.616595}, // Location 2
{38.135981, -105.473027} // Location 3
};
// Location-specific messages
const char* locationMessages[maxLocations] = {
"Where we first met.",
"Where we would talk late at night",
"The city near an adventure hike to the clouds."
};
// Arrival messages for each location
const char* arrivalMessages[maxLocations] = {
"We miss you here!",
"Go have your favorite drink of the night.",
"Beautiful, just one more puzzle."
};
// EEPROM addresses for storage
const int latStartAddr = 0;
const int lngStartAddr = latStartAddr + (maxLocations * sizeof(double));
unsigned long gpsUpdateTime = 0; // Time for GPS update
void setup() {
pinMode(servoPin, OUTPUT); // Set the servo pin as output
lcd.begin(16, 2); // Initialize the LCD with 16 columns and 2 rows
Serial.begin(9600); // Start the hardware serial for debugging
gpsSerial.begin(GPS_BAUD); // Start the GPS serial
// Display welcome message
lcd.print("Brittany,");
lcd.setCursor(0, 1);
lcd.print("welcome to your");
delay(2000);
lcd.setCursor(0, 1);
lcd.print("treasure box");
delay(2000);
lcd.clear();
// Load locations from EEPROM
loadLocations();
}
void loop() {
// Read GPS data
while (gpsSerial.available()) {
gps.encode(gpsSerial.read());
}
// Check if the GPS location is valid
if (gps.location.isUpdated() && gps.location.isValid()) {
// Get latitude and longitude
double latitude = gps.location.lat();
double longitude = gps.location.lng();
// Print to Serial Monitor
Serial.print("GPS Signal Acquired:\n");
Serial.print("Latitude: ");
Serial.print(latitude, 6);
Serial.print(" Longitude: ");
Serial.println(longitude, 6);
// Display on LCD
lcd.clear(); // Clear the LCD
lcd.setCursor(0, 0); // Set cursor to the first line
lcd.print("Lat: ");
lcd.print(latitude, 6); // Print latitude
lcd.setCursor(0, 1); // Move to the second line
lcd.print("Lng: ");
lcd.print(longitude, 6); // Print longitude
// Calculate distances to each location
for (int i = 0; i < maxLocations; i++) {
double distanceMeters = gps.distanceBetween(latitude, longitude, locations[i][0], locations[i][1]);
double distanceFeet = distanceMeters * 3.28084; // Convert meters to feet
Serial.print("Distance to location ");
Serial.print(i + 1); // Display location number
Serial.print(": ");
Serial.print(distanceFeet);
Serial.println(" ft");
// Check if within 500 feet
if (distanceFeet < 500) { // If within 500 feet
foundLocations++;
lcd.clear();
lcd.print("Clue: ");
lcd.print(locationMessages[i]); // Show the clue for the location
delay(5000); // Show clue for 5 seconds
break; // Exit the loop after processing one location
}
}
// Check if all locations have been found
if (foundLocations >= maxLocations && !unlocked) {
unlockBox();
}
} else {
// If GPS signal is not available or invalid
Serial.println("No GPS Signal or Invalid Location");
lcd.clear();
lcd.print("No GPS Signal");
lcd.setCursor(0, 1);
lcd.print("Go Outside!");
}
delay(1000); // Wait for a second before the next loop iteration
}
void unlockBox() {
if (!unlocked) {
// Manually control the servo to unlock (90 degrees)
for (int pos = 0; pos <= 90; pos++) { // Sweep from 0 to 90 degrees
analogWrite(servoPin, map(pos, 0, 180, 0, 255)); // Map position to PWM value
delay(15); // Wait for the servo to reach the position
}
lcd.clear();
lcd.print("Box Unlocked!");
delay(2000);
unlocked = true; // Set unlocked state
}
}
void lockBox() {
if (unlocked) {
// Manually control the servo to lock (0 degrees)
for (int pos = 90; pos >= 0; pos--) { // Sweep from 90 to 0 degrees
analogWrite(servoPin, map(pos, 0, 180, 0, 255)); // Map position to PWM value
delay(15); // Wait for the servo to reach the position
}
lcd.clear();
lcd.print("Box Locked!");
delay(2000);
unlocked = false; // Set locked state
}
}
void loadLocations() {
for (int i = 0; i < maxLocations; i++) {
EEPROM.get(latStartAddr + i * sizeof(double), locations[i][0]);
EEPROM.get(lngStartAddr + i * sizeof(double), locations[i][1]);
}
}
void saveCurrentLocation(double latitude, double longitude) {
if (foundLocations < maxLocations) {
EEPROM.put(latStartAddr + foundLocations * sizeof(double), latitude);
EEPROM.put(lngStartAddr + foundLocations * sizeof(double), longitude);
}
}