#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>
// LCD Setup
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Pin Definitions
const int encoderCLK = 2;
const int encoderDT = 3;
const int directionButton = 4;
const int startButton = 5;
const int relayPin = 12;
const int pulsePinCW = 6; // Simulated CW pulse input
const int pulsePinCCW = 7; // Simulated CCW pulse input
// Variables
volatile int windCount = 0; // Start at 0 for new wind sessions
volatile int targetWinds = 100;
bool directionCW = true;
bool windingActive = false;
bool paused = false;
bool finished = false;
unsigned long lastDebounceTime = 0;
const int debounceDelay = 50;
volatile bool encoderUpdated = false; // Flag for encoder update
void setup() {
// Serial.begin(9600); // Initialize serial communication
pinMode(encoderCLK, INPUT);
pinMode(encoderDT, INPUT);
pinMode(directionButton, INPUT_PULLUP);
pinMode(startButton, INPUT_PULLUP);
pinMode(relayPin, OUTPUT);
pinMode(pulsePinCW, INPUT_PULLUP);
pinMode(pulsePinCCW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(encoderCLK), updateEncoder, CHANGE);
lcd.init();
lcd.backlight();
displaywelcomeScreen();
displayConfigScreen();
}
void loop() {
if (encoderUpdated) {
encoderUpdated = false;
bool currentCLK = digitalRead(encoderCLK);
bool currentDT = digitalRead(encoderDT);
if (currentCLK == LOW) { // Trigger only on falling edge
if (currentDT == LOW) {
targetWinds = max(0, targetWinds - 1); // Decrement
} else {
targetWinds++; // Increment
}
updateTargetWinds();
}
}
handleDirectionButton();
handleStartButton();
handlePulseButtons();
}
void updateEncoder() {
encoderUpdated = true; // Set flag instead of serial print
}
void handleDirectionButton() {
static bool lastState = HIGH;
static unsigned long pressStartTime = 0;
bool currentState = digitalRead(directionButton);
// Check for button press
if (currentState == LOW && lastState == HIGH) {
pressStartTime = millis(); // Record the start time of the press
}
// Check for button release
if (currentState == HIGH && lastState == LOW) {
unsigned long pressDuration = millis() - pressStartTime;
// If the button is held for more than 500ms, toggle the direction
if (pressDuration >= 500) {
directionCW = !directionCW; // Toggle direction
updateDirection(); // Update direction on the screen
// Update the relay pin based on direction change
if (directionCW) {
digitalWrite(relayPin, LOW); // CW mode: Ensure relay is off
} else {
digitalWrite(relayPin, HIGH); // CCW mode: 5V to A7
}
}
}
lastState = currentState; // Update last state
}
void handleStartButton() {
static bool lastState = HIGH;
static unsigned long pressStartTime = 0;
bool currentState = digitalRead(startButton);
if (currentState == LOW && lastState == HIGH) {
pressStartTime = millis(); // Record the start time of the press
}
if (currentState == HIGH && lastState == LOW) {
unsigned long pressDuration = millis() - pressStartTime;
if (pressDuration >= 500) { // Half-second press for pause/resume
if (!windingActive) {
wipeScreen();
startWinding();
} else if (paused) {
paused = false;
updateDisplay();
} else {
pauseWinding();
}
} else if (windingActive && !paused) { // Short press to pause
pauseWinding();
}
}
lastState = currentState;
}
void handlePulseButtons() {
if (windingActive && !paused) {
if (directionCW) {
if (digitalRead(pulsePinCW) == LOW) {
windCount++;
updateWindCount();
}
if (digitalRead(pulsePinCCW) == LOW) {
windCount = max(0, windCount - 1);
updateWindCount();
}
} else {
if (digitalRead(pulsePinCCW) == LOW) {
windCount++;
updateWindCount();
}
if (digitalRead(pulsePinCW) == LOW) {
windCount = max(0, windCount - 1);
updateWindCount();
}
}
}
// Stop winding if target count is reached
if (windCount >= targetWinds && windingActive) {
windingActive = false;
displayFinishedScreen();
// Set A7 to LOW when winding stops (motor is off)
digitalWrite(relayPin, LOW);
}
}
void startWinding() {
windCount = 0; // Reset current count to 0 when starting
windingActive = true;
finished = false;
paused = false; // Ensure it's not paused when starting
updateDisplay();
// Set relay based on the direction at the time of resuming
if (directionCW) {
digitalWrite(relayPin, LOW); // CW mode: Ensure relay is off
} else {
digitalWrite(relayPin, HIGH); // CCW mode: 5V to A7
}
}
void pauseWinding() {
paused = !paused;
updateDisplay();
}
void updateDisplay() {
lcd.setCursor(0, 0);
lcd.print("Winds: ");
lcd.print(windCount);
lcd.print(" "); // Clear trailing digits
lcd.setCursor(0, 1);
lcd.print("Dir: ");
lcd.print(directionCW ? "CW " : "CCW");
if (windingActive) {
lcd.setCursor(0, 3);
lcd.print(paused ? "Paused " : "Running ");
} else {
lcd.setCursor(0, 3);
lcd.print("Hold Start to begin");
}
}
void updateWindCount() {
lcd.setCursor(7, 0);
lcd.print(windCount);
lcd.print(" "); // Clear trailing digits
}
void updateTargetWinds() {
lcd.setCursor(11, 0);
lcd.print(targetWinds);
lcd.print(" ");
}
void updateDirection() {
lcd.setCursor(5, 1);
lcd.print(directionCW ? "CW " : "CCW");
}
void displayConfigScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set Winds: ");
lcd.print(targetWinds);
lcd.setCursor(0, 1);
lcd.print("Dir: ");
lcd.print(directionCW ? "CW " : "CCW");
lcd.setCursor(0, 3);
lcd.print("Hold Start to begin");
}
void displayFinishedScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Finished!");
lcd.setCursor(0, 2);
lcd.print("Hold Start to return");
finished = true;
while (true) {
if (digitalRead(startButton) == LOW) {
unsigned long pressStartTime = millis();
while (digitalRead(startButton) == LOW) {
if (millis() - pressStartTime > 1000) { // 1-second hold
windCount = 0;
displayConfigScreen();
return;
}
}
}
}
}
void displaywelcomeScreen(){
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("EPIC AMPLIFICATION");
lcd.setCursor(0, 2);
lcd.print("Winderbot 2000");
delay(3000);
}
void wipeScreen() {
lcd.clear();
delay(200);
}