#include <TinyGPSPlus.h>
#include <U8g2lib.h>
#define GPS_BAUD 9600
#define ROTARY_PIN_A 33
#define ROTARY_PIN_B 32
#define ROTARY_PIN_BTN 34
#define BUZZER_PIN 9
#define BUZZER_PWM_CHANNEL 0
#define BUZZER_PWM_FREQUENCY 1000
#define BUZZER_PWM_RESOLUTION 8
#define MAX_DISTANCE_FT 2000 // maximum allowable distance
TinyGPSPlus gps;
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/ 22, /*data=*/ 21, /*reset=*/ U8X8_PIN_NONE);
// ClickEncoder encoder(ROTARY_PIN_A, ROTARY_PIN_B, ROTARY_PIN_BTN);
double anchor_lat, anchor_lng;
bool is_armed = false;
uint16_t alarm_range = 0; // in feet
void setup() {
Serial.begin(9600);
u8g2.begin();
u8g2.setFont(u8g2_font_ncenB08_tr);
// encoder.setAccelerationEnabled(true);
// buzzer stuff
ledcSetup(BUZZER_PWM_CHANNEL, BUZZER_PWM_FREQUENCY, BUZZER_PWM_RESOLUTION);
ledcAttachPin(BUZZER_PIN, BUZZER_PWM_CHANNEL);
}
void loop() {
while (Serial.available() > 0) {
if (gps.encode(Serial.read())) {
if (!gps.location.isValid()) {
u8g2.clearBuffer();
u8g2.drawStr(0, 10, "GPS Lock: No");
} else {
// if (encoder.getButton() == ClickEncoder::Clicked) {
// if (is_armed) {
// is_armed = false;
// } else {
// is_armed = true;
// anchor_lat = gps.location.lat();
// anchor_lng = gps.location.lng();
// }
// }
// setRange();
displayGPS();
checkDistance();
}
} else {
u8g2.clearBuffer();
u8g2.drawStr(0, 10, "GPS Error");
}
}
}
// void setRange() {
// int16_t encoder_value = encoder.getValue();
// if (encoder_value != 0) {
// // Update the alarm range
// alarm_range += encoder_value;
// if (alarm_range > MAX_DISTANCE_FT) {
// alarm_range = MAX_DISTANCE_FT;
// } else if (alarm_range < 0) {
// alarm_range = 0;
// }
// }
// }
void displayGPS() {
u8g2.clearBuffer();
u8g2.drawStr(0, 10, "GPS Lock: Yes");
u8g2.drawStr(0, 20, ("Max Range: " + String(alarm_range) + "ft").c_str());
u8g2.drawStr(0, 30, String("Alarm: " + String(is_armed ? "Armed" : "Disarmed")).c_str());
if (is_armed) {
double current_distance = TinyGPSPlus::distanceBetween(gps.location.lat(), gps.location.lng(), anchor_lat, anchor_lng);
current_distance *= 3.281; // convert to feet
u8g2.drawStr(0, 40, ("Distance: " + String(current_distance, 2) + "ft").c_str());
}
u8g2.sendBuffer();
}
void checkDistance() {
if (is_armed) {
double current_distance = TinyGPSPlus::distanceBetween(gps.location.lat(), gps.location.lng(), anchor_lat, anchor_lng);
current_distance *= 3.281; // convert to feet
if (current_distance > alarm_range) {
alarm(true);
} else {
alarm(false);
}
} else {
alarm(false);
}
}
void alarm(bool isOn){
ledcWrite(BUZZER_PWM_CHANNEL, isOn ? 127 : 0); // 1.65 V
}