// 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;
}
}
Left
Limit
(manual)
Right Limit Switch
Adjustment.