#include <AccelStepper.h>
#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define STEP_PIN 3
#define DIR_PIN 4
#define JOY_Y_PIN A0
#define SERVO_PIN 5
LiquidCrystal_I2C lcd(0x27, 16, 2);
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
Servo myServo;
const int threshold = 150;
int yCenter;
bool waitingForNeutral = false;
bool runningDown = false;
unsigned long runStart = 0;
int downPressCount = 0;
int servoAngle = 0;
const int maxStepperMillis = 5000; // 5 seconds max
void setup() {
stepper.setMaxSpeed(500);
stepper.setSpeed(200);
myServo.attach(SERVO_PIN);
myServo.write(0);
delay(500);
yCenter = analogRead(JOY_Y_PIN);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Stepper/Servo Demo");
lcd.setCursor(0, 1);
lcd.print("Waiting...");
}
void loop() {
int joyY = analogRead(JOY_Y_PIN);
// UP pressed: Reset/homing
if (!waitingForNeutral && (joyY > yCenter + threshold)) {
runningDown = false;
downPressCount = 0;
servoAngle = 0;
myServo.write(0);
waitingForNeutral = true;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Home: Srv=0 S=Stop");
lcd.setCursor(0, 1);
lcd.print("Press DOWN...");
}
// DOWN pressed: Start stepper timing if allowed
if (!waitingForNeutral && (joyY < yCenter - threshold) && downPressCount < 2) {
if (!runningDown) {
runningDown = true;
runStart = millis();
waitingForNeutral = true; // Wait for release before next press
lcd.setCursor(0, 0);
lcd.print("DOWN: Stepper Run ");
lcd.setCursor(0, 1);
lcd.print("Srv:");
lcd.print(servoAngle);
lcd.print(" Cnt:");
lcd.print(downPressCount);
}
}
// Wait for joystick return to neutral
if (waitingForNeutral && abs(joyY - yCenter) < threshold / 2) {
waitingForNeutral = false;
}
// While joystick DOWN pressed and runningDown active
if (runningDown) {
// Only run stepper if joystick still held DOWN
if (joyY < yCenter - threshold) {
stepper.runSpeed();
// Check max duration
if (millis() - runStart >= maxStepperMillis) {
runningDown = false;
downPressCount++;
servoAngle += 90;
if (servoAngle > 180) servoAngle = 180;
myServo.write(servoAngle);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("RunDone: Srv=");
lcd.print(servoAngle);
lcd.setCursor(0, 1);
if (downPressCount < 2)
lcd.print("Next DOWN run...");
else
lcd.print("Max. Press UP.");
}
} else {
// Joystick released early, stop without progressing sequence
runningDown = false;
}
}
}