#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int reedPin = 6, selectPin = 7, buzzerPin = 8;
long revolutionCount = 0;
const float lengthPerPress = 0.5;
bool buttonPressed = false, lengthSet = false, beeped = false;
unsigned long lastButtonPressTime = 0, buttonPressDuration = 0;
const unsigned long debounceDelay = 100, longPressDuration = 1000;
enum LengthOption { LENGTH_50, LENGTH_75, FREE_MODE } selectedLength = LENGTH_50;
const int animationDelay = 200;
int animationPosition = 0;
void setup() {
lcd.init();
lcd.backlight();
lcd.print("Select Length:");
pinMode(reedPin, INPUT_PULLUP);
pinMode(selectPin, INPUT_PULLUP);
pinMode(buzzerPin, OUTPUT);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
void beep(int times, int duration = 200) {
for (int i = 0; i < times; i++) {
tone(buzzerPin, 1000, duration);
delay(duration);
}
}
void loop() {
unsigned long currentTime = millis();
int buttonState = digitalRead(reedPin), selectState = digitalRead(selectPin);
if (!lengthSet) {
if (selectState == LOW && !buttonPressed && (currentTime - lastButtonPressTime > debounceDelay)) {
buttonPressed = true;
lastButtonPressTime = currentTime;
buttonPressDuration = currentTime;
} else if (selectState == HIGH && buttonPressed) {
buttonPressed = false;
if ((currentTime - buttonPressDuration) >= longPressDuration) {
lengthSet = true;
lcd.clear();
lcd.print("Set: ");
displaySelectedLength();
beep(2);
lcd.clear();
revolutionCount = 0;
beeped = false;
} else {
beep(1);
cycleLengthOption();
}
}
} else {
if (selectState == LOW && !buttonPressed && (currentTime - lastButtonPressTime > debounceDelay)) {
buttonPressed = true;
lastButtonPressTime = currentTime;
} else if (selectState == HIGH && buttonPressed) {
buttonPressed = false;
beep(1);
lengthSet = false;
lcd.clear();
lcd.print("Select Length:");
}
static bool reedSwitchClosed = false;
static unsigned long reedSwitchLastOpenTime = 0;
if (buttonState == LOW && !reedSwitchClosed) {
reedSwitchClosed = true;
revolutionCount++;
float length_ft = revolutionCount * lengthPerPress;
lcd.setCursor(0, 1);
lcd.print("Length: ");
lcd.print(length_ft);
lcd.print(" ft");
if ((selectedLength == LENGTH_50 && length_ft >= 50) || (selectedLength == LENGTH_75 && length_ft >= 75)) {
if (!beeped) {
beep(3, 1000);
beeped = true;
}
} else if (selectedLength == FREE_MODE && length_ft >= 10 && (int(length_ft) % 10 == 0)) {
beep(1, 200);
}
} else if (buttonState == HIGH && reedSwitchClosed) {
reedSwitchClosed = false;
reedSwitchLastOpenTime = currentTime;
}
if (!reedSwitchClosed && (currentTime - reedSwitchLastOpenTime) < debounceDelay) {
buttonPressed = false;
}
if (currentTime - lastButtonPressTime >= animationDelay) {
lastButtonPressTime = currentTime;
updateAnimation();
}
}
delay(10);
}
void cycleLengthOption() {
lcd.setCursor(0, 1);
lcd.print(" ");
selectedLength = (LengthOption)((selectedLength + 1) % 3);
lcd.setCursor(0, 1);
displaySelectedLength();
}
void displaySelectedLength() {
lcd.print(selectedLength == LENGTH_50 ? "50 ft" : selectedLength == LENGTH_75 ? "75 ft" : "Free Mode");
}
void updateAnimation() {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
for (int i = 0; i < 16; i++) {
lcd.print((i + animationPosition) % 8 < 3 ? '<' : '-');
}
animationPosition = (animationPosition + 1) % 8;
}