Created
May 4, 2018 07:33
-
-
Save Dan-Q/db7dae18e3b61f45d8526f36dcd6f49f to your computer and use it in GitHub Desktop.
GC591VV "You Can't Do It Alone!" geocache source code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is the source code the the Arduinos powering my GC591VV "You Can't Do It Alone!" cache: | |
further details can be found at https://danq.me/2014/08/13/gc591vv/ | |
synchronise_clocks.ino - this program sets the clock on the device to the date and time of | |
compilation: run it at the same time on both boxes to synchronise them | |
it_takes_two_cache.ino - this is the program that runs on both boxes when they're to be | |
deployed to the field; some constants need setting: | |
* SALT - needs to be set to a random number (the same for both boxes); this helps to prevent | |
cryptanalysis of the output given only one box | |
* SECOND_UNIT - needs to be set to true on the one box, false on the other | |
* TARGET_NORTH, TARGET_WEST - the Northings and Westings parts of the GZ of the actual cache | |
container, expressed as a long decimal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <LiquidCrystal.h> | |
#include <Wire.h> | |
#include <RTClib.h> | |
// initialize the library with the numbers of the interface pins | |
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); | |
// initialize the real-time clock (DS1307 chip) | |
RTC_DS1307 RTC; | |
const int LIFESPAN = 900; // How many seconds does each code-cycle last. Default 900 (15 minutes). | |
const int EPOCH = 104; // Number of days before code-cycle completes and starts over. Default 104. | |
const long SALT = 17628435; // To avoid trivial cryptanalysis, a secret salt is added to the random seed. | |
const boolean SECOND_UNIT = false; // Is this device the second of the two units? "false" for unit A, "true" for unit B. | |
const unsigned long TARGET_NORTH = 5112123L; // 51° 12.123' | |
const unsigned long RNG_NORTH_MIN = 1000000L; | |
const unsigned long TARGET_WEST = 112123L; // 001° 12.123' | |
const unsigned long RNG_WEST_MIN = 100000L; | |
void setup() { | |
Wire.begin(); | |
RTC.begin(); | |
// set up the LCD's number of columns and rows: | |
lcd.begin(16, 2); | |
} | |
/* Given the current DateTime, returns the number of the current code-cycle: | |
* i.e. a number between 0 and 9983 (changing every 15 minutes throughout a | |
* 104-day cycle) [assuming default constant values]. | |
*/ | |
int code_cycle_number(DateTime now){ | |
int day_count = now.unixtime() / 86400L; | |
// calculate code number | |
int code_number = ((day_count % EPOCH) * (24 * (3600 / LIFESPAN))) + | |
(now.hour() * (3600 / LIFESPAN)) + | |
(now.minute() / (LIFESPAN / 60)); | |
return code_number; | |
} | |
/* Given the current DateTime, returns the number of whole seconds remaining | |
* in the current code-cycle: i.e. a number between 900 and 1 [assuming | |
* default constant values]. | |
*/ | |
int seconds_left_this_cycle(DateTime now){ | |
int secs_left = LIFESPAN; | |
secs_left -= (now.minute() % 15) * 60; | |
secs_left -= now.second(); | |
return secs_left; | |
} | |
/* Given a random seed (typically based on the current date and time) and a | |
* boolean - "true" if this is the "unit B" (the second of the two paired | |
* devices), "false" otherwise - returns a formatted string suitable for | |
* outputting to a single 16-character LCD screen layer (7 digits, one space, | |
* 8 digits [because longitude of the same precision potentially has one more | |
* digit]). | |
* Note that to avoid having to think about pointers, the THIRD parameter is | |
* the character array (string buffer) to be populated with the string, rather | |
* than this function truly returning a value. | |
*/ | |
void partial_coordinates(int seed, boolean second_unit, char buf[]){ | |
randomSeed(seed); | |
unsigned long rOffsetNorth = random(TARGET_NORTH - RNG_NORTH_MIN); | |
unsigned long rOffsetWest = random(TARGET_WEST - RNG_WEST_MIN); | |
unsigned long rNorth = rOffsetNorth + RNG_NORTH_MIN; | |
unsigned long rWest = rOffsetWest + RNG_WEST_MIN; | |
unsigned long rAlternateNorth = TARGET_NORTH - rNorth; | |
unsigned long rAlternateWest = TARGET_WEST - rWest; | |
if(second_unit){ // if we're the second unit, show the alternate coords | |
sprintf(buf, "%07lu %08lu", rAlternateNorth, rAlternateWest); | |
} else { // we're the first unit, show the regular coords | |
sprintf(buf, "%07lu %08lu", rNorth, rWest); | |
} | |
} | |
void loop() { | |
DateTime now = RTC.now(); | |
int code_cycle = code_cycle_number(now); | |
int secs_left = seconds_left_this_cycle(now); | |
char line1[16], line2[16]; | |
// print the cycle number and the number of seconds left this cycle | |
sprintf(line1, "Code %04d (%3ds)", code_cycle, secs_left); | |
lcd.setCursor(0, 0); | |
lcd.print(line1); | |
// print the partial coordinates | |
partial_coordinates(SALT + code_cycle, SECOND_UNIT, line2); | |
lcd.setCursor(0, 1); | |
lcd.print(line2); | |
// DEBUG: print the current datetime | |
//sprintf(line2, "%04d%02d%02d %02d%02d%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second()); | |
//lcd.setCursor(0, 1); | |
//lcd.print(line2); | |
delay(1000); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <LiquidCrystal.h> | |
#include <Wire.h> | |
#include <RTClib.h> | |
// initialize the library with the numbers of the interface pins | |
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); | |
// initialize the real-time clock (DS1307 chip) | |
RTC_DS1307 RTC; | |
void setup() { | |
Wire.begin(); | |
RTC.begin(); | |
Serial.begin(9600); | |
// set up the LCD's number of columns and rows: | |
lcd.begin(16, 2); | |
// set the DS1307 system clock to the date and time of compilation | |
RTC.adjust(DateTime(__DATE__, __TIME__)); | |
lcd.setCursor(0, 0); | |
lcd.print(__DATE__); | |
lcd.setCursor(0, 1); | |
lcd.print(__TIME__); | |
} | |
void loop() { | |
delay(1000); | |
lcd.setCursor(0, 1); | |
Serial.println(RTC.now().unixtime()); | |
lcd.print(RTC.now().unixtime()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment