#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// Define LCD properties
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 columns and 2 rows
// Define Keypad properties
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; // Connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; // Connect to the column pinouts of the keypad
// Create the Keypad object
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Define stepper motor pins
#define STEPPER_DIR_PIN 10
#define STEPPER_STEP_PIN 11
#define SLEEP 12
// Global variables
float yards = 0.0;
unsigned long duration = 0;
float Time = 0.0;
bool decimalEntered = false;
void setup() {
pinMode(SLEEP, OUTPUT);
pinMode(STEPPER_DIR_PIN,OUTPUT);
pinMode(STEPPER_STEP_PIN,OUTPUT);
// Initialize LCD
lcd.init();
lcd.backlight();
// Initialize serial communication for debugging
Serial.begin(9600);
// Print initial message
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" 1 for Auto");
lcd.setCursor(0, 1);
lcd.print(" 2 for Manual");
}
void loop() {
// Check for keypad input
char key = keypad.getKey();
// If a key is pressed
if (key != NO_KEY) {
// If key is '1', enter automatic mode
if (key == '1') {
enterAutomaticMode();
}
// If key is '2', enter manual mode
else if (key == '2') {
enterManualMode();
}
}
}
void enterAutomaticMode() {
// Print initial message
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter yards:");
while (true) {
char key = keypad.getKey();
if (key != NO_KEY) {
// If key is a digit or decimal point, append it to the yards variable
if (isdigit(key) || key == '.') {
if (key == '.') {
// Check if decimal point is already entered
if (!decimalEntered) {
decimalEntered = true;
lcd.print(key);
}
} else {
yards = yards * 10 + (key - '0');
if (decimalEntered) {
// Increment the decimal point position
yards /= 10.0;
}
lcd.print(key);
}
}
// If key is 'A', start measuring
else if (key == 'A') {
startMeasuring();
break;
}
// If key is '#', clear the yards variable
else if (key == '#') {
yards = 0;
decimalEntered = false; // Reset decimal point flag
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter yards:");
}
}
}
}
void enterManualMode() {
// Clear LCD and print instructions for manual mode
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("1- FreeRun");
lcd.setCursor(0, 1);
lcd.print("#- Stop run");
char key; // Declare key outside of the while loops
unsigned long startTime = millis();
int stepperdelay = 5000;
while (true) {
// Check for keypress
key = keypad.getKey();
// If key is '1', start free run
if (key == '1') {
digitalWrite(STEPPER_DIR_PIN, HIGH);
digitalWrite(SLEEP, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Free Running");
while (true) {
while(millis() - startTime < stepperdelay){
digitalWrite(STEPPER_STEP_PIN,HIGH);
delayMicroseconds(stepperdelay);
digitalWrite(STEPPER_STEP_PIN,LOW);
delayMicroseconds(stepperdelay);
//decrease stepper delay value by 1 microsecond
stepperdelay--;
}
digitalWrite(STEPPER_STEP_PIN, HIGH);
delayMicroseconds(500); // Adjust delay based on motor speed requirements
digitalWrite(STEPPER_STEP_PIN, LOW);
delayMicroseconds(500); // Adjust delay based on motor speed requirements
key = keypad.getKey();
if (key == '#') {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Time-");
while (true) {
digitalWrite(STEPPER_DIR_PIN, LOW);
digitalWrite(SLEEP, LOW);
key = keypad.getKey();
if (isdigit(key) || key == '.') {
if (key == '.') {
// Check if decimal point is already entered
if (!decimalEntered) {
decimalEntered = true;
lcd.print(key);
}
} else {
Time = Time * 10 + (key - '0');
if (decimalEntered) {
// Increment the decimal point position
Time /= 10.0;
}
lcd.print(key);
}
} else if (key == 'A') {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Yards:");
while (true) {
key = keypad.getKey();
if (isdigit(key)) {
yards = yards * 10 + (key - '0');
lcd.print(key);
} else if (key == 'A') {
digitalWrite(SLEEP, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Measuring");
unsigned long yardTime = Time * 1000; // Time for one yard in milliseconds
duration = yards * yardTime; // Total duration for all yards
int stepperdelay = 5000;
digitalWrite(STEPPER_DIR_PIN, HIGH);
unsigned long startTime = millis();
while (millis() - startTime < duration) {
while(millis() - startTime < stepperdelay){
digitalWrite(STEPPER_STEP_PIN,HIGH);
delayMicroseconds(stepperdelay);
digitalWrite(STEPPER_STEP_PIN,LOW);
delayMicroseconds(stepperdelay);
//decrease stepper delay value by 1 microsecond
stepperdelay--;
}
// Generate step pulse
digitalWrite(STEPPER_STEP_PIN, HIGH);
delayMicroseconds(500); // Adjust delay based on motor speed requirements
digitalWrite(STEPPER_STEP_PIN, LOW);
delayMicroseconds(500); // Adjust delay based on motor speed requirements
}
digitalWrite(STEPPER_STEP_PIN, LOW);
digitalWrite(SLEEP, LOW);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Measured");
resetState(); // Reset state after all operations are completed
return; // Exit the function after resetting state
}
}
}
}
}
}
}
}
}
void startMeasuring() {
// Clear LCD and display 'Measuring' message
digitalWrite(SLEEP, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Measuring");
// Calculate duration based on yards
unsigned long yardTime = 4 * 1000; // Time for one yard in milliseconds
duration = yards * yardTime; // Total duration for all yards
int stepperdelay = 5000;
// Set direction of stepper motor (clockwise)
digitalWrite(STEPPER_DIR_PIN, HIGH);
unsigned long startTime = millis();
while (millis() - startTime < duration) {
while(millis() - startTime < stepperdelay){
digitalWrite(STEPPER_STEP_PIN,HIGH);
delayMicroseconds(stepperdelay);
digitalWrite(STEPPER_STEP_PIN,LOW);
delayMicroseconds(stepperdelay);
//decrease stepper delay value by 1 microsecond
stepperdelay--;
}
// Generate step pulse
digitalWrite(STEPPER_STEP_PIN, HIGH);
delayMicroseconds(500); // Adjust delay based on motor speed requirements
digitalWrite(STEPPER_STEP_PIN, LOW);
delayMicroseconds(500); // Adjust delay based on motor speed requirements
}
digitalWrite(STEPPER_STEP_PIN, LOW);
digitalWrite(SLEEP, LOW);
// Return to initial state
resetState();
}
void resetState() {
// Clear LCD and reset variables
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" 1 for Auto");
lcd.setCursor(0, 1);
lcd.print(" 2 for Manual");
yards = 0.0;
Time = 0.0;
decimalEntered = false; // Reset decimal point fla
}