Cant stop stepper motor from rotating

Hi guys,

Its been a long few days as I’ve been trying to solve the following problem. I have a setup with an arm thats rotating a total of 90 degrees in the horizontal plane around the Z axis. The rotation is achieved with a stepper motor that has an incremental encoder attached to its shaft. Also, on the left and the right side of the arm, i have limit switches to home the arm.

I found a code for reading out the encoder using interrupts, which works perfectly fine. Then I created a homing function with the limit switches. I’m encountering the following problems:

  • arm moves to the first limit switch, changes direction and moves to the second limit switch, then goes all the way back to the first limit switch. This keeps repeating. After it hitting the second limit switch, i want the arm to stand still in the middle at 45 degrees, but it just keeps moving.
  • I cannot put the function homing () in the void setup(). Thid would be much better because then it would home directly at startup, but if I put it in the setup, the encoder reading function doesn’t work anymore. I get the error isr_2 not defined.

So, my main question is: how can I get the motor to stop rotating after homing?

See code below and thanks in advance!

//encoder
#define encoderPinA 2 //encoder A
#define encoderPinB 3 //encoder B
#define CPR 4096 // encoder counts/rev
volatile int counter = 0; //counter encoder steps
volatile int var_degrees = 0; // encoder output in degrees

//stepper motor
#define dirPin 8 //dir motorcontroller
#define stepPin 9 // step motorcontroller
int stepsPerRevolution = 800; //microstepping incl
boolean motorMayMoveFwd = LOW;
boolean motorMayMoveFwd2 = LOW;

//limit switch 1
#define limitSwitch1 4 // limit switch 1
boolean switchState1 = LOW; // switch state
boolean prevSwitchState1 = LOW; // previous switch state
boolean leftHomingDone = false;

//limit switch 2
#define limitSwitch2 10 // limit switch 2
boolean switchState2 = LOW; // switch state
boolean prevSwitchState2 = LOW; // previous switch state
boolean rightHomingDone = true;

//interrupt
volatile boolean flag; // flag for interrupts


void setup() {

  Serial.begin (115200); // baudrate serial monitor
  attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_2, CHANGE); //initialize interrupt

  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  pinMode (limitSwitch1, INPUT);
  pinMode (limitSwitch2, INPUT);

  pinMode (encoderPinA, INPUT);
  pinMode (encoderPinB, INPUT);

}

void loop() {
  if (flag == true) {
    var_degrees = ((360 / 4096.00) * counter); //convert encoder steps to degrees
    Serial.println(counter);
    flag = false;
  }
  homing();
}

//Interrupts for encoder

void isr_2() {
  flag = true;
  if (digitalRead(encoderPinA) == HIGH) {
    if (digitalRead(encoderPinB) == LOW) {
      counter = counter - 1; //COUNTER CLOCK WISE
    }
    else {
      counter = counter + 1; //CW
    }
  }
  else {
    if (digitalRead(encoderPinB) == LOW) {
      counter = counter + 1; //CW
    }
    else {
      counter = counter - 1 ; //CCW
    }
  }
}

//homing of the arm
void homing() {
  /////limit switch 1////
  prevSwitchState1 = switchState1;
  switchState1 = digitalRead(limitSwitch1); //read out switch

  if (switchState1 == HIGH && prevSwitchState1 == LOW) { //if switch is not activated
    motorMayMoveFwd = true; //motor may move
  }

  if (motorMayMoveFwd == true) {
    digitalWrite(dirPin, HIGH);// Set the spinning direction CCW
    // Spin the stepper motor 1 revolution slowly:
    //for (int i = 0; i < stepsPerRevolution; i++) {
    // These four lines result in 1 step:
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(7000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(7000);
  }

  switchState1 = digitalRead(limitSwitch1); //read out switch

  if (switchState1 == LOW && prevSwitchState1 == HIGH) { //if switch is activated
    // var_degrees = -45;
    counter = 0;
    Serial.print(counter);
    switchState1 = prevSwitchState1;
    motorMayMoveFwd = false; //motor may not move
  }

  if (motorMayMoveFwd == false) {
    digitalWrite(dirPin, LOW);// CW
    // Spin the stepper motor 1 revolution slowly:
    //for (int i = 0; i < stepsPerRevolution; i++) {
    // These four lines result in 1 step:
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(7000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(7000);
    leftHomingDone = true;
  }



  /////Limit switch 2/////
  prevSwitchState2 != switchState2;
  switchState2 = digitalRead(limitSwitch2); //read out switch

  if (switchState2 == LOW && prevSwitchState2 == LOW) { //if switch is activated
    //var_degrees = 45;
    counter = 1024; //=90 graden in cpr
    // Serial.println("pressed");
    switchState2 = prevSwitchState2;
    motorMayMoveFwd2 = false;
    motorMayMoveFwd = true;
    if (motorMayMoveFwd2 == false) {
      digitalWrite(dirPin, HIGH);// CW
      // Spin the stepper motor 1 revolution slowly:
      //for (int i = 0; i < stepsPerRevolution; i++) {
      // These four lines result in 1 step:
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(7000);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(7000);
      rightHomingDone = true;

      if (rightHomingDone == true) {
        digitalWrite(dirPin, LOW);// CW
        // Spin the stepper motor 1 revolution slowly:
        //for (int i = 0; i < stepsPerRevolution; i++) {
        // These four lines result in 1 step:
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(7000);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(7000);
        if (counter == 512) { //tried getting it to the            middle, doesn't work
          digitalWrite(stepPin, LOW);
        }

      }
    }

  }
}

What is the role of the encoder if you have limit switches? are you tracking speed or specific positions?

how did you wire your limit switches? do you have a pulldown?

I'm not sure I understand why do you call homing() in the loop ?

May be you could use libraries to make your life easier:

That would let you focus on the structure of your code at a higher conceptual level

  • in set up
  • setup everything (pinMode etc)
  • make steps clockwise until you hit the limit switch of that direction
  • mark that position as 0 for the encoder
  • note that direction to move is counter-clockwise (a nextStep variable of -1 for example)

in loop

  • take a set in the direction to move
  • read and print the encoder
  • check if you just hit the limit switch for that direction. if so, inverse direction to move

==> you'll get homing first, then a sweeping movement