Go Down

Topic: end stops for stepper motor (Read 177 times) previous topic - next topic

bob999


I need to add some end stops to this stepper motor code. I'm using one axis of a joystick to control a carriage that goes back and forth on a long screw. I have hall switches for both ends, I just want it to stop going in that direction when it triggers the switch. I didn't wright this code but it works great if I could just add the end stops. If I have the switches connected to pins 2 and 3, how could I wright something like; if pin 2 high, stop motor in that direction, and then the same for pin 3 in the opposite direction?



Code: [Select]
#include <AccelStepper.h> //accelstepper library
AccelStepper stepper(1, 8, 9); // direction Digital 9 (CCW), pulses Digital 8 (CLK)
//Pins
 const byte Analog_X_pin = A0; //x-axis readings
 const byte enablePin = 7;
//Variables
 int Analog_X = 0; //x-axis value
 int Analog_X_AVG = 0; //x-axis value average
  //----------------------------------------------------------------------------
void setup()
{
  Serial.begin(9600);
  //----------------------------------------------------------------------------   
  //PINS
  pinMode(Analog_X_pin, INPUT);
  pinMode(enablePin, OUTPUT);
  //---------------------------------------------------------------------------- 
  InitialValues(); //averaging the values of the 3 analog pins (values from potmeters)
  //---------------------------------------------------------------------------- 
  //Stepper parameters
  //setting up some default values for maximum speed and maximum acceleration
  stepper.setMaxSpeed(2000); //SPEED = Steps / second 
  stepper.setAcceleration(1000); //ACCELERATION = Steps /(second)^2   
  stepper.setSpeed(1000);
  delay(1000);
}
void loop()
{
  ReadAnalog(); 
  stepper.runSpeed(); //step the motor (this will step the motor by 1 step at each loop indefinitely)
}
void ReadAnalog()
{
  if(abs(Analog_X-Analog_X_AVG)>50)
  {
      digitalWrite(enablePin, HIGH);  // enable the driver
      stepper.setSpeed(5*(Analog_X-Analog_X_AVG));   
  }
  else
  {
      digitalWrite(enablePin, LOW);   // disable the driver
      stepper.setSpeed(0);
  }
  //Reading the potentiometer in the joystick:
  Analog_X = analogRead(Analog_X_pin); 
  //if the value is 25 "value away" from the average (midpoint), we allow the update of the speed
  //This is a sort of a filter for the inaccuracy of the reading
  if(abs(Analog_X-Analog_X_AVG)>50)
  {
  stepper.setSpeed(5*(Analog_X-Analog_X_AVG));   
  }
  else
  {
    stepper.setSpeed(0);
  }
}
void InitialValues()
{
  //Set the values to zero before averaging
  float tempX = 0;
  //---------------------------------------------------------------------------- 
  //read the analog 50x, then calculate an average.
  //they will be the reference values
  for(int i = 0; i<50; i++)
  {
    tempX += analogRead(Analog_X_pin); 
    delay(10); //allowing a little time between two readings
  }
  //---------------------------------------------------------------------------- 
  Analog_X_AVG = tempX/50;
  //---------------------------------------------------------------------------- 
  Serial.print("AVG_X: ");
  Serial.println(Analog_X_AVG);
  Serial.println("Calibration finished"); 
}



drmpf

Check out my revised library  SpeedStepper
I think it does what you want and will let you replace the switches with position limit settings.



Robin2

#2
Jan 24, 2021, 10:29 am Last Edit: Jan 24, 2021, 10:35 am by Robin2
I just want it to stop going in that direction when it triggers the switch.
You just need another function (a little like your readAnalog() function) that reads the state of the limit switches and also call that from loop() - something like this

Code: [Select]
void loop()
{
  ReadAnalog();  
  checkEndStops();
  if (stepperMayMove == true) {
     stepper.runSpeed();
  }
}


Code: [Select]
void checkEndStops() {
  static byte leftStopState = HIGH;
  static byte rightStopState = HIGH;
  byte previousLeftState = leftStopState;
  byte previousRightState = rightStopState;
  leftStopState = digitalRead(leftStoPin);
  rightStopState = digitalRead(rightStopPin);
  if (leftStopState == LOW and previousLeftState == HIGH) { // assumes LOW when triggered may be wrong
   stepperMayMove = false; // stepperMayMove must be a global variable
 }
 if (rightStopState == LOW and previousRightState == HIGH) { // assumes LOW when triggered may be wrong
   stepperMayMove = false;
 }
}


You have not said how you want the motor to restart after a stop so I have not dealt with that. You could, for example, get the motor to change direction when a limit switch is triggered.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

bob999

Thanks, simply put I only want the motor to stop going left when left switch is on and stop going right when right switch is on.  So the carriage moves either direction unless it reaches one of the end switches which stops it from going any farther in that direction only.  Also the code has been modified so that when the joystick is in center (off) position no power is going to the motor. This is because I'm using battery power and I don't need precision locking.

Robin2

Thanks, simply put I only want the motor to stop going left when left switch is on and stop going right when right switch is on.
Try the code I suggested and then try modifying it to the meet your requirement - it should provide a good starting point.

If you run into a problem please post the program that represents your best attempt and tell us in detail what it actually does and what you want it to do that is different. That way we can focus on the parts you need help with rather than wasting time on things that you can do.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

bob999

I don't know how to add your code, I just get errors and it won't compile
Code: [Select]
#include <AccelStepper.h> //accelstepper library
AccelStepper stepper(1, 8, 9); // direction Digital 9 (CCW), pulses Digital 8 (CLK)
//Pins
 const byte Analog_X_pin = A0; //x-axis readings
 const byte enablePin = 7;
//Variables
 int Analog_X = 0; //x-axis value
 int Analog_X_AVG = 0; //x-axis value average

void setup()
{
 
  //SERIAL
  Serial.begin(9600);
  //----------------------------------------------------------------------------
  InitialValues(); //averaging the values of the 3 analog pins (values from potmeters)
  //----------------------------------------------------------------------------    
  //PINS
  pinMode(Analog_X_pin, INPUT);
  pinMode(enablePin, OUTPUT);
  //----------------------------------------------------------------------------  
  //Stepper parameters
  //setting up some default values for maximum speed and maximum acceleration
  stepper.setMaxSpeed(2000); //SPEED = Steps / second  
  stepper.setAcceleration(1000); //ACCELERATION = Steps /(second)^2    
  stepper.setSpeed(1000);
  delay(1000);
}
void loop()
{
  ReadAnalog();  
  checkEndStops();
  if (stepperMayMove == true) {
     stepper.runSpeed();
  }
{
  ReadAnalog();  
  stepper.runSpeed(); //step the motor (this will step the motor by 1 step at each loop indefinitely)
}
void ReadAnalog()
void checkEndStops() {
  static byte leftStopState = HIGH;
  static byte rightStopState = HIGH;
  byte previousLeftState = leftStopState;
  byte previousRightState = rightStopState;
  leftStopState = digitalRead(leftStoPin);
  rightStopState = digitalRead(rightStopPin);
  if (leftStopState == LOW and previousLeftState == HIGH) { // assumes LOW when triggered may be wrong
   stepperMayMove = false; // stepperMayMove must be a global variable
 }
 if (rightStopState == LOW and previousRightState == HIGH) { // assumes LOW when triggered may be wrong
   stepperMayMove = false;
 }
}
{
  if(abs(Analog_X-Analog_X_AVG)>50)
  {
      digitalWrite(enablePin, HIGH);  // enable the driver
      stepper.setSpeed(5*(Analog_X-Analog_X_AVG));  
  }
  else
  {
      digitalWrite(enablePin, LOW);   // disable the driver
      stepper.setSpeed(0);
  }
  //Reading the potentiometer in the joystick:
  Analog_X = analogRead(Analog_X_pin);  
  //if the value is 25 "value away" from the average (midpoint), we allow the update of the speed
  //This is a sort of a filter for the inaccuracy of the reading
  if(abs(Analog_X-Analog_X_AVG)>50)
  {
  stepper.setSpeed(5*(Analog_X-Analog_X_AVG));    
  }
  else
  {
    stepper.setSpeed(0);
  }
}
void InitialValues()
{
  //Set the values to zero before averaging
  float tempX = 0;
  //----------------------------------------------------------------------------  
  //read the analog 50x, then calculate an average.
  //they will be the reference values
  for(int i = 0; i<50; i++)
  {
    tempX += analogRead(Analog_X_pin);  
    delay(10); //allowing a little time between two readings
  }
  //----------------------------------------------------------------------------  
  Analog_X_AVG = tempX/50;
  //----------------------------------------------------------------------------  
  Serial.print("AVG_X: ");
  Serial.println(Analog_X_AVG);
  Serial.println("Calibration finished");  
}

Robin2

You have put the code for the function checkEndStops() inside the code for the function readAnalaog() - that is not allowed. Each function must be separate. Like this

Code: [Select]
readAnalog() {
  // all the code for this function
} // end of the function

checkEndStops() {
   // all the code for this function
}



There may be other errors and if so please post the updated program and the error message.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

bob999

Thanks but this could go on for days correcting errors. I'll find another way

Robin2

Thanks but this could go on for days correcting errors. I'll find another way
I spent over an hour with a program problem the day before yesterday because I had incorrectly created a file with the name cyllinder.tpl and I had not thought to consider that the file name was wrong.

Programming takes perseverance.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up