GeoFence Treasure Hunt With Artemis Global Tracker

Pages
Contributors: [redacted]
Favorited Favorite 6

The Code

Here, we have the main loop function which combines the logic above with functions that interact with the AGT hardware.

// MAIN LOOP FUNCTION
void loop() {

 if (WIN) {

   Serial.println(F("YOU FOUND THE TREASURE!!"));
   signalVictory();
   while (true) {
     delay(2000);
     Serial.println(F("YOU FOUND THE TREASURE!!"));
   }

 } else {
   geofenceState currentGeofenceState; // Create storage for the geofence state
   boolean result = myGNSS.getGeofenceState(currentGeofenceState);
   Serial.print(F("getGeofenceState returned: ")); // Print the combined state
   Serial.print(result); // Get the geofence state

   if (!result) // If getGeofenceState did not return true
   {
     Serial.println(F(".")); // Tidy up
     return; // and go round the loop again
   }

   // Print the Geofencing status
   // 0 - Geofencing not available or not reliable; 1 - Geofencing active
   Serial.print(F(". status is: "));
   Serial.print(currentGeofenceState.status);

   // Print the numFences
   Serial.print(F(". numFences is: "));
   Serial.print(currentGeofenceState.numFences);

   // Print the state of the geofence
   // 0 - Unknown; 1 - Inside; 2 - Outside
   Serial.print(F(". The geofence stats is: "));
   Serial.print(currentGeofenceState.states[0]);

   byte fenceStatus = digitalRead(geofencePin); // Read the geofence pin
   digitalWrite(LED, !fenceStatus); // Set the LED (inverted)
   Serial.print(F(". Geofence pin (PIO14) is: ")); // Print the pin state
   Serial.print(fenceStatus);
   Serial.println(F("."));


   // GET CURRENT POSITION
   curr_lat = myGNSS.getLatitude(); // Get the latitude in degrees * 10^-7
   curr_long = myGNSS.getLongitude(); // Get the longitude in degrees * 10^-7
   curr_angle = (getCoordinateBearing(latitude, longitude, curr_lat, curr_long) + 180) % 360;
   curr_distance = getCoordinateDistance(latitude, longitude, curr_lat, curr_long);

   Serial.print(F("Current Latitude: "));
   Serial.print(curr_lat);
   Serial.print(F(". Current Longitude: "));
   Serial.println(curr_long);

   Serial.print(F("Goal Angle: "));
   Serial.print(goal_angle);
   Serial.print(F(". Goal Distance: "));
   Serial.println(goal_distance);

   Serial.print(F("Current Angle: "));
   Serial.print(curr_angle);
   Serial.print(F(". Current Distance: "));
   Serial.println(curr_distance);

   score = sqrt(curr_distance * curr_distance + goal_distance * goal_distance - 2 * goal_distance * curr_distance * cos((curr_angle * (2*PI/360)) - (goal_angle * (2*PI/360))));
   Serial.print(F("Current Score: "));
   Serial.print(score);

   if (score < 2) {
     WIN = true;
   } if (score < 5) {
     Serial.println(F(": HOT!!"));
   } else if (score < 12) {
     Serial.println(F(": Warmerrr..."));
   } else if (score < 20) {
     Serial.println(F(": Room Temp"));
   } else {
     Serial.println(F(": Ice Cold..."));
   }
   Serial.println();

 }

 digitalWrite(LED, LOW);
 delay(score*5);
 digitalWrite(LED, HIGH);
 delay(score*5);
}

Once the player finds the treasure, the victory function runs, which connects the AGT to the Iridium network and sends a victory message.

void signalVictory() {
  int signalQuality = -1;
  int err;

  pinMode(LED, OUTPUT); // Make the LED pin an output

  gnssOFF(); // Disable power for the GNSS
  pinMode(gnssBckpBatChgEN, INPUT); // GNSS backup batttery charge control
  pinMode(geofencePin, INPUT); // Configure the geofence pin as an input
  pinMode(iridiumPwrEN, OUTPUT); // Configure the Iridium Power Pin
  digitalWrite(iridiumPwrEN, LOW); // Disable Iridium Power
  pinMode(superCapChgEN, OUTPUT); // Configure the super capacitor charger enable pin
  digitalWrite(superCapChgEN, LOW); // Disable the super capacitor charger
  pinMode(iridiumSleep, OUTPUT); // Iridium 9603N On/Off (Sleep) pin
  digitalWrite(iridiumSleep, LOW); // Put the Iridium 9603N to sleep
  pinMode(iridiumRI, INPUT); // Configure the Iridium Ring Indicator as an input
  pinMode(iridiumNA, INPUT); // Configure the Iridium Network Available as an input
  pinMode(superCapPGOOD, INPUT); // Configure the super capacitor charger PGOOD input

  modem.endSerialPort();

  // Enable the supercapacitor
  Serial.println(F("Enabling the supercapacitor charger..."));
  digitalWrite(superCapChgEN, HIGH);
  delay(1000);
  // wait for the capacitor to charge
  while (digitalRead(superCapPGOOD) == false)
  {
    Serial.println(F("Waiting for supercapacitors to charge..."));
    delay(1000);
  }
  Serial.println(F("Supercapacitors charged!"));

  // Enable power for the 9603N (Iridium Connection)
  Serial.println(F("Enabling 9603N power..."));
  digitalWrite(iridiumPwrEN, HIGH); // Enable Iridium Power
  delay(1000);
  modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE);

  // Startup the modem
  Serial.println(F("Starting modem..."));
  err = modem.begin();
  if (err != ISBD_SUCCESS)
  {
    Serial.print(F("Begin failed: error "));
    Serial.println(err);
    if (err == ISBD_NO_MODEM_DETECTED)
    Serial.println(F("No modem detected: check wiring."));
    return;
  }

  // Test the signal quality.
  err = modem.getSignalQuality(signalQuality);
  if (err != ISBD_SUCCESS)
  {
    Serial.print(F("SignalQuality failed: error "));
    Serial.println(err);
    return;
  }
  modem.useMSSTMWorkaround(false);

  Serial.print(F("On a scale of 0 to 5, signal quality is currently "));
  Serial.print(signalQuality);
  Serial.println(F("."));

  // Send the message
  Serial.println(F("Trying to send the message.  This might take several minutes."));
  err = modem.sendSBDText("YOU FOUND THE TREASURE!!");
  if (err != ISBD_SUCCESS)
  {
    Serial.print(F("sendSBDText failed: error "));
    Serial.println(err);
    if (err == ISBD_SENDRECEIVE_TIMEOUT)
    Serial.println(F("Try again with a better view of the sky."));
  }

  // POWER DOWN IRIDIUM CONNECTION

  // Clear the Mobile Originated message buffer
  Serial.println(F("Clearing the MO buffer."));
  err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear MO buffer
  if (err != ISBD_SUCCESS)
  {
    Serial.print(F("clearBuffers failed: error "));
    Serial.println(err);
  }

  // Power down the modem
  Serial.println(F("Putting the 9603N to sleep."));
  err = modem.sleep();
  if (err != ISBD_SUCCESS)
  {
    Serial.print(F("sleep failed: error "));
    Serial.println(err);
  }

  Serial.println(F("Disabling 9603N power..."));
  digitalWrite(iridiumPwrEN, LOW); // Disable Iridium Power

  Serial.println(F("Disabling the supercapacitor charger..."));
  digitalWrite(superCapChgEN, LOW); // Disable the super capacitor charger

  Serial.println(F("Game Complete!"));
}