Limit switch(es) for stepper

Hi,

I have managed to get my NEMA 17 motor running via my Uno and 3 Axis shield with A4988. The project will eventually control 3 steppers, all running with the same settings, slowly turning at about 15RPM, which is output to drive shaft via 5:1 reduction, thus final output is approx 3 rpm. For now I'm just working with one, to tyr and get the settings correct.

The aim is to drive a nut along a 1M shaft, m8x1mm ,travelling approximately 900mm, then reversing back to home and repeating, 24/7. If I can figure out the number of steps to move 900mm, which I think I can...
[3rpm*(900mm*200step/rpm) =18,000]*5 for reduction = 90,000 steps??? (90,000 seems to be the maximium permitted or the motor just does nothing)?) then I believe I will only require one limit switch, with the nut (which is pulling an assembly along a track) homing, before beginning the continuous cycle. I attached my animation of how it operates.

The other option is to use two switches at each end of travel... My issue is I am having trouble getting a limit switch to reverse the motor when its running. Is the some code I need?

Here is what I have so far:
#define EN 8

//Direction pin
#define X_DIR 5

//Step pin
#define X_STP 2

//A498
int delayTime = 90000;
int stps=90000;

void step(boolean dir, byte dirPin, byte stepperPin, int steps)
{
digitalWrite(dirPin, dir);
delay(100);
for (int i = 0; i< steps; i++)
{
digitalWrite(stepperPin, HIGH);
delayMicroseconds(delayTime);
digitalWrite(stepperPin, LOW);
delayMicroseconds(delayTime);
}
}

void setup()
{
pinMode(X_DIR, OUTPUT); pinMode(X_STP,OUTPUT);
pinMode(EN, OUTPUT);
digitalWrite(EN,LOW);
}
void loop()
{
step(false, X_DIR, X_STP, stps);
delay(1000);
step(true, X_DIR, X_STP, stps);
delay(1000);
}

This drives the output shaft CW for about 20mins before pausing, and then continuing CW instead of reversing to CCW which seems odd... The reversing action was working when the step/delay numbers were much smaller...

If any of this babble makes any sense, then a little assistance would be great

The only reasons I can think of that you'd need the far limit switch are
A) to ensure the motor actually reached the end of travel (and hadn't stalled or otherwise lost steps on the way),
B) to be able to change the end position mechanically, i.e. without having to alter program parameters,
C) to prevent damage if you had a runaway situation during testing, or
D) if by some odd (and usually unlikely) means (maybe electrical noise?) you have gained steps, and are going too far.

If you can eliminate these, then forget the far limit switch - you don't need it.

OP's code in code tags - see How to get the best out of the Forum

#define EN 8

//Direction pin
#define X_DIR 5

//Step pin
#define X_STP 2

//A498
int delayTime = 90000;
int stps=90000;

void step(boolean dir, byte dirPin, byte stepperPin, int steps)
{
    digitalWrite(dirPin, dir);
    delay(100);
    for (int i = 0; i< steps; i++)
    {
        digitalWrite(stepperPin, HIGH);
        delayMicroseconds(delayTime);
        digitalWrite(stepperPin, LOW);
        delayMicroseconds(delayTime);
    }
}

void setup()
{
    pinMode(X_DIR, OUTPUT); pinMode(X_STP,OUTPUT);
    pinMode(EN, OUTPUT);
    digitalWrite(EN,LOW);
}
void loop()
{
    step(false, X_DIR, X_STP, stps);
    delay(1000);
    step(true, X_DIR, X_STP, stps);
    delay(1000);
}

I suggest you start with a program that just takes 10 or 20 seconds to work - so that it becomes practical to debug it before your pension arrives.

If it was my project I would make the direction more explicit (and easier for my brain) though it would mean more code - for example

step('F', X_DIR, X_STP, stps); // F for forward, R for reverse

and, in the step() function

void step(char dir, byte dirPin, byte stepperPin, int steps)
{
   if (dir == 'F') {
       digitalWrite(dirPin, LOW);
   }
   else {
       digitalWrite(dirPin, HIGH);
  }
  // etc

...R

Edit 03 Dec 2020 to make it clear that I am using 'F' for forward

When my pension arrives haha, thats not so far off by the way :smiley:

Thanks for your response, I'll look at the code in a bit... meanwhile, I wondered can you answer this...

I have been running it faster, however, this is part of my bug... The motor will rotate, pause and reverse as desired with faster settings, but continues in same direction at full (slow) speed. Furthermore, I can only make the motor rotate for approx 6:40mins at full speed before it pauses and continues. I need this to be around 30 minutes!

The largest number of steps I seem to be able to enter is 90,000 (I tried over 100k, and 99,999 but the motor does nothing)

johndg:
The only reasons I can think of that you'd need the far limit switch are
A) to ensure the motor actually reached the end of travel (and hadn't stalled or otherwise lost steps on the way),
B) to be able to change the end position mechanically, i.e. without having to alter program parameters,
C) to prevent damage if you had a runaway situation during testing, or
D) if by some odd (and usually unlikely) means (maybe electrical noise?) you have gained steps, and are going too far.

If you can eliminate these, then forget the far limit switch - you don't need it.

Yes, I would much prefer to eliminate the far limit switch if possible. I don't see why not, although there seems to be some issue with the maximum number of steps I can enter, and also the slowest speed, as when I get too slow the motor makes far to of a "grinding" sound, though functions correctly

AxeGrinder:
... there seems to be some issue with the maximum number of steps I can enter, and also the slowest speed ...

Make sure the number types you are using are big enough to hold the values.

@ johndg has put his finger on the problem.

In your program you have these definitions

int delayTime = 90000;
int stps=90000;

The largest value you can have in an int is 32767. You need to use a long, or, if you don't need negative numbers an unsigned long

unsigned long delayTime = 90000;
unsigned long stps=90000;

...R

I managed to get this working from Robin2's code which is far simpler and a little easier to understand, thankyou...

However, no matter what values I enter into "int stps" I think my pension will arrive before the motor decides to change direction. It now just rotates continuously without pause in one direction. It's interesting that the speed is less effected by "int delaytime" than it is by dabbling with the delay values at

step('F', X_DIR, X_STP, stps);
    delay(5);
    step('T', X_DIR, X_STP, stps);
    delay(5);

Anyideas why this is happening?

#define EN 8

//Direction pin
#define X_DIR 5

//Step pin
#define X_STP 2

//A498
int delayTime = 1;
int stps = 200;

void step(char dir, byte dirPin, byte stepperPin, int steps)
{
   if (dir == 'F') {
       digitalWrite(dirPin, HIGH);
   }
   else {
       digitalWrite(dirPin, LOW);
  }
  // etc
    {
        digitalWrite(stepperPin, LOW);
        delayMicroseconds(delayTime);
        digitalWrite(stepperPin, HIGH);
        delayMicroseconds(delayTime);
    }
 //   delay 3000;
}

void setup()
{
    pinMode(X_DIR, OUTPUT); pinMode(X_STP,OUTPUT);
    pinMode(EN, OUTPUT);
    digitalWrite(EN,LOW);
}
void loop()
{
    step('F', X_DIR, X_STP, stps);
    delay(5);
    step('T', X_DIR, X_STP, stps);
    delay(5);
}

The real problem is that you have omitted the FOR loop in your revised step() function.

When I put "// etc" in my code I intended you to replace that with the rest of the code you already had in step()

Also I suggest you put a much larger delay() between the direction changes. delay(5); is only 5 millisecs and you would not notice it. Try delay(5000);

...R

I did notice the //etc but forgot to address it, apologies for my newbiness! Yep, I've tried lots of delay settings and have a good feel for it now. At least my output shaft is running very nice and quiet at it's desired 3rpm, which is a big improvement from the earlier rumble :slight_smile:

cheers!

I think a delay time of 1 microsec between step pin low and step pin high (as per the code in #7) is a bit tight, and unnecessarily so. Admittedly, the overheads of digitalWrite() and delayMicroseconds() will add loads, but I can't find a proper spec for the PCB, so heaven knows what delays there may be on that.
@AxeGrinder, make it at least 5 microsec - you've got all day!

This is from the Allegro datasheet for the A4988:

Thanks, I shall try to absorb that. At present, my timings are set for "debugging" but when running at actual speeds I found that the reduction gear is not a true 5:1, something a little less like 4.7:1 or something, so at least I found the correct number of steps for a complete rotation of the shaft which was confusing me. All sorted now, 890 steps per rev!

OK... now I'm befuddled.... I cam up with this, but still can't make the motor change direction! (It's a lot easier without a shield!)

#define EN 8

//Direction pin
#define X_DIR 5

//Step pin
#define X_STP 2

//A4988
int delayTime = 1000;
int stps = 890;

void step(char dir, byte dirPin, byte stepperPin, int steps)
{
  if (dir == 'F') {
    digitalWrite(dirPin, LOW);
  }
  else {
    digitalWrite(dirPin, HIGH);
  }
  {
    digitalWrite(stepperPin, LOW);
    delayMicroseconds(delayTime);
    digitalWrite(stepperPin, HIGH);
    delayMicroseconds(delayTime);
  }

  {
    digitalWrite(dirPin, dir);
    delay(100);
    for (int i = 0; i < stps; i++)
    {
      digitalWrite(stepperPin, LOW);
      delayMicroseconds(delayTime);
      digitalWrite(stepperPin, HIGH);
      delayMicroseconds(delayTime);
    }
  }

}

void setup()
{
  pinMode(X_DIR, OUTPUT); pinMode(X_STP, OUTPUT);
  pinMode(EN, OUTPUT);
  digitalWrite(EN, LOW);
}
void loop () 
{
  step(false, X_DIR, X_STP, stps);
  delay(1000);
  step(true, X_DIR, X_STP, stps);
  delay(3000);
}

Not sure where to go now??? I've tried all kinds of things but code wont compile or direction remains constant

 {
    digitalWrite(dirPin, dir);

Did you mean that? It's writing 'F' or another character to the pin!

This is odd:

  step(false, X_DIR, X_STP, stps);

step tests for an 'F' but you're passing it false.

wildbill:
This is odd:

  step(false, X_DIR, X_STP, stps);

step tests for an 'F' but you're passing it false.

I've probably got confused messing with values to try and reverse the motor... perhaps if I just swith true/false labels?

johndg:

 {

digitalWrite(dirPin, dir);




Did you mean that? It's writing 'F' or another character to the pin!

TBH. I don't know what I meant, I'm just befuddled now!

AxeGrinder:
I've probably got confused messing with values to try and reverse the motor... perhaps if I just swith true/false labels?

No, pass an 'F' to one of the calls to step. And get rid of the line johndg pointed out.

AxeGrinder:
TBH. I don't know what I meant, I'm just befuddled now!

Look back at the code I suggested in Reply #2 - is yours the same?

...R

wildbill:
No, pass an 'F' to one of the calls to step. And get rid of the line johndg pointed out.

I may pass a Fart before I know exactly what that means?