Problem in controlling stepper motor rotation direction using 2 limit switches

Hai!!! Can you help me in controlling the direction of rotation of my stepper motor

The components used are as follows:

  1. Arduino Nano
    2.Stepper Motor Driver - A4988 (Vref 0.77v)
    3.1A 125AC limit Switches (2)
    4.NEMA 17HS3401 Stepper Motor
    5.12V 5A SMPS (Power Supply)
    6.47uf decoupling capacitor

I made the connections as per the above pasted wiring diagram,

#include <AccelStepper.h> //accelstepper library

const byte limitSwitch_1 = 2; //pin for the microswitch using attachInterrupt()
const byte limitSwitch_2 = 3; //pin for the microswitch using attachInterrupt()

bool switchFlipped = false; //stores the status for flipping
bool previousFlip = true; //stores the previous state for flipping - needed for the direction change

// direction Digital 9 (CCW), pulses Digital 8 (CLK)
AccelStepper stepper(1, 4, 5);

void setup()
{
  //Limit Switches
  pinMode(limitSwitch_1, INPUT_PULLUP); // internal pullup resistor (debouncing)
  pinMode(limitSwitch_2, INPUT_PULLUP); // internal pullup resistor (debouncing)
  
  attachInterrupt(digitalPinToInterrupt(2), FlipDirection, FALLING);   //do not change it to 'CHANGE'
  attachInterrupt(digitalPinToInterrupt(3), FlipDirection, FALLING); 
  //---------------------------------------------------------------------------

  //Serial Communication
  Serial.begin(9600); //defining some baud rate
  Serial.println("Testing Accelstepper"); //print a message
  //---------------------------------------------------------------------------

  //Stepper parameters
  //setting up some default values for maximum speed and maximum acceleration
  stepper.setMaxSpeed(5000); //SPEED = Steps / second  
  stepper.setAcceleration(1000); //ACCELERATION = Steps /(second)^2    
  stepper.setSpeed(1500);
  delay(500);
  //---------------------------------------------------------------------------

}

void loop()
{
  
  stepper.runSpeed(); //step the motor (this will step the motor by 1 step at each loop indefinitely)
  flipCheck();   //checking the flip in each loop
}

void flipCheck()
{
  if(switchFlipped == true)
  {    
     //Serial.println(previousFlip); //This was just a control flag for debugging
    
     if(previousFlip == true) //If the previous flip is 1, we have positive direction
     {    
        stepper.setSpeed(1500);       
     }
     if(previousFlip == false) //If the previous flip is 0, we have negative direction
     {  
       stepper.setSpeed(-1500);
     }
     switchFlipped = false; 
  //We have to reset this, so in the next iteration of the loop, the code will not enter this part, only when there was a click again
  }
 
}

void FlipDirection()
{    
  switchFlipped = true; //we change the status to true, so the code will enter the flipCheck() function 
  previousFlip = !previousFlip; //change the state to different from the previous - this controls the direction
 
}

This the code what i used. So the mechanism is initially the stepper should spin in Clockwise direction, and when limit switch 1 is pressed it should change the direction to Counterclockwise, and when limit switch 2 is pressed it should again change the direction to Clockwise.

I have grounded the Common (C) terminals of the limit switches and connected the Normally Open (NO) terminals to D2 and D3 respectively, so that when the limit switch is pressed the FALLING in voltage will cause an interrupt.

The problem is that the stepper motor is spinning fine initially before pressing the limit switch, but when the limit switch is pressed, the motor is getting freeze or struggling to change the direction, sometimes when i turn the shaft by my hands its changing the direction.

NOTE: I had checked my Stepper using the tutorial codes and it was working good.

Any Help Appreciated. Thanks.
:blush:

I would suspect there is an issue with the interrupt, any variable accessed in an interrupt should be declared as volatile. Ideally while you are accessing shared variables outside the interrupt you should use "noInterrupts/Interrupts" to prevent the interrupt changing them.

Do you need to use interrupts? In this example polling would work fine.

1 Like

Yes i need to use interrupt.To be frank, the code i used is borrowed from web source. Can you help me in altering the code

Try...

void FlipDirection()
{
  noInterrupts(); // disable interrupts while in the ISR
  switchFlipped = true; //we change the status to true, so the code will enter the flipCheck() function
  // move the following line out of the ISR and inside the sketch
  // previousFlip = !previousFlip; //change the state to different from the previous - this controls the direction
  interrupts(); // enable interrupts upon exiting the ISR
}
1 Like

Thank you so much for your reply😊

Interrupts are off when the interrupt service routine is triggered, off for the duration. There is no need to turn them off and on yourself in the ISR, no point.

What is more likely here is that you are getting multiple interrupts and the stepper is being told rapidly to switch directions many times, meanwhile the limit switch it is bumping may be chattering.

The solution is to "know" which way you are going. In this case, you could...

  attachInterrupt(digitalPinToInterrupt(2), goToTheLeft, FALLING);   //do not change it to 'CHANGE'
  attachInterrupt(digitalPinToInterrupt(3), goToTheRifht, FALLING);

use two similar interrupt service routines, each of which could only tell the stepper to go in the direction which will guarantee that the switch that triggered it will soon be untouched and the steps will always be driving the motor towards the other limit switch.

Then it won't matter if the stepper is told a few dozen times to go to the left, or anticlockwise or however you want to call the two directions. Something going left told to go left will just keep… going to the left, soon leaving the right hand limit switch, at which point nothing will tell it otherwise until the hole thing is repeated when the left hand limit switch is reached, where it will be told (many times, maybe) to go right.

Rinse and repeat.

The caveats about volatile variables and protected access are well taken and should be heeded.

HTH

a7

1 Like

You already do this... (sorry)

My response was a little cryptic... check switchFlipped outside the ISR, and also reset switchFlipped...

if (switchFlipped) {
  previousFlip = !previousFlip;
  switchFlipped = false; // reset the flag
}
1 Like

I got the idea. Yet I think there could still be multiple rapid changes in the direction the code thinks the stepper should move.

a7

2 Likes

Thank you😊....but im new to this....can you elaborate me

I'm afraid not. If what I wrote doesn't make sense, you'll have to puzzle it out as anything I can say will only add words that repeat the essence of the idea.

I don't have time now to run your code, demonstrate that what I think might be happening is in fact the problem and write two ISRs, one of which says go CCW and the other says go CW.

I'll circle back to see your questions and if any fellow travelers have helped or otherwise solved your problem, just now it is close to time to leave for the beach.

a7

1 Like

Hmm fine...:smile:

Still the stepper isn't respondin😕

Reading @alto777 notes, I think treating the limit switch like a noisy, bouncing, ringing button press might be worth a try. An ugly-but-easy way to de-bounce the limit switch is to insert a delay after the (if) condition... here...

For a better solution (delay is a function that degrades code responsiveness) read about debouncing a button.
https://docs.arduino.cc/built-in-examples/digital/Debounce/

1 Like

Does this mean "the motor is getting freeze or struggling to change the direction,"?

Sure,i will make use of it😁

Nope,it is spinning continuously in CW....and i think there's a pblm in my limit switch

Yes. That would also be the fastest test of the theory. Some might not even call it ugly.

In this particular case, we can step around (see what I did there) any need to denounce, as the mechanical system will provide the necessary hysteresis.

If, that is, you do have two ISRs. Each can only make the thing go the other way. All bouncing is completely handled by amounting to redundant commands to go the way the thing has been being told to go just now already.

I haven't and won't be able to for some time looked closely at the code @ragul_17 is wrangling - my first question would be to see if interrupts are even necessary and appropriate for this.

I use interrupts, usually know what I am doing (!) and find them indispensable when they are, which in this kind of project is very rarely.

Other than using them without even caring or knowing because a library author has decided to.

a7

1 Like
void goToTheLeft(void){stepper.setSpeed(-1500);}
void goToTheRifht(void){stepper.setSpeed(1500);}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.