Stepper Return To Home (Limit Switch) on Start Up

Evening,

For the last month I have been trying to learn the basics of C++, I can now do basic things but I'm still struggling with my project.

I am using a Mega 2560 with a A4988 Driver and a Nema 17 driving a lead screw to control a nozzle.

I have copied the code from a guide and slowed it down and reduced the amount of steps moved when the button is pressed as my project only requires it to turn 270 deg.

I would like the stepper to move back slowly to the home switch when turned on -

I have tried writing an if function in the setup but I don't seem to be having much luck, would anyone be able to help me out.

Here is the original code which I copied.

#define DISTANCE 100

int StepCounter = 0;
int Stepping = false;

void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);

  pinMode(2, INPUT);
  pinMode(3, INPUT);
}

void loop() {
  if (digitalRead(3) == LOW && Stepping == false)
  {
    digitalWrite(8, LOW);
    Stepping = true;
  }
  if (digitalRead(2) == LOW && Stepping == false)
  {
    digitalWrite(8, HIGH);
    Stepping = true;
  }

  if (Stepping == true)
  {
    digitalWrite(9, HIGH);
    delayMicroseconds(50);
    digitalWrite(9, LOW);
    delayMicroseconds(50);

    StepCounter = StepCounter + 1;

    if (StepCounter == DISTANCE)
    {
      StepCounter = 0;
      Stepping = false;
    }
  }
}

Limit switch is wired to pin 4 if anyone is feeling kind enough to write it for me :wink: cheers guys.

I have tried writing an if function

If can not be used as a function name. An if statement...

but I don't seem to be having much luck

Winning the lottery is a matter of luck. Programming is not a matter of luck.

Limit switch is wired to pin 4

One leg is, anyway. Where is the other leg connected?

Post the code that you tried. Explain what it actually does, and how that differs from what you want.

You should first learn to wire and read a button or switch. Example.

electro-jerry:
I would like the stepper to move back slowly to the home switch when turned on -

That is a very common requirement.

If you can be CERTAIN that the motor is always to right (say) of the limit switch then you need something like this in setup()

limitSwitchState = digitalRead(limitSwitchPin);
while (limitSwitchState == HIGH) {    // assumes LOW when pressed
   // code to move one step to the left
   limitSwitchState = digitalRead(limitSwitchPin);
   delay(timeBetweenSteps);
}

...R

then you need something like this in setup()

In the while loop, you need to make the stepper step, too - one step per iteration of the while loop. Make sure that it steps toward the limit switch.

PaulS:
In the while loop, you need to make the stepper step, too

Agreed - I have a comment in my pseudo-code as a substitute for whatever code the OP uses to cause a step to happen

...R

It works!!!! thank you so much Robin2

Is there a simple way which I could integrate a revolution limit into this code?

I need it to not be able to move behind the limit switch and only move forward from the limit switch by 1 revolution.

It seems to move faster during the homing loop than it does under the switch, not a problem just curious why?

#define DISTANCE 1


int StepCounter = 0;
int Stepping = false;
int limitSwitch = 4;

void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);

  pinMode(2, INPUT); // move down and open nozzle
  pinMode(3, INPUT); // move up and close nozzle
  pinMode(limitSwitch, INPUT); //return home switch

  Serial.begin(9600);

  //While statment/return to home function contributed by (Robin2, 2017) via arduino forum 

  limitSwitch = digitalRead(4);

  while (limitSwitch == HIGH) {

    digitalWrite(9, HIGH);
    delayMicroseconds(500);
    digitalWrite(9, LOW);
    delayMicroseconds(500);

    limitSwitch = digitalRead(4);

    delayMicroseconds(500);
  }
  
}

void loop() {

  int buttonState = digitalRead(limitSwitch);

  Serial.println(buttonState);
 
  if (digitalRead(3) == LOW && Stepping == false)
  {
    digitalWrite(8, LOW);
    Stepping = true;
  }
  if (digitalRead(2) == LOW && Stepping == false)
  {
    digitalWrite(8, HIGH);
    Stepping = true;
  }

  if (Stepping == true)
  {
    digitalWrite(9, HIGH);
    delayMicroseconds(500);
    digitalWrite(9, LOW);
    delayMicroseconds(500);

    StepCounter = StepCounter + 1;

    if (StepCounter == DISTANCE)
    {
      StepCounter = 0;
      Stepping = false;
    }
  }
}

electro-jerry:
It seems to move faster during the homing loop than it does under the switch, not a problem just curious why?

Perhaps because of the time taken to execute the other lines of code in loop(). If you use the non-blocking code as illustrated in the second example in this Simple Stepper Code it will allow for the time taken on other activities.

You don't need Line 33

I need it to not be able to move behind the limit switch and only move forward from the limit switch by 1 revolution.

There are two issues here and I don't think I understand what you have in mind for either of them.

How (or when) does it move behind the switch?

If you want to limit how far the motor moves just keep count of the steps and stop when you get to the max.

...R

The project is to control a nozzle for a display which the public will be able to control via the buttons. As as we know the public like to break things.

To reach the full movement I only require 1 revolution of the lead screw away from the home switch.

electro-jerry:
The project is to control a nozzle for a display which the public will be able to control via the buttons. As as we know the public like to break things.

I understand that problem.

But how does your program allow anyone to move the motor out of range? In what circumstances can that happen? For example can someone manually move the motor to the wrong place?

The normal way to control a stepper motor is to establish the zero position at startup (you are doing that) and then keep count of the position as each step is taken and only allow it to move from (say) 0 to 200 steps.

if something can interfere with the motion so that the motor misses steps then, of course, the counting becomes meaningless.

...R

sorry, it wont be missing steps it just has the possibility for people to hold the button down and wind it to the end of the lead screw.

limiting to a given number of steps would be practical.

electro-jerry:
has the possibility for people to hold the button down and wind it to the end of the lead screw.

limiting to a given number of steps would be practical.

Something as simple as this would probably be suitable

if (stepCount > stepMax) {
  stepCount = stepMax;
}
if (stepCount < stepMin) {
  stepCount = stepMin;
}

...R

it just has the possibility for people to hold the button down and wind it to the end of the lead screw.

That is what limit switches are for.

Sorry for the delayed reply, i am unsure how I initialise these statements, should they be located before each 'if' statement?

electro-jerry:
Sorry for the delayed reply, i am unsure how I initialise these statements, should they be located before each 'if' statement?

It will be easier to understand what is in your mind if you make an attempt to include them in your code and then post the latest version of your program.

I'm not even sure what you mean by "these statements"

...R

Sorry I really struggle to know the correct words to describe code related problems.

I have added

int stepCount;
int stepMin = 0;
int stepMax = 3000;

at the start before the set up.

and then added

if (stepCount > stepMax) 
    {
 stepCount = stepMax;
    }

 if (stepCount < stepMin) 
    {
 stepCount = stepMin;
    }

at the end of the loop function. The sketch compiles but does not work as intended.

The aim would be that when switch is held down or pressed lots of times it will not exceed 3200 steps/ 360 degrees.

The full code showing the locations of this is also included below.

//Code adapted from stepper control guide !!!

#define DISTANCE 50


int StepCounter = 0;
int Stepping = false;
int limitSwitch = 4;

int stepCount;
int stepMin = 0;
int stepMax = 3200;


void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);

  pinMode(2, INPUT);           // move down and open nozzle
  pinMode(3, INPUT);           // move up and close nozzle
  pinMode(limitSwitch, INPUT); //return home switch

  Serial.begin(9600);          //Used during construction to confirm the function of the switch
 
 /*While statment/return to home function contributed 
    by (Robin2, 2017) via arduino forum*/

  limitSwitch = digitalRead(4);

  while (limitSwitch == HIGH) 
   {

    digitalWrite(9, HIGH);
    delayMicroseconds(500);
    digitalWrite(9, LOW);
    delayMicroseconds(500);

    limitSwitch = digitalRead(4);

    delayMicroseconds(500);
   }
              }

void loop() {

  int buttonState = digitalRead(limitSwitch);

  Serial.println(buttonState); //Used during construction to confirm the function of the switch
 
   /*when switch state is changed motor moves 
    anti clockwise by  the 'defined' distance*/

  if (digitalRead(3) == LOW && Stepping == false) 
   {
    digitalWrite(8, LOW);
    Stepping = true;
   }

   /*when button state is changed motor moves 
    clockwise by  the 'defined' distance*/

  if (digitalRead(2) == LOW && Stepping == false)
   {
    digitalWrite(8, HIGH);
    Stepping = true;
   }

  /*This defines the speed at which the steps are taken in 
     microseconds, e.g. 0.0005 seconds between each step */

  if (Stepping == true)
   {
    digitalWrite(9, HIGH);
    delayMicroseconds(500);
    digitalWrite(9, LOW);
    delayMicroseconds(500);

    StepCounter = StepCounter + 1;

    if (StepCounter == DISTANCE)
     {
      StepCounter = 0;
      Stepping = false;
     }
   }

  if (stepCount > stepMax) 
     {
  stepCount = stepMax;
     }

  if (stepCount < stepMin) 
     {
  stepCount = stepMin;
     }

            }

Thanks Robin2 for your patience and help.

You already have a variable called stepCounter in your program - what are you using that for?

I note, for example, that you set it back to 0 when the motor reaches the "DISTANCE". Why are you doing that? It seems to me that it would allow the motor to move in the same direction by another "DISTANCE" - wouldn't that be too far?

And, because I don't know what you are using stepCounter for I cannot say whether that is the variable you should be using in the piece of code I suggested.

You should not treat what I suggest as the exact final code to use. It was just intended to put an idea in your head so you could build the idea into your own code.

...R

Im not 100% on how the code step counter works. As I understand it is used to count how many steps are moved each time the button is pressed.

As you can see from the image if the stepper continued to move it would destroy the mechanism.

Do you have limit switches at both ends of the travel ? If not, then why not ?

I have only included a limit switch at the bottom, this allow the stepper to know its home position. Once the home position is confirmed I had assumed the upper limit could be controlled by counting the number of steps.