#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 pulsePin = 6; // Single Hall sensor for pulse input
// Variables
volatile int windCount = 0; // Start at 0 for new wind sessions
volatile int targetWinds = 100;
bool initialCW = true; // This will store the initial direction when winding starts
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
volatile bool pulseDetected = false; // Flag for pulse detection
void setup() {
pinMode(encoderCLK, INPUT);
pinMode(encoderDT, INPUT);
pinMode(directionButton, INPUT_PULLUP);
pinMode(startButton, INPUT_PULLUP);
pinMode(relayPin, OUTPUT);
pinMode(pulsePin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(encoderCLK), updateEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(pulsePin), pulseISR, RISING);
lcd.init();
lcd.backlight();
displaywelcomeScreen();
displayConfigScreen();
Serial.begin(9600);
Serial.println("Debugging started...");
}
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();
}
}
if (pulseDetected) {
pulseDetected = false;
Serial.println("Manual handlePulseSensor()");
handlePulseSensor();
}
handleDirectionButton();
handleStartButton();
if (digitalRead(pulsePin) == LOW) { // Check if pulse is triggered
Serial.println("Pulse Detected manually in loop!");
handlePulseSensor();
}
Serial.print("Pulse Pin: ");
Serial.println(digitalRead(pulsePin));
delay(200);
}
void updateEncoder() {
encoderUpdated = true; // Set flag instead of serial print
}
void pulseISR() {
static unsigned long lastInterruptTime = 0;
unsigned long interruptTime = millis();
// Check for debounce
if (interruptTime - lastInterruptTime > debounceDelay) {
pulseDetected = true;
}
lastInterruptTime = interruptTime;
}
void handleDirectionButton() {
static bool lastState = HIGH;
static unsigned long pressStartTime = 0;
bool currentState = digitalRead(directionButton);
if (currentState == LOW && lastState == HIGH) {
pressStartTime = millis();
}
if (currentState == HIGH && lastState == LOW) {
unsigned long pressDuration = millis() - pressStartTime;
if (pressDuration >= 500) {
// Toggle direction
directionCW = !directionCW; // Toggle direction based on long press
updateDirection(); // Update the direction on the display
}
}
lastState = currentState;
}
void handleStartButton() {
static bool lastState = HIGH;
static unsigned long pressStartTime = 0;
bool currentState = digitalRead(startButton);
if (currentState == LOW && lastState == HIGH) {
pressStartTime = millis();
Serial.println("Start button pressed");
}
if (currentState == HIGH && lastState == LOW) {
unsigned long pressDuration = millis() - pressStartTime;
if (pressDuration >= 500) {
Serial.println("Long press detected");
if (!windingActive) {
wipeScreen();
Serial.println("Starting winding...");
startWinding();
} else if (paused) {
Serial.println("Resuming winding...");
paused = false;
updateDisplay();
} else {
Serial.println("Pausing winding...");
pauseWinding();
}
} else if (windingActive && !paused) {
Serial.println("Short press - pausing winding...");
pauseWinding();
}
}
lastState = currentState;
}
void handlePulseSensor() {
if (windingActive && !paused) {
// Check the initial wind direction set at the start
if (initialCW) {
// Started in CW mode: CW increments, CCW decrements
if (directionCW) {
windCount++;
} else {
windCount--;
}
} else {
// Started in CCW mode: CCW increments, CW decrements
if (directionCW) {
windCount--;
} else {
windCount++;
}
}
// Prevent wind count from going negative
windCount = max(0, windCount);
Serial.print("Wind Count: ");
Serial.println(windCount);
updateWindCount();
}
// Stop when target wind count is reached
if (windCount >= targetWinds && windingActive) {
Serial.println("Target winds reached. Stopping...");
windingActive = false;
displayFinishedScreen();
digitalWrite(relayPin, LOW);
}
}
void startWinding() {
if (!windingActive) {
Serial.println("Starting wind...");
windingActive = true;
paused = false;
initialCW = directionCW; // Store the initial winding direction
updateWindScreen(); // Force full screen refresh
updateWindCount(); // Ensure the count updates
}
}
void updateWindScreen() {
lcd.clear(); // Clear screen before redrawing everything
lcd.setCursor(0, 0);
lcd.print("Winds: ");
lcd.print(windCount);
lcd.setCursor(0, 1);
lcd.print("Dir: ");
lcd.print(directionCW ? "CW" : "CCW");
lcd.setCursor(0, 3);
lcd.print(windingActive ? "Running..." : "Paused ");
//lcd.setCursor(0, 3);
//lcd.print("Hold Start to Stop");
}
void pauseWinding() {
paused = !paused;
updateDisplay();
}
void updateDisplay() {
lcd.setCursor(0, 0);
lcd.print("Winds: ");
lcd.print(windCount);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("Dir: ");
lcd.print(directionCW ? "CW " : "CCW");
lcd.setCursor(0, 3);
lcd.print(windingActive ? (paused ? "Paused " : "Running...") : "Hold Start to begin");
}
void updateWindCount() {
lcd.setCursor(7, 0);
lcd.print(windCount);
lcd.print(" ");
}
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) {
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);
}