// https://wokwi.com/projects/399355387445360641
// for https://forum.arduino.cc/t/limit-switch-issue-for-stepper-motor-application/1265784/12
//
// based on sim https://wokwi.com/projects/388661915235241985
// and https://github.com/waspinator/AccelStepper/tree/master/examples/Bounce
// adding a state machine to have an un-balanced CW-CCW movement
// and a limited number of cycle counts.
// and a button for a limit switch
// and simulated limit switchs on both ends, Right side pot-adjustable
// and a scope to see the stepper phase timing.
//

//
// Bounce.pde -- adapted for state machine
// -*- mode: C++ -*-
//
// Make a single stepper bounce from one limit to another
//
// Copyright (C) 2012 Mike McCauley
// $Id: Random.pde,v 1.1 2011/01/05 01:51:01 mikem Exp mikem $

#include <AccelStepper.h> // https://www.airspayce.com/mikem/arduino/AccelStepper/index.html

// Define a stepper and the pins it will use
AccelStepper stepper(1, 10, 7); // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5

const byte limitSwitchPin = A1;
// name some states
enum MotionStates {STOPPED,CW,CCW} motionState = STOPPED;

long positionAbs = 200;
long leftPos = -100;
long rightPos = 200;
int cycleCount = 100;
int currentCycle = 0;
bool simLeftSwitchTriggered = 0, simRightSwitchTriggered = 0;

void setup()
{
  Serial.begin(115200);
  pinMode(limitSwitchPin, INPUT_PULLUP);
  // Change these to suit your stepper if you want
  stepper.setMaxSpeed(100);
  stepper.setAcceleration(400);
  stepper.moveTo(rightPos);
  motionState = CW;
  currentCycle = cycleCount;
  Serial.print(currentCycle);
  Serial.print(':');
  reportPosition();
}

void loop()
{
  simulateHardware();

  bool limitSwitchActive = digitalRead(limitSwitchPin) == LOW || simLeftSwitchTriggered;

  // If at the end of travel go to the other end
  switch (motionState) {
    case CCW: // moving CCW
      if (stepper.distanceToGo() == 0 // finished motion?
          || limitSwitchActive // active limit switch
         )
      {
        currentCycle -= 1;
        Serial.print(currentCycle);
        Serial.print(':');
        reportPosition();
        if (currentCycle > 0) {
          stepper.moveTo(rightPos);
          motionState = CW;
        } else {
          motionState = STOPPED; // go idle
        }
      }
      break;
    case CW: 
      if (stepper.distanceToGo() == 0
          || simRightSwitchTriggered // active Right limit switch
         )
      {
        reportPosition();
        Serial.print(", ");
        stepper.moveTo(leftPos);
        motionState = CCW;
      }
      break;
    case STOPPED: 
      ; // do nothing
      break;
  }
  stepper.run(); // move stepper as needed
}

void reportPosition(){
  Serial.print("(@");
  Serial.print(stepper.currentPosition());
  Serial.print(")");
}

void simulateHardware(void) {
  const uint32_t interval = 10;
  static uint32_t last = 0;
  if (millis() - last >= interval) {
    last += interval;
    int rightLimit = rightPos - map(analogRead(A0),0,1023,0,rightPos);
    simLeftSwitchTriggered = (stepper.currentPosition() <= 0 && stepper.currentPosition() > -20) ;
    simRightSwitchTriggered = stepper.currentPosition() >= rightLimit && stepper.currentPosition() < rightLimit+20;
  }
}
A4988
A4988
Loading chip...chip-scope
Left Limit (manual)
Right Limit Switch Adjustment.