#include <EEPROM.h>
// Define pin numbers for buttons and limit switches
#define BUTTON_AUTO 2
#define BUTTON_STOP 3
#define LIMIT_FORWARD 4
#define LIMIT_REVERSE 5
#define IR_SENSOR_PIN 9 // Pin for the IR sensor
// Define pin numbers for motor control
#define MOTOR_BREAK 6
#define MOTOR_ENABLE 7
#define MOTOR_REVERSE 8
// Define variables to store motor state and timing
bool autoMode = false; // To track if auto mode is active
bool motorRunning = false; // To track if the motor is running
bool motorForward = true; // To track motor direction (true = forward)
bool forwardLimitReached = false;
bool reverseLimitReached = false;
bool obstacleDetected = false; // To track obstacle detection
// Cycle counting and timing variables
unsigned int openCloseCount = 0; // Count of total open-close cycles
unsigned long startTime = 0; // Time when motor started moving
unsigned long cycleDuration = 0; // Time taken for a full open-close cycle
// EEPROM addresses for storing cycle count and time
const int eepromCycleCountAddr = 0;
const int eepromTimeAddr = sizeof(unsigned int); // After cycle count
// Function to reset invalid EEPROM values
void resetEEPROMValues() {
if (openCloseCount == 255 || openCloseCount > 10000) { // Check if cycle count is uninitialized or invalid
openCloseCount = 0; // Reset to 0 if uninitialized or invalid
}
if (cycleDuration == 0xFFFFFFFF || cycleDuration > 1000000000L) { // Check if duration is invalid
cycleDuration = 0; // Reset to 0 if uninitialized or invalid
}
}
void setup() {
// Set button and limit switch pins as inputs with pull-up resistors
pinMode(BUTTON_AUTO, INPUT_PULLUP);
pinMode(BUTTON_STOP, INPUT_PULLUP);
pinMode(LIMIT_FORWARD, INPUT_PULLUP);
pinMode(LIMIT_REVERSE, INPUT_PULLUP);
pinMode(IR_SENSOR_PIN, INPUT_PULLUP); // IR sensor pin as input with pull-up
// Set motor control pins as outputs
pinMode(MOTOR_BREAK, OUTPUT);
pinMode(MOTOR_ENABLE, OUTPUT);
pinMode(MOTOR_REVERSE, OUTPUT);
// Initialize motor control (brake engaged, motor off)
stopMotor(); // Ensures all control pins are in default states
// Initialize serial communication for displaying info
Serial.begin(9600);
// Retrieve saved data from EEPROM
EEPROM.get(eepromCycleCountAddr, openCloseCount);
EEPROM.get(eepromTimeAddr, cycleDuration);
// Reset invalid EEPROM values
resetEEPROMValues();
// Print initialization data
Serial.println("System Initialized");
Serial.print("Cycle Count: ");
Serial.println(openCloseCount);
Serial.print("Last Cycle Duration (s): ");
Serial.println(cycleDuration / 1000); // Display seconds
}
void loop() {
// Read button states
bool autoButtonPressed = digitalRead(BUTTON_AUTO) == LOW;
bool stopButtonPressed = digitalRead(BUTTON_STOP) == LOW;
// Read limit switch states
bool forwardLimitPressed = digitalRead(LIMIT_FORWARD) == LOW;
bool reverseLimitPressed = digitalRead(LIMIT_REVERSE) == LOW;
// Read IR sensor state
obstacleDetected = digitalRead(IR_SENSOR_PIN) == LOW; // Obstacle detected if IR sensor reads LOW
// Handle Auto Button Press (momentary)
if (autoButtonPressed) {
autoMode = !autoMode; // Toggle auto mode on button press
motorRunning = autoMode;
if (motorRunning) {
startTime = millis(); // Start timing the cycle
startMotorForward(); // Start motor in forward direction
} else {
stopMotor(); // Stop motor if auto mode is turned off
}
delay(200); // Debounce delay
}
// Handle Stop Button Press (momentary)
if (stopButtonPressed) {
autoMode = false; // Disable auto mode
motorRunning = false;
stopMotor(); // Stop the motor
delay(200); // Debounce delay
}
// Obstacle detection logic
if (obstacleDetected) {
// If obstacle is detected, stop the motor immediately
stopMotor();
Serial.println("Obstacle detected! Motor stopped.");
}
// Auto Mode Logic (if auto mode is active)
if (autoMode && motorRunning && !obstacleDetected) {
if (motorForward) {
// Move forward until Forward Limit is hit
if (forwardLimitPressed && !forwardLimitReached) {
forwardLimitReached = true; // Mark that forward limit is hit
motorForward = false; // Switch to reverse direction
startMotorReverse(); // Reverse the motor
} else if (!forwardLimitPressed) {
forwardLimitReached = false; // Reset if limit is released
}
} else {
// Move reverse until Reverse Limit is hit
if (reverseLimitPressed && !reverseLimitReached) {
reverseLimitReached = true; // Mark that reverse limit is hit
motorForward = true; // Switch to forward direction
startMotorForward(); // Forward the motor
// Complete cycle (forward + reverse = 1 open-close cycle)
cycleDuration = millis() - startTime; // Calculate time taken
openCloseCount++;
// Save the count and time to EEPROM
EEPROM.put(eepromCycleCountAddr, openCloseCount);
EEPROM.put(eepromTimeAddr, cycleDuration);
// Display the updated count and cycle duration
Serial.print("Cycle Count: ");
Serial.println(openCloseCount);
Serial.print("Last Cycle Duration (ms): ");
Serial.println(cycleDuration); // Display in milliseconds
Serial.print("Last Cycle Duration (s): ");
Serial.println(cycleDuration / 1000.0, 3); // Convert ms to seconds, display with 3 decimal places
// Reset the startTime for the next cycle
startTime = millis();
} else if (!reverseLimitPressed) {
reverseLimitReached = false; // Reset if limit is released
}
}
}
}
// Function to start motor in forward direction
void startMotorForward() {
Serial.println("Motor moving forward...");
digitalWrite(MOTOR_BREAK, LOW); // Release brake
digitalWrite(MOTOR_REVERSE, HIGH); // Set forward direction
digitalWrite(MOTOR_ENABLE, LOW); // Enable motor (ensure motor runs forward)
}
// Function to start motor in reverse direction
void startMotorReverse() {
Serial.println("Motor moving reverse...");
digitalWrite(MOTOR_BREAK, LOW); // Release brake
digitalWrite(MOTOR_REVERSE, LOW); // Set reverse direction
digitalWrite(MOTOR_ENABLE, LOW); // Enable motor (ensure motor runs in reverse)
}
// Function to stop motor
void stopMotor() {
Serial.println("Motor stopping...");
digitalWrite(MOTOR_BREAK, HIGH); // Engage brake (ensure motor is stopped)
digitalWrite(MOTOR_ENABLE, HIGH); // Disable motor
digitalWrite(MOTOR_REVERSE, HIGH); // Default forward direction
}