/*
 * Arduio Uno control stepper motor drive for att and phase in LINAC
 * limit travel range by 2 limits switch and control moving my 2 switchs
 * Created by Mr.Chatchabhumi Dhammatong
 *
 *
 * Thank you for tutorial as below:
 * Tutorial page: https://arduinogetstarted.com/tutorials/arduino-stepper-motor-and-limit-switch
 */

#include <ezButton.h>
#include <AccelStepper.h>
//#include "Arduino_DebugUtils.h"

// axial Atten 2
#define M1_DIR 8
#define M1_STEP 9
#define AXIS1_UP_LIM A0
#define AXIS1_LO_LIM A1
#define AXIS1_UP_SW A2
#define AXIS1_LO_SW A3

// axial Phase 2
#define M2_DIR 10
#define M2_STEP 11
#define AXIS2_UP_LIM A4
#define AXIS2_LO_LIM A5
#define AXIS2_UP_SW A6
#define AXIS2_LO_SW A7

#define DEBUG 1
#define DIRECTION_CCW -1
#define DIRECTION_CW 1

#define STATE_STOP 0
#define STATE_STANDBY 10
#define STATE_CHANGE_DIR 1
#define STATE_MOVE 2
#define STATE_MOVING 3
#define STATE_MOV_CW 4
#define STATE_MOV_CCW 5
#define STATE_LIMIT_1 6
#define STATE_LIMIT_2 7
#define STATE_QUICKSTOP 99

#define MAX_POSITION 0x7FFFFFFF // maximum of position we can set (long type)
#define MIN_POSITION 0          // mm

#define MAX_SPEED 1000.0 // step per secound
#define ACCELERATE 400   // step per sec^2
#define INIT_SPEED 100.0
#define RUN_SPEED 600.0
#define STEP_PER_REV 18000
#define DISTANCE_REV 1.0
#define SLEW_RATE_SPEED 100.0

struct axial
{
    int stepperState = STATE_STOP;
    int direction = DIRECTION_CW;
    long targetPos = 0;
    long maxPos = MAX_POSITION;
    int runSpeed = RUN_SPEED;
    long pressTime = 0;
};

axial Axial[2];
AccelStepper stepper[] = {
    AccelStepper(AccelStepper::DRIVER, M1_STEP, M1_DIR),
    AccelStepper(AccelStepper::DRIVER, M2_STEP, M2_DIR)
    };

ezButton upperLimitSwitch[] = {
    ezButton(AXIS1_UP_LIM),
    ezButton(AXIS2_UP_LIM)
    };

ezButton lowerLimitSwitch[] = {
    ezButton(AXIS1_LO_LIM),
    ezButton(AXIS2_LO_LIM)
    };

ezButton CW_Switch[] = {
    ezButton(AXIS1_UP_SW),
    ezButton(AXIS2_UP_SW)
    };

ezButton CCW_Switch[] = {
    ezButton(AXIS1_LO_SW),
    ezButton(AXIS2_LO_SW)
    };

void setup()
{
    // Serial.begin(115200);

    for (byte i = 0; i < 2; i++)
    {
        upperLimitSwitch[i].setDebounceTime(20); // set debounce time to 10 milliseconds
        lowerLimitSwitch[i].setDebounceTime(20); // set debounce time to 10 milliseconds
        CW_Switch[i].setDebounceTime(50);        // set debounce time to 50 milliseconds
        CCW_Switch[i].setDebounceTime(50);       // set debounce time to 50 milliseconds

        stepper[i].disableOutputs();            // disable outputs
        stepper[i].setMaxSpeed(MAX_SPEED);      // set the maximum speed
        stepper[i].setAcceleration(ACCELERATE); // set acceleration
        stepper[i].setSpeed(INIT_SPEED);        // set initial speed
        stepper[i].setCurrentPosition(0.0);       // set position
        Axial[i].pressTime = 0;
    }
}

void loop()
{
        
    for (byte j = 0; j < 2; j++)
    {
        upperLimitSwitch[j].loop(); // MUST call the loop() function
        lowerLimitSwitch[j].loop(); // MUST call the loop() function
        CW_Switch[j].loop();        // MUST call the loop() function first
        CCW_Switch[j].loop();       // MUST call the loop() function first
    }

    for (byte j = 0; j < 2; j++)
    {
        if (CW_Switch[j].isPressed())
        {
            Axial[j].stepperState = STATE_MOV_CW;
    
        }
        if (CW_Switch[j].isReleased())
        {
            Axial[j].stepperState = STATE_STOP;
        }

        if (CCW_Switch[j].isPressed())
        {
            Axial[j].stepperState = STATE_MOV_CCW;
            //Axial[j].pressTime=0;
        }

        if (CCW_Switch[j].isReleased())
        {
            Axial[j].stepperState = STATE_STOP;
        }

        if (lowerLimitSwitch[j].isPressed())
        {
            Axial[j].stepperState = STATE_QUICKSTOP;
        }
        if (lowerLimitSwitch[j].isReleased())
        {
        }
        if (upperLimitSwitch[j].isPressed())
        {
            Axial[j].stepperState = STATE_QUICKSTOP;
            Axial[j].maxPos = stepper[j].currentPosition();
        }
        if (upperLimitSwitch[j].isReleased())
        {
            stepper[j].setCurrentPosition(0.0);
        }
    }

    for (byte i = 0; i < 2; i++)
    {
        switch (Axial[i].stepperState)
        {
        case STATE_QUICKSTOP:
            stepper[i].stop(); // STOP
            stepper[i].setSpeed(0.0);
            stepper[i].runSpeed();
            break;

        case STATE_STOP:
            stepper[i].setSpeed(0.0);
            stepper[i].runSpeed();
            Axial[i].stepperState = STATE_STANDBY;
            stepper[i].runSpeed();

            break;

        case STATE_STANDBY:
            stepper[i].disableOutputs(); // disable outputs
            stepper[i].setSpeed(0.0);
            Axial[i].stepperState = STATE_STANDBY;
            break;

        case STATE_MOV_CW:
            if (upperLimitSwitch[i].getState())
            { // checking the limits are touched?
                Axial[i].direction = DIRECTION_CW;
                stepper[i].setSpeed(Axial[i].direction * INIT_SPEED);
                stepper[i].enableOutputs();
                Axial[i].stepperState = STATE_MOVE;
                Axial[i].pressTime = millis();
            }
            else
            {
            }

            break;
        
    case STATE_MOV_CCW:
        if (lowerLimitSwitch[i].getState())
        { // checking the limits are touched?
            Axial[i].direction = DIRECTION_CCW;
            stepper[i].setSpeed(Axial[i].direction * INIT_SPEED);
            stepper[i].enableOutputs();
            Axial[i].stepperState = STATE_MOVE;
            Axial[i].pressTime=millis();
        }
        else
        {
        }

        break;

    case STATE_MOVE:
        stepper[i].runSpeed();
        Axial[i].stepperState = STATE_MOVE;
        if(millis()-Axial[i].pressTime >=1000){
          if (Axial[i].direction ==DIRECTION_CW){
             stepper[i].setSpeed((stepper[i].speed() < MAX_SPEED)? stepper[i].speed() +SLEW_RATE_SPEED:MAX_SPEED );
            
          }else{
            stepper[i].setSpeed(stepper[i].speed() > (-1*MAX_SPEED)? stepper[i].speed() -SLEW_RATE_SPEED :-1*MAX_SPEED );
          }
          Axial[i].pressTime=millis();
        }

        break;

    case STATE_MOVING: // without this state, the move will stop after reaching maximum position

        break;
    }
}
}
A4988
A4988