millis, AccelSteppr, 2 servos, 2 steppers

I need a little help switching libraries from stepper.h to accelStepper.h

I need a little help switching from “delay()” to “MIllis()”

My code is below for my “accelSteppr and Millis” attempt. My code using the standard libraries worked fine, except I have to do each action in a sequence, so it ends up being relatively slow. I would like to implement milis() and accelStepper to combine actions of the components.

What I am trying to accomplish:

  1. actuate the Servos from 180 to 80

  2. hold for one second

  3. run 2 steppers (one rotates and the other drives linear) – one at 300 steps/minute and the other at 600 steps per minute (with an acceleration and deceleration). one will step 1000 steps, the other only 500 steps.

  4. power a relay to run a “dumb” motor (not shown in the current sketch).

  5. WAIT for 6 seconds. This time may be as little as 2 seconds or as much as 10, but that will be “hard written” in the code, not a sensor or other programming “function.” Basically just the MIllis() version of “delay(6000).”

  6. return the steppers AND servos to their original positions (servos can return at ANY time after Step #2, but I want to combine the action while )

  7. restart the loop to do everything again.

Right now in this sketch, my servos work fine, but my steppers are exceptionally slow and erratic - they seem to ONLY move 1-2 steps (over a 1-2 second period) then stop for a moment, then move 1-2 steps with no real pattern - always the same direction.
The stepper set-up works perfectly at the speeds I am asking - I even got it to “MoveTo(1000)” using accelStepper.h in a “test sketch” (and they run the examples fine), so I don’t have a "mechanical problem.

This is my stepper motors and drivers (with 10amp 24v power supply):

I am running an Arduino Nano.

It’s something in the coding and I just cannot crack it. After I wasted a whole day Saturday, I finally just decided to ask the Pros!

Here’s my code:

#include <AccelStepper.h>
#include <Servo.h>

AccelStepper stepper2(AccelStepper::DRIVER, 2, 3, 4);
AccelStepper stepper3(AccelStepper::DRIVER, 8, 9, 10);

Servo loaderServo1;
Servo loaderServo2;
unsigned long previousMillis = 0; 
unsigned long currentMillis;
const int loadDelay = 1000; 
const int drillDelay = 5000;


void setup()
{  
  loaderServo1.attach(7);
  loaderServo2.attach(6);
  loaderServo1.write(0);
  loaderServo2.write(0);
  delay(1000);
  loaderServo1.write(180);
  loaderServo2.write(180);
  
  stepper2.setMaxSpeed(600.0);
  stepper2.setAcceleration(100.0); 
       
  stepper3.setMaxSpeed(300.0);
  stepper3.setAcceleration(100.0);
   
}

void For() {
    stepper2.moveTo(1000);
    stepper3.moveTo(500);   
    stepper2.run();
    stepper3.run();
}

void Rev() {
    stepper2.moveTo(-1000);
    stepper3.moveTo(-500);   
    stepper2.run();
    stepper3.run();
}

void loadRod() {
 unsigned long currentMillis = millis(); 
 int interval = 1000; 
 if ((unsigned long)(currentMillis - previousMillis) >= interval) {
   previousMillis = currentMillis;
   loaderServo1.write(80);
   loaderServo2.write(80);

 }
 if ((unsigned long)(currentMillis - previousMillis) >= interval) {
  previousMillis = currentMillis;
  loaderServo1.write(180);
  loaderServo2.write(180);
  previousMillis = millis();
  
 } 
}


void loop()
{
  loadRod();
  currentMillis = millis();
    if (currentMillis - previousMillis >= loadDelay) {
      For();
      previousMillis = millis();
   }
 
   if (currentMillis - previousMillis >= drillDelay) {
      Rev();
      previousMillis = 0; 
   }
}

I can see several things wrong but I'm not clear about what you want to happen.

For example the lines

    stepper2.run();
    stepper3.run();

should be in loop() and not inside any conditional tests. The run() function MUST be called very frequently - at least a few times faster than the desired step rate. The AccelStepper library will stop automatically when the motor gets to its destination.

And this line is not needed in loadRod()

 unsigned long currentMillis = millis();

because you already have defined currentMillis at the top of the program and you update its value in loop()

And in loadRod() there is no need for (unsigned long) in this line

 if ((unsigned long)(currentMillis - previousMillis) >= interval) {

I wonder if you need separate variables for the "previousMillis" for different actions - perhaps one for the servos and one for the steppers?

...R

Robin,

originally, I was playing with this in accelStepper and it worked BY ITSELF

#include <AccelStepper.h>

AccelStepper stepper2(AccelStepper::DRIVER, 2, 3, 4);
AccelStepper stepper3(AccelStepper::DRIVER, 8, 9, 10);


void setup() {
stepper2.setMaxSpeed(600.0);
  stepper2.setAcceleration(100.0); 
       
  stepper3.setMaxSpeed(300.0);
  stepper3.setAcceleration(100.0);
}

void loop() {
    stepper2.moveTo(1000);
    stepper3.moveTo(500);   
    stepper2.run();
    stepper3.run();

]

I was trying to make a “function” out of the above stepper moves (and it’s inverse) so that my loop would look like this (this, obviously, did not work):

blah(blah); //all the above set-up criteria


void loop() {

For();
delay(6000);
Rev();
delay(1000);
}

… BUT quickly learned “delay” pretty-much kills accelStepper functions no matter where the “delay” is in the loop (and read tons of your posts telling us NOT to use “delay”!).

I WAS HOPING it would run the For() function like it did in the “loop()” by itself, then the “delay”, then the Rev(), then another “delay” - in a “4-part” sequence.

So, now I’m thinking I CANNOT do the For() or Rev() as “functions” since TECHNICALLY the …

stepper2.run();
stepper3.run();

…is not in the “loop()”

This is where I am stuck. I guess I don’t understand how to call the above “with timing.”

For(), Rev() and loadRod() all run by themselves in separate sketches. I just need to bring them together in a timed sequence.

now I’m thinking more on the lines of eliminating the For() and Rev() functions like this (Does this look viable?I won’t be able to test it until tonight):

blah(blah); //all the above set-up criteria

void loop()
{
  loadRod();

  currentMillis = millis();

    if (currentMillis - previousMillis >= loadDelay) {
      stepper2.moveTo(1000);
      stepper3.moveTo(500);   
      stepper2.run();
      stepper3.run();
      previousMillis = millis();
   }

   if (currentMillis - previousMillis >= drillDelay) {
      stepper2.moveTo(-1000);
      stepper3.moveTo(-500);   
      stepper2.run();
      stepper3.run();
      previousMillis = 0;
   }
}

Have you tried the changes I suggested?

If so, tell us what happened (in detail).

And post the complete revised program.

...R

Changes not made:
Using different variables for the servos and steppers: I’m gonna have to think about it’s impact on the whole sketch - it’s sounds logical, but once I do that, I’ll need to pass the millis() value out of the loadRod() function, I think.

Changes made:

As advised, I removed the 2 unnecessary parts of the loadRod() function having to do with “unsigned long”

re-wrote the Loop() and removed the For() and Rev() functions and just put in straight code

removed the the “previousMillis = Millis()” and “previousMillis = 0” statements from inside their respective “IF STATEMENTS” in the loop().

Here’s my code I tried tonight:

#include <AccelStepper.h>
#include <Servo.h>

AccelStepper stepper2(AccelStepper::DRIVER, 2, 3, 4);
AccelStepper stepper3(AccelStepper::DRIVER, 8, 9, 10);

Servo loaderServo1;
Servo loaderServo2;
unsigned long previousMillis = 0; 
unsigned long currentMillis;
const int loadDelay = 1000; 
const int drillDelay = 5000;


void setup()
{  
  loaderServo1.attach(7);
  loaderServo2.attach(6);
  loaderServo1.write(0);
  loaderServo2.write(0);
  delay(1000);
  loaderServo1.write(180);
  loaderServo2.write(180);
  
  stepper2.setMaxSpeed(600.0);
  stepper2.setAcceleration(100.0); 
       
  stepper3.setMaxSpeed(300.0);
  stepper3.setAcceleration(100.0);
   
}
void loadRod() {
  int interval = 1000; 
 if ((currentMillis - previousMillis) >= interval) {
   previousMillis = currentMillis;
   loaderServo1.write(80);
   loaderServo2.write(80);

 }
 if ((unsigned long)(currentMillis - previousMillis) >= interval) {
  previousMillis = currentMillis;
  loaderServo1.write(180);
  loaderServo2.write(180);
  previousMillis = millis();
  
 }
} 
void loop() {
    loadRod();
      
    currentMillis = millis();

    if (currentMillis - previousMillis >= loadDelay) {
      stepper2.moveTo(1000);
      stepper3.moveTo(500);   
      stepper2.run();
      stepper3.run();
    }
      previousMillis = millis();
      
    if (currentMillis - previousMillis >= drillDelay) {
      stepper2.moveTo(-1000);
      stepper3.moveTo(-500);   
      stepper2.run();
      stepper3.run();
   }
      previousMillis = 0;
}

Results:

loadRod() function did not run at all - almost like it was skipped (servos did actuate from the call in setup(), though).

Both STEPPERS moved in a “herky-jerky” manner forward, but did not move backward at all – they just oscillated in place and never moved again in either direction. Both motors seemed to be making 10-12 steps forward and 3-4 steps back and it was DEFINITELY NOT at 600 or 300 steps per second – to go 2-1/2 revolutions was like 20 seconds.

Servo2 moved 2-1/2 rotations, which is 500 steps, so it knows how far to go.
Servo3 moved 5 rotations, so it knows how far to go.

It is something in the millis() that is catching me, I think


Here is a video of the little contraption working with “stepper.h” and “delay” if it helps:

YES, I HAVE THESE KINDS OF “TOYS” JUST LAYING AROUND - LARGER GEARBOXES, TOO!

This will feed the rods into my X-carve which will clamp the rod, then put 2 holes in the end. Yes, I COULD just make a jig in a regular drill press and do this, but THIS IS MUCH MORE FUN – and since I have 200 of them to do (both ends, so 400 holes), i decided to automate the process.

Had it not been for “Covid”, I would not have had the time to do this. these are some kind of “sticks” my kid is using for some sorority fund-raising event once “Covid”" is over. The sticks you see are just some dowels and a cut broom-handle i’m practicing with…

I also need a way to justify to my wife all the time and energy I put into “Arduino.” LOL

Any Help is appreciated.

johnnycatt:
Changes made:

You do not seem to have taken account of my comments.

Go back to the program in your Original Post and apply the changes I suggested in Reply #1 and post the revised program and report how it behaves.

Programming problems need to be dealt with in a slow step-by-step manner. Firing a scatter-gun at a problem is rarely useful.

...R

Robin,
You are certainly on the right track (you got a venmo acct? I owe you a few $$ for the help so far!!!) - I think this is a “millis()” problem.

I cannot work on this problem DIRECTLY from home. My shop is about a mile away, but I CAN WORK WITH “similar-code.” I took my original problem and condensed it down to a Serial.println() sketch and started playing with the “variables” – AS YOU SUGGESTED. - easier for you to run, too.

I seem to need to add a variable to denote a start time and a stop time for each “process.” (originally, I was trying to put these “processes” into separate functions)

With this code (which can be put in place for my project), I’m trying to print “Go Home” just ONCE after 1000 milliseconds have elapsed, then write "I AM Home!’ just ONCE after 2 seconds have elapsed, then restart the loop.

I’m close, but not there yet.

Here’s the code:

unsigned long primaryPreviousMillis = 0;
unsigned long currentMillis;

int secondaryPreviousMillis = 1001;
int endLoopMillis = 2001;
int interval = 1000;
int nextInterval = 2001;

void setup() {
  Serial.begin(9600);
}

void loop() {
  currentMillis = millis();
  int x = (currentMillis - primaryPreviousMillis);
  int y = (currentMillis - secondaryPreviousMillis);
  
   if ((x >= interval) && (x <= secondaryPreviousMillis)) {
     primaryPreviousMillis = currentMillis;
     Serial.println("go home!");
   }
   
   if ((y >= nextInterval) && (y <= endLoopMillis)) {
     secondaryPreviousMillis = currentMillis;
     Serial.println("I AM home!");
     secondaryPreviousMillis = currentMillis;
   }
 
}

johnnycatt:
Here's the code:

All variables associated with millis() must be defined as unsigned long.

Please put your code to one side for a few moments and write down in English the sequence of events that you want to happen.

...R

PS ... payment is not needed. I do this as a hobby.

Robin,

The events I wish to happen in this order:

  1. actuate the Servos from 180 to 80

  2. hold for one second

  3. run the 2 steppers (one rotates and the other drives linear) – one at 300 steps/minute and the other at 600 steps per minute. One motor will step only 1000 steps, the other only 500 steps; both moving AT THE SAME TIME. (optional: acceleration and deceleration)

  4. Activate a relay to run a “dumb” motor (NOT IN THE SKETCH, YET - this will actually trigger my X-carve which will be running a “manual” program loaded into it’s arduino).

  5. WAIT for 6 seconds for the drill operation to complete. This time may be as little as 2 seconds or as much as 10, but that will be “hard written” in THIS code, not a sensor or other programming “function.” Basically, I just want the MIllis() version of “delay(6000).”

  6. return the steppers AND servos to their original positions (servos can return at ANY time after Step #2, but I want to combine the action with the steppers to save time)

  7. restart the loop to do everything again.

Here’s my updated Stepper code with the 'unsigned long" rather than “int”

#include <AccelStepper.h>
#include <Servo.h>

AccelStepper stepper2(AccelStepper::DRIVER, 2, 3, 4);
AccelStepper stepper3(AccelStepper::DRIVER, 8, 9, 10);

Servo loaderServo1;
Servo loaderServo2;

unsigned long currentMillis;
unsigned long LoadpreviousMillis = 0;
unsigned long primaryPreviousMillis = 0;
unsigned long secondaryPreviousMillis = 1001;
unsigned long endLoopMillis = 2001;
unsigned long interval = 1000;
unsigned long nextInterval = 2001;
int relay = 13;

void setup()
{ 
  loaderServo1.attach(7);
  loaderServo2.attach(6);
 
  stepper2.setMaxSpeed(600.0);
  stepper2.setAcceleration(100.0);
       
  stepper3.setMaxSpeed(300.0);
  stepper3.setAcceleration(100.0);
  pinMode(relay, OUTPUT);
   
}
void loadRod() {
  unsigned long z = (currentMillis - LoadpreviousMillis);
  int loadInterval = 1000;
 if ((z < loadInterval) && (z >= 0)) {
   LoadpreviousMillis = currentMillis;
   loaderServo1.write(80);
   loaderServo2.write(80);

 }
 if (z >= loadInterval) {
  LoadpreviousMillis = currentMillis;
  loaderServo1.write(180);
  loaderServo2.write(180);
  LoadpreviousMillis = millis();
 
 }
}

void drill() {
  digitalWrite(relay, HIGH);
  delay(500);
  digitalWrite(relay, LOW);
}

void loop() {
    loadRod();
     
    currentMillis = millis();
    unsigned long x = (currentMillis - primaryPreviousMillis);
    unsigned long y = (currentMillis - secondaryPreviousMillis);
  
   if ((x >= interval) && (x <= secondaryPreviousMillis)) {
     primaryPreviousMillis = currentMillis;
      stepper2.moveTo(1000);
      stepper3.moveTo(500);   
      stepper2.run();
      stepper3.run();
    }
      if ((y >= nextInterval) && (y <= endLoopMillis)) {
     secondaryPreviousMillis = currentMillis;
      stepper2.moveTo(-1000);
      stepper3.moveTo(-500);   
      stepper2.run();
      stepper3.run();
      secondaryPreviousMillis = currentMillis;
   }
 
}

Let's stick with the description for the moment.

In Item 3 is it necessary for motor1 to do 1000 steps in exactly the same time as motor2 moves 500 steps? OR would it be OK for one motor to finish first? If they both need to stop at the same time the AccelStepper library is not suitable but the MultiStepper version would be suitable, however it does not do acceleration. If you need acceleration then you will need to write your own code which is not that difficult.

Is the action in Item 4 to start when the steppers start, or only after the steppers finish?

You mention a drill in Item 5. Is that the "dumb motor" you refer to in Item 4?

...R

Robin..

In Step 3, YES, one motor can finish first.

When the last stepper has finished it's move in Step #3, I will be starting the drill's actions wiht a signal to teh arduino of the X-carve (step #4), which will take approx 6 seconds to complete - hence the need for the "delay" of step #5 so the drill can finish it's 2 holes.

After step #5, the "carriage" backs-out, discharges and re-load (step #6).

Step 6 may have to be spit into 2 parts, but once I nail-down the method, I can break this "Rube Goldburg" machine into 1,000 steps, if needed.

Honestly , this is just a project of using millis() as a timer with the acellStepper library - i"m just wondering if it's possible - or maybe I'm using the wrong methods/libraries.

I had posted a video, of it running with the "stepper.h" library and using "delay." That works fine except the steppers don't move at the same time (which greatly slows the process) - this is really just become a "grudge" to figure it out - I CAN do it with the regular libraries, but it seems to me there NEEDS to be a "example" for "timing multiple steppers" and once I finish this, I want to submit it as a possible addition to the acellstepper example list. (Actually, I need to credit you if I do - you got me over the first hurdle - that alone is worthy of credit)

johnnycatt:
I had posted a video, of it running with the "stepper.h" library and using "delay." That works fine except the steppers don't move at the same time (which greatly slows the process) - this is really just become a "grudge" to figure it out

From your description of the project it does seem that delay() can have a place because actions happen in succession.

If the only issue is to get the two steppers to move at the same time (so as not to waste time) then that can probably be achieved with a small variation on the code that has them working one after the other. Please post that working program so I can see what might be the minimum needed to satisfy your requirement - now that I know the requirement clearly.

...R

Robin,

This is a bit messy… I forgot that I didn’t use the “stepper.h” library in my original sketch. I did have it running that way, but it was in my “testing sketch” which is now overwritten with the “accelStepper.h” sketch.

I kept this original just in case I needed it, but that’s it… I usually do a better job of keeping old sketches - sorry.

My setup() loads the first rod, so loadRod() is actually listed towards the end in the sequence inside loop().

#include <Servo.h>

Servo loaderServo1;
Servo loaderServo2;

int PulPinLinear = 2;
int DirPinLinear = 3;
int enblPinLinear = 4;

int PulPinRotate = 8;
int DirPinRotate = 9;
int enblPinRotate = 10;

int drillerEngage = 13;

int rotSpeed = 4;             //higher numbers are slower - sets "delay" between steps
int linSpeed = 1;             //higher numbers are slower - sets "delay" between steps
int loaderDelay = 1000;

void setup() {

  loaderServo1.attach(7);
  loaderServo2.attach(6);

  loaderServo1.write(80);
  loaderServo2.write(80);
  delay(1000);
  loaderServo1.write(180);
  loaderServo2.write(180);
   
  pinMode(PulPinLinear, OUTPUT);
  pinMode(DirPinLinear, OUTPUT);
  pinMode(enblPinLinear, OUTPUT);
  
  pinMode(PulPinRotate, OUTPUT);
  pinMode(DirPinRotate, OUTPUT);
  pinMode(enblPinRotate, OUTPUT);
  
  pinMode(drillerEngage, OUTPUT);
   
  digitalWrite(PulPinLinear, LOW);
  digitalWrite(enblPinLinear, LOW);
  digitalWrite(DirPinLinear, LOW);
  
  digitalWrite(PulPinRotate, LOW);
  digitalWrite(enblPinRotate, LOW);
  digitalWrite(DirPinRotate, LOW);
  
  digitalWrite(drillerEngage, LOW);
  
  digitalWrite(enblPinLinear, HIGH);
  digitalWrite(enblPinRotate, HIGH);
  delay(100);
  
  digitalWrite(enblPinLinear, LOW);
  digitalWrite(enblPinRotate, LOW);
  delay(100);
  
}

void loop() {

//setup() actually loads the 1st rod, so loadRod() is at the end of loop()
  
  linearIn();
  digitalWrite(drillerEngage, HIGH);
  delay(6000);
  digitalWrite(drillerEngage, LOW);
  linearOut();
  rotate();
  loadRod();
  delay(loaderDelay);
  rotate();
}

void linearIn() {
  digitalWrite(DirPinLinear, HIGH);
  delay(10); 
  for(int i=0; i<=1000; i++) {
  digitalWrite(PulPinLinear, HIGH);
  digitalWrite(drillerEngage, HIGH);
  digitalWrite(PulPinLinear, LOW);
  digitalWrite(drillerEngage, LOW);
  delay(linSpeed);
  }
}

void linearOut() {
  digitalWrite(DirPinLinear, LOW);
  delay(10);
  for(int i=0; i<=1000; i++) {
  digitalWrite(PulPinLinear, HIGH);
  digitalWrite(drillerEngage, HIGH);
  digitalWrite(PulPinLinear, LOW);
  digitalWrite(drillerEngage, LOW);
  delay(linSpeed);
  }
}
  
void rotate() {
  digitalWrite(DirPinRotate, HIGH);
  delay(10); 
  for(int i=0; i<=500; i++) {
  digitalWrite(PulPinRotate, HIGH);
  digitalWrite(drillerEngage, HIGH);
  digitalWrite(PulPinRotate, LOW);
  digitalWrite(drillerEngage, LOW);
  delay(rotSpeed);
  }
  delay(1000);
} 

void loadRod() {
  loaderServo1.write(80);
  loaderServo2.write(80);
  delay(1000);
  loaderServo1.write(180);
  loaderServo2.write(180);
  
}

johnnycatt:
I kept this original just in case I needed it, but that's it..

Does this program behave in the way you said in Reply #10 " That works fine except the steppers don't move at the same time (which greatly slows the process)" ?

...R

Robin,
After reviewing my code, I inadvertently had the DrillerEngage pin turning on and off in the functions: linearIn(), LinearOut(), and rotate() - I’m not sure why I put that code in there, but I removed it below.

Also, I noticed when I ran the sketch that Rotate() should be called in the beginning of the loop(), not at the end – as far as the loop() sequence is concerned, it will “loop” exactly the same, but now the carriage will pick up the first rod that is loaded by the setup() function.

TBH, the linearIn() and linearOut() need to be around 6000 steps not 1000 and the rotate() needs to be 600 steps not 500, but BOTH of those distances have yet to be determined. I changed them in my original post to make them “simple numbers” to remember - they are not the focus; once I have “the process,” they will just be just “variables.” Moments ago, I ran this exact code (below) on the contraption and it did exactly what I wanted it to do – EXCEPT THE STEPPERS DIDN’T MOVE AT THE SAME TIME. They can’t without the use of the accellStepper.h library.

Here’s the code. I cut this right out of the IDE after testing the code on the contraption.

#include <Servo.h>

Servo loaderServo1;
Servo loaderServo2;

int PulPinLinear = 2;
int DirPinLinear = 3;
int enblPinLinear = 4;

int PulPinRotate = 8;
int DirPinRotate = 9;
int enblPinRotate = 10;

int drillerEngage = 13;

int rotSpeed = 4;             //higher numbers are slower - sets "delay" between steps
int linSpeed = 1;             //higher numbers are slower - sets "delay" between steps
int loaderDelay = 1000;

void setup() {

  loaderServo1.attach(7);
  loaderServo2.attach(6);

  loaderServo1.write(80);
  loaderServo2.write(80);
  delay(1000);
  loaderServo1.write(180);
  loaderServo2.write(180);
  delay(1000);
   
  pinMode(PulPinLinear, OUTPUT);
  pinMode(DirPinLinear, OUTPUT);
  pinMode(enblPinLinear, OUTPUT);
 
  pinMode(PulPinRotate, OUTPUT);
  pinMode(DirPinRotate, OUTPUT);
  pinMode(enblPinRotate, OUTPUT);
 
  pinMode(drillerEngage, OUTPUT);
   
  digitalWrite(PulPinLinear, LOW);
  digitalWrite(enblPinLinear, LOW);
  digitalWrite(DirPinLinear, LOW);
 
  digitalWrite(PulPinRotate, LOW);
  digitalWrite(enblPinRotate, LOW);
  digitalWrite(DirPinRotate, LOW);
 
  digitalWrite(drillerEngage, LOW);
 
  digitalWrite(enblPinLinear, HIGH);
  digitalWrite(enblPinRotate, HIGH);
  delay(100);
 
  digitalWrite(enblPinLinear, LOW);
  digitalWrite(enblPinRotate, LOW);
  delay(100);
 
}

void loop() {

//setup() actually loads the 1st rod, so loadRod() is at the end of loop()

  rotate();
  linearIn();
  digitalWrite(drillerEngage, HIGH);
  delay(6000);
  digitalWrite(drillerEngage, LOW);
  linearOut();
  rotate();
  loadRod();
  delay(loaderDelay);
}

void linearIn() {
  digitalWrite(DirPinLinear, HIGH);
  delay(10);
  for(int i=0; i<=1000; i++) {
  digitalWrite(PulPinLinear, HIGH);
  digitalWrite(PulPinLinear, LOW);
  delay(linSpeed);
  }
}

void linearOut() {
  digitalWrite(DirPinLinear, LOW);
  delay(10);
  for(int i=0; i<=1000; i++) {
  digitalWrite(PulPinLinear, HIGH);
  digitalWrite(PulPinLinear, LOW);
  delay(linSpeed);
  }
}
 
void rotate() {
  digitalWrite(DirPinRotate, HIGH);
  delay(10);
  for(int i=0; i<=500; i++) {
  digitalWrite(PulPinRotate, HIGH);
  digitalWrite(PulPinRotate, LOW);
  delay(rotSpeed);
  }
  delay(1000);
}

void loadRod() {
  loaderServo1.write(80);
  loaderServo2.write(80);
  delay(1000);
  loaderServo1.write(180);
  loaderServo2.write(180);
 
}

You need to create a single function that does the combined work of linearXXX() and rotate(). I think this should work, but I have not tested it

void twoSteppers(char direction) {
    if (direction == 'I') {
        digitalWrite(DirPinLinear, HIGH);
    }
    else {
        digitalWrite(DirPinLinear, LOW);
    }
    int numLinearSteps = 0;
    for(int n=0; n<=2000; n++) {
        if (numLinearSteps < 1000) {  // stops when count gets to 1000
            digitalWrite(PulPinLinear, HIGH);
            digitalWrite(PulPinLinear, LOW);
            numLinearSteps ++;
        }
        if (n % 4 == 0) {  // every 4th count - once very 4 millisecs
            digitalWrite(PulPinRotate, HIGH);
            digitalWrite(PulPinRotate, LOW);
        }
        delay(linSpeed);
    }
}

In your program in Reply #14 you call your functions like this

void loop() {

//setup() actually loads the 1st rod, so loadRod() is at the end of loop()

  rotate();
  linearIn();

With my function that would change to

void loop() {

  twoSteppers('I'); // 'I' for in and 'O' for out

…R

Looks Good, pal!

Pretty cute trick with the "%" :slight_smile: ! I'll leave for work a little early, drop by my shop, give it a quick go and update you!

thanks!

hey Robin,

It works great. Need to tweek the steps to get them right, but I knew i'd have to do that, no matter what and that is just "trial and error."

"The Process" is now correct.

Again, THANKS for the help!!!!