Small stepper+Accelstepper- Q.1) rotation speed, Q.2 [solved]) absolute position

Dear all,
I am a newbie who followed the exhaustive tutorial available at http://arduino-info.wikispaces.com/SmallSteppers - and I'm very proud of controlling two 28YBJ-48 stepper motors.
They will allow to rotate sort of a light-following turret I am building.
Movement shall be in discrete increments, about 9° per increment.
As long as, due to gear reduction, steps per output revolution are 2048, each time I have to rotate 9° I must do approximately 50 steps in the appropriate direction.

With the following settings in Setup():

  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(100.0);
  stepper2.setSpeed(900);

when I want to rotate by 9° in the revlevant direction I do the following (in this case I'm moving clockwise):

 currVerPosition=stepper2.currentPosition();
 stepper2.moveTo(currPosition+50);
                while (stepper2.currentPosition() != currVerPosition+50) 
                    stepper2.runSpeedToPosition();

Question 1: the movement is painstakingly slow, and may require some seconds. Is there a way to get advantage of the full speed that I see when I run the following example from the same source cited above? I didn't notice any improvement even when I used the MoveTo() - should MoveTo() be faster than RunSpeedToPosition()?

void setup()   /****** SETUP: RUNS ONCE ******/
{
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(50.0);
  stepper1.setSpeed(200);
  stepper1.moveTo(2048);  // 1 revolution 
  
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(50.0);
  stepper2.setSpeed(200);
  stepper2.moveTo(-2048);  // 1 revolution 

}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  //Change direction at the limits
  if (stepper1.distanceToGo() == 0) 
    stepper1.moveTo(-stepper1.currentPosition());
    if (stepper2.distanceToGo() == 0) 
    stepper2.moveTo(-stepper2.currentPosition());
  
  stepper1.run();
  stepper2.run();

}//--(end main loop )---

Question 2: I would like to implement "soft rotation limits" (limiting the rotation of each stepper to 180° and 90* respectively). My intention is to set both steppers to a neutral heading manually (by physically rotating the light following turret and its arm (that carries a set of photoresistors) before power up, and then limit the rotation by keeping trace of the movements and avoiding to exceed a given number of steps in each direction (left, right, up, down...). Is there a smarter way to implement rotation limits without recurring to physical switches (I wouldn't be able to add switches as all the Arduino pins are engaged...)?

Many thanks for your attention and all the best,
Cesare

Question 2: I would like to implement "soft rotation limits" (limiting the rotation of each stepper to 180° and 90* respectively). My intention is to set both steppers to a neutral heading manually (by physically rotating the light following turret and its arm (that carries a set of photoresistors) before power up, and then limit the rotation by keeping trace of the movements and avoiding to exceed a given number of steps in each direction (left, right, up, down...).

That is about the only way. Set a value for center = 0. Then test that value before moving. Increment or decrement that value when it moves. Do the same for each stepper. Example, set 0 at boot-up then check for -90 or +90 before moving.

Thank you, @steinie44! I suspected that there could be no other way, and your opinion is a very welcome confirmation.
Best regards,
Cesare

Just so I understand your question about speeding up movements, are you asking if there is faster wsy to oncrement 9 degrees?+

@raschemmel - yes, right! I would like to get the fastest 9° rotation increment possible in each direction.
I couldn't understand which is fastest: runSpeedToPosition(), moveTo() or what else...
Many thanks
Cesare

I'm not sure if "solved" only applies to Q2.

For Q1, have you tried higher values of

  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(100.0);
  stepper2.setSpeed(900);

or are these the max what would work for you.

You don't seem to have posted your full code so I can only guess you are using the AccelStepper library.

Those 5-wire stepper motors put heavier computation demands on an Arduino than would a bipolar stepper with a stepper motor driver board that just requires step and direction connections.

...R

@Robin2
Yes, solved applies only to Q2 - your answer is much appreciated! :slight_smile:

Well, I read somewhere (the AccelStepper documentation or the tutorial at http://arduino-info.wikispaces.com/SmallSteppers ) that setMaxSpeed() above 1000 is unreliable - surely the steppers work well at 1000 (used in the other example I posted), so one thing that I can do is set speed at 1000 instead of 900, and even try higher speed.
About setAcceleration, the value of 100 is the highest I saw used in the code examples, and I don't know whether higher values are viable.
Most of all, I am not sure which rotation methods - moveTo(), runSpeedToPosition()... - take advantage of the acceleration.

In fact I would need some advice by someone who has worked with those small 28YBJ-48 stepper motors. Yes, I'm aware that those small 5 wire steppers are heavier to manage, but they are so cheap that I couldn't resist... :slight_smile: My project has not any practical outcome, it's made just for curiosity, otherwise I would have selected a more sophisticated type of stepper.

Thanks @Robin2 for your relevant and useful comments.

I don't see any mention of microstepping in your post. Are you doing that ?

@raschemmel
I'm sorry but I'm not sure what exactly "microstepping" means.
The minimum movement that I'd like to perform is in 9° increments - and it's there that I'd like to improve rotation speed.
I can't attach here my whole code because it exceeds the 9500 char limit, but I already posted before just the lines related with stepper movement.
The code works perfectly, the only problem being the slowness of the 9° rotations.

CesareBrizio:
I'm sorry but I'm not sure what exactly "microstepping" means.

From the following earlier statement I suspect you are using full steps and the high step number per revolution is due to the gear ratio. If so microstepping (eg two half steps in place of 1 full step) would make things worse.

due to gear reduction, steps per output revolution are 2048

...R

Yes @Robin2, I can confirm that the "original sin" of those small, general purpose steppers is gear ratio - to get enough power at the output shaft, it takes 64 full revolution of the stepper itself to get one revolution of the output shaft.
According to the tutorial I cited in my first post, the internal motor can work at 64 steps per revolution in 8 steps sequence, and at 32 steps per revolution in 4-step sequence. So, it takes 64 * 64 4096 steps per output shaft revolution in 8-steps sequence, and 32 * 64 = 2048 steps in 4-step sequence.

Regardless those figures, there is one thing that escapes me and prompted me to start this thread. If I run the following code:

void setup()   /****** SETUP: RUNS ONCE ******/
{
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(50.0);
  stepper1.setSpeed(200);
  stepper1.moveTo(2048);  // 1 revolution 
  
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(50.0);
  stepper2.setSpeed(200);
  stepper2.moveTo(-2048);  // 1 revolution 

}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  //Change direction at the limits
  if (stepper1.distanceToGo() == 0) 
    stepper1.moveTo(-stepper1.currentPosition());
    if (stepper2.distanceToGo() == 0) 
    stepper2.moveTo(-stepper2.currentPosition());
  
  stepper1.run();
  stepper2.run();

}//--(end main loop )---

I get surprisingly high rotation speeds (a full revolution of the output shaft can take 3 seconds), while with my code, that includes a:

#define FULLSTEP 4
#define HALFSTEP 8
// motor pins

                        
#define motorPin5  8     // Blue   - 28BYJ48 pin 1
#define motorPin6  9     // Pink   - 28BYJ48 pin 2
#define motorPin7  10    // Yellow - 28BYJ48 pin 3
#define motorPin8  11     // Orange - 28BYJ48 pin 4
AccelStepper stepper2(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);

and:

stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(100.0);
  stepper2.setSpeed(900);  

currVerPosition=stepper2.currentPosition();
 stepper2.moveTo(currPosition+50);
                while (stepper2.currentPosition() != currVerPosition+50) 
                    stepper2.runSpeedToPosition();

it takes 3 seconds or a little more just to rotate 9°.
Maybe the culprit is the while loop, with too frequent checks of the current position, maybe the method runSpeedToPosition in inherently slow...
Actually, I don't know!
Thanks again for your assistance.

CesareBrizio:
Regardless those figures, there is one thing that escapes me and prompted me to start this thread. If I run the following code:

My brain is too fuzzy to make sense of what you have said.

You have posted the full code for the "fast" program so please also post the full code for the "slow" program.

...R

Alas, @Robin2, I cannot because it exceeds the 9500 char limit imposed by the forum. But I have already posted all the relevant lines that is to say the "slow" code is as follows:

====================> The following lines are from the program header
#define FULLSTEP 4
#define HALFSTEP 8
// motor pins

                        
#define motorPin5  8     // Blue   - 28BYJ48 pin 1
#define motorPin6  9     // Pink   - 28BYJ48 pin 2
#define motorPin7  10    // Yellow - 28BYJ48 pin 3
#define motorPin8  11     // Orange - 28BYJ48 pin 4


====================> The following lines are from the setup() function

AccelStepper stepper2(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);
stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(100.0);
  stepper2.setSpeed(900);  

====================> the following line are from a parametric function that activates the proper stepper in the proper direction

currVerPosition=stepper2.currentPosition();
 stepper2.moveTo(currPosition+50);
                while (stepper2.currentPosition() != currVerPosition+50) 
                    stepper2.runSpeedToPosition();

CesareBrizio:
Alas, @Robin2, I cannot because it exceeds the 9500 char limit imposed by the forum.

You can add it as an attachment.

...R

Thanks, I notice just now that the "Additional options" include the attachments.
Unfortunately currently I'm at work - I'll attach the code in the late evening (Italian time).

raschemmel:
I don't see any mention of microstepping in your post. Are you doing that ?

Its a unipolar stepper, 28YBJ-48, driven as described here:
http://arduino-info.wikispaces.com/SmallSteppers
so microstepping isn't relevant.

As promised to @Robin2, I'm attaching the whole code, even though I still think that the questions needing answer are still the following:

  1. Are the various methods to perform a rotation such as moveTo(), runSpeedToPosition() etc. inherently different in rotation speed attainable?
  2. Do all the rotation methods take advantage of the acceleration settings?

It all boils down to understanding why this sequence of settings and commands:

====================> The following lines are from the program header
#define FULLSTEP 4
#define HALFSTEP 8
// motor pins

                        
#define motorPin5  8     // Blue   - 28BYJ48 pin 1
#define motorPin6  9     // Pink   - 28BYJ48 pin 2
#define motorPin7  10    // Yellow - 28BYJ48 pin 3
#define motorPin8  11     // Orange - 28BYJ48 pin 4


====================> The following lines are from the setup() function

AccelStepper stepper2(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);
stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(100.0);
  stepper2.setSpeed(900);  

====================> the following line are from a parametric function that activates the proper stepper in the proper direction

currVerPosition=stepper2.currentPosition();
 stepper2.moveTo(currPosition+50);
                while (stepper2.currentPosition() != currVerPosition+50) 
                    stepper2.runSpeedToPosition();

generates a rotation that is uncomparably SLOWER that the fast rotation generated by the following settings and commands:

void setup()   /****** SETUP: RUNS ONCE ******/
{
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(50.0);
  stepper1.setSpeed(200);
  stepper1.moveTo(2048);  // 1 revolution 
  
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(50.0);
  stepper2.setSpeed(200);
  stepper2.moveTo(-2048);  // 1 revolution 

}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  //Change direction at the limits
  if (stepper1.distanceToGo() == 0) 
    stepper1.moveTo(-stepper1.currentPosition());
    if (stepper2.distanceToGo() == 0) 
    stepper2.moveTo(-stepper2.currentPosition());
  
  stepper1.run();
  stepper2.run();

}//--(end main loop )---

Is the slowness caused by the while loop constantly checking whether the destination position is reached??

    currVerPosition=stepper2.currentPosition();
               stepper2.moveTo(currPosition+50); 
               while (stepper2.currentPosition() != currVerPosition+50) 
                      stepper2.runSpeedToPosition();

In that case, is there another way to get 50 steps or -50 steps done by a single command, not requiring a loop nor a constant check of the position attained?

Many thanks to all those who already gave me their attention, and to those that will come.

Turret_intermediate.ino (17.3 KB)

I have just realized that you haven't actually provided the full code for the "fast" example - you have not included the stuff prior to setup() in which variables are declared. These could be the key to the problem.

Why, for example, are you using AccelStepper stepper2(HALFSTEP, in the slow code? Doesn't that halve the speed?

And, are you sure that you have defined HALFSTEP properly - I thought those values were defined within the AccelStepper library.

I don't understand why you are driving your stepper differently from the fast code. I am not sufficiently familiar with the AccelStepper library to know when to use stepper.run() and stepper.runSpeedToPosition(). Why have you chosen the latter?

...R

Thank you for your patience and availability, @Robin2!
You are truly right, I missed the variable dellaration section in my cut&paste of the "fast" example available at
here is all the code.

/* YourDuinoStarter Example: 2 Stepper Motors
 - WHAT IT DOES: Runs 2 28BYJ-48 stepper motors with AccelStepper Library
 - Motors accelerate and decelerate simultaneously in opposite rotations
 - SEE the comments after "//" on each line below
 -  Derived from example code by Mike McCauley
 -  modified by Celem for single stepper
 -  modified by lowres for two steppers 
 NOTE: This may not run 2 motors from USB. 
       May need separate +5 Supply for motors
 - CONNECTIONS: See Pin definitions below

 - V1.01 11/30/2013
   Questions: terry@yourduino.com */

/*-----( Import needed libraries )-----*/
#include <AccelStepper.h>
/*-----( Declare Constants and Pin Numbers )-----*/
#define FULLSTEP 4
#define HALFSTEP 8
// motor pins
#define motorPin1  4     // Blue   - 28BYJ48 pin 1
#define motorPin2  5     // Pink   - 28BYJ48 pin 2
#define motorPin3  6     // Yellow - 28BYJ48 pin 3
#define motorPin4  7     // Orange - 28BYJ48 pin 4
                        // Red    - 28BYJ48 pin 5 (VCC)
                        
#define motorPin5  8     // Blue   - 28BYJ48 pin 1
#define motorPin6  9     // Pink   - 28BYJ48 pin 2
#define motorPin7  10    // Yellow - 28BYJ48 pin 3
#define motorPin8  11    // Orange - 28BYJ48 pin 4
                        // Red    - 28BYJ48 pin 5 (VCC)
/*-----( Declare objects )-----*/
// NOTE: The sequence 1-3-2-4 is required for proper sequencing of 28BYJ48
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
AccelStepper stepper2(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);

/*-----( Declare Variables )-----*/
//none

void setup()   /****** SETUP: RUNS ONCE ******/
{
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(50.0);
  stepper1.setSpeed(200);
  stepper1.moveTo(2048);  // 1 revolution 
  
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(50.0);
  stepper2.setSpeed(200);
  stepper2.moveTo(-2048);  // 1 revolution 

}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  //Change direction at the limits
  if (stepper1.distanceToGo() == 0) 
    stepper1.moveTo(-stepper1.currentPosition());
    if (stepper2.distanceToGo() == 0) 
    stepper2.moveTo(-stepper2.currentPosition());
  
  stepper1.run();
  stepper2.run();

}//--(end main loop )---

/*-----( Declare User-written Functions )-----*/
//none
//*********( THE END )***********

As you can see, also the "fast" example above uses the HALFSTEP setting - I thought that it should mean "do the same job in half the steps", that is to say at double speed if compared to "fullstep".
Anyway - unless I missed something, and knowing how messy I am it's probable! - I copied the same variable declaration of the fast example into my code.

Many thanks for any further suggestion that you may provide.

CesareBrizio:
As you can see, also the "fast" example above uses the HALFSTEP setting

Using HALF steps means that twice as many steps are required - think about how you walk.

I'm a great believer in isolating this sort of problem into a very short sketch that (in your case) does nothing but move one motor. That way it is easy to explore alternatives without the complexities of other parts of the code that have nothing to do with the motor.

One suggestion is to take the fast example and bit by bit modify it to match your code watching carefully to see what happens to performance at every stage.

Another approach is to start with your code and try changing parts back towards the fast example to see what happens.

My own suspicion is that this code may be doing the same thing twice - does it really need the WHILE ?

while (stepper1.currentPosition() != currHorPosition-50) {
                  stepper1.runSpeedToPosition()
             }

I find the {} make it easier to see what is covered by the WHILE

Alternatively, if the WHILE is needed, is there a conflict between the position that runSpeedToPosition() is trying to get to and the position in the WHILE test?

...R