// https://wokwi.com/projects/357333073299191809
// https://forum.arduino.cc/t/stepper-motors-limit-switches-and-buttons/1089118
// this has ben slightly modified from the version posted on the forum thread
// Define pins for stepper motor control
#define DIR_PIN 8
#define STEP_PIN 9
// Define pins for buttons and limit switches
#define UP_BUTTON 2
#define DOWN_BUTTON 3
#define STOP_BUTTON 4
#define LIMIT_SWITCH_1 5
#define LIMIT_SWITCH_2 6
enum MotorStates
{
STOPPED=0,
MOVING
};
#define BTN_PRESSED LOW
#define LIMSW_PRESSED HIGH
const uint32_t kFadeTime = 3000000ul; //3-second ramp time
const uint32_t kInitSpeed = 1000ul; //2x == uS/step
const uint32_t kFinalSpeed = 250ul; //2x == uS/step
const uint32_t kAccelDelay = (uint32_t)(kFadeTime / (kInitSpeed - kFinalSpeed) );
uint32_t
ulStepDelay,
tNow,
tAccel = 0ul;
bool
bAccel;
void setup()
{
// Set pins for motor control as output
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
// Set pins for buttons and limit switches as input
pinMode(UP_BUTTON, INPUT_PULLUP);
pinMode(DOWN_BUTTON, INPUT_PULLUP);
pinMode(STOP_BUTTON, INPUT_PULLUP);
pinMode(LIMIT_SWITCH_1, INPUT_PULLUP);
pinMode(LIMIT_SWITCH_2, INPUT_PULLUP);
// Set initial state of DIR_PIN to LOW
digitalWrite(DIR_PIN, LOW);
bAccel = false;
setupDisplay();
}//setup
void loop()
{
static uint8_t
motorState = STOPPED,
pinLimit;
rackService(motorState, pinLimit);
if( digitalRead( STOP_BUTTON ) == BTN_PRESSED )
{
motorState = STOPPED;
}
switch( motorState )
{
case STOPPED:
if( digitalRead( UP_BUTTON ) == BTN_PRESSED )
{
digitalWrite(DIR_PIN, LOW);
pinLimit = LIMIT_SWITCH_1;
ulStepDelay = kInitSpeed;
tAccel = micros();
bAccel = true;
motorState = MOVING;
}//if
else if( digitalRead( DOWN_BUTTON ) == BTN_PRESSED )
{
digitalWrite(DIR_PIN, HIGH);
pinLimit = LIMIT_SWITCH_2;
ulStepDelay = kInitSpeed;
tAccel = micros();
bAccel = true;
motorState = MOVING;
}//if
break;
case MOVING:
tNow = micros();
if( bAccel )
{
if( (tNow - tAccel) >= kAccelDelay )
{
tAccel = tNow;
ulStepDelay--;
if( ulStepDelay == kFinalSpeed )
bAccel = false;
}//if
}//if
if( digitalRead( pinLimit ) != LIMSW_PRESSED )
{
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(ulStepDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(ulStepDelay);
}//if
else
{
motorState = STOPPED;
}//if
break;
}//switch
}//loop
//
# include <Adafruit_NeoPixel.h>
# define LED_PIN A2
# define LED_COUNT 25
# define upperFakeLimit A0
# define lowerFakeLimit A1
# define SPEED 277 // ms per step
Adafruit_NeoPixel rack(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void setupDisplay()
{
pinMode(lowerFakeLimit, OUTPUT);
pinMode(upperFakeLimit, OUTPUT);
digitalWrite(lowerFakeLimit, LOW);
digitalWrite(upperFakeLimit, LOW);
rack.begin();
rack.setPixelColor(LED_COUNT / 2, 0x00ff00);
rack.show();
}
void rackService(uint8_t state, uint8_t direction)
{
static byte position = LED_COUNT / 2;
static unsigned long lastDisplay;
unsigned long now = millis();
if (state != MOVING) return;
if (now - lastDisplay < SPEED) return;
lastDisplay = now;
rack.setPixelColor(position, 0x101010);
if (direction == LIMIT_SWITCH_1)
position++;
else
position--;
if (position >= LED_COUNT) {
position = LED_COUNT - 1;
}
if (position < 0) position = 0;
digitalWrite(lowerFakeLimit, position <= 0 ? HIGH : LOW);
digitalWrite(upperFakeLimit, position >= (LED_COUNT - 1) ? HIGH : LOW);
rack.setPixelColor(position, 0x0000ff);
rack.show();
lastDisplay = now;
}
LIMIT (NC)
LIMIT (NC)
<-proxies
UPPER
LOWER