Controlling 4 steppers

Hi!

I have a project: omniwheel 4WD car with stepper motors. I use library AH_EasyDriver for controlling steppers. I want to control those motors with three parameters: X axis speed (Xm), Y axis speed (Ym) and rotating speed (fi).

#include <AH_EasyDriver.h>
#include <Math.h>

// AH_EasyDriver(int RES, int DIR, int STEP, int MS1, int MS2, int SLP);

AH_EasyDriver stepper1(200,2,3,4,5,6);    
AH_EasyDriver stepper3(200,7,8,9,10,11);
AH_EasyDriver stepper2(200,22,23,24,25,26);
AH_EasyDriver stepper4(200,27,28,29,30,31);

void setup()
{
  Serial.begin(57600);
  Serial.println(stepper1.getVersion());
  stepper1.setMicrostepping(0);  // 0 -> full stepping  1 -> 1/2 stepping  2 -> 1/4 stepping  3 -> 1/8 stepping                        
  Serial.println(stepper2.getVersion());
  stepper2.setMicrostepping(0);     
  Serial.println(stepper3.getVersion());
  stepper3.setMicrostepping(0);     
  Serial.println(stepper4.getVersion());
  stepper4.setMicrostepping(0);     
}

void loop()
{
  //speed calculating 
  float Pi= 3.1416;
  float Xm= 15.0; //speed X smer
  float Ym= 0.0; //speed Y  smer
  float fi= 0.0; //rotating

  int koraki = 200; //number of steps for one rpm
  float r = 0.029; //wheel radius
  float l = 0.09; //width 
  float d = 0.09; //length

  float obseg= 2*r*Pi;

  float v1= (Xm - Ym - (l+d)*fi)/sqrt(2);  //1 motor speed
  float v2= (Xm + Ym - (l+d)*fi)/sqrt(2);  //2 motor speed
  float v3= (Xm - Ym + (l+d)*fi)/sqrt(2);  //3 motor
  float v4= (Xm + Ym + (l+d)*fi)/sqrt(2);  //4 motor

  float obrati1 = v1 / obseg; //obrati prvega kolesa
  float obrati2 = v2 / obseg; //obrati drugega kolesa
  float obrati3 = v3 / obseg; //obrati tretjega kolesa
  float obrati4 = v4 / obseg; //obrati četrtega kolesa

  Serial.print(obrati1,4);
  Serial.print("\t");
  Serial.print(obrati2,4);
  Serial.print("\t");
  Serial.print(obrati3,4);
  Serial.print("\t");
  Serial.print(obrati4,4);
  Serial.print("\n");

  if(Xm==0.0 && Ym==0.0 && fi==0.0)
  {
    stepper1.sleepON();
    stepper2.sleepON();
    stepper3.sleepON();
    stepper4.sleepON(); 
  }
  else if(Xm != 0.0 || Ym!=0.0 ||fi!=0.0)
  {
    stepper1.sleepOFF();
    stepper2.sleepOFF();
    stepper3.sleepOFF();
    stepper4.sleepOFF(); 
  }
  //MOTOR1
  if(obrati1<0)
  {
    stepper1.move(FORWARD);  
  }
  else if (obrati1>0)
  {
    stepper1.move(-FORWARD);
  }
  stepper1.setSpeedRPM(obrati1);              // RPM 

  ///MOTOR2
  if(obrati2<0)
  {
    stepper2.move(FORWARD);  
  }
  else if (obrati2>0)
  {
    stepper2.move(-FORWARD);  
  }
  stepper2.setSpeedRPM(obrati2);              // RPM 

  //MOTOR3
  if(obrati3<0)
  {
    stepper3.move(-FORWARD);  
  }
  else if (obrati3>0)
  {
    stepper3.move(FORWARD);  
  }  
  stepper3.setSpeedRPM(obrati3);              // RPM 

  //MOTOR4
  if(obrati4<0)
  {
    stepper4.move(-FORWARD);  
  }
  else if (obrati4>0)
  {
    stepper4.move(FORWARD);  
  }
  stepper4.setSpeedRPM(obrati4);              // RPM 


}

In this code, every motor is individually controlled. But I get same speed on all wheels if I input more than one parameter. Any advice?

I have not heard of the AH_EasyDriver library. Please post a link to its documentation.

What stepper motor drivers are you using?
What Arduino are you using?

...R

Im using bipolar nema 11 steppers, with easy drivers, and Arduino Mega.

My robot was controlled with joystick at first, but now, I want to control motors with input parameters.

AH_EasyDriver_20120512.zip (6.27 KB)

The AH_EasyDriver library was written by Alexander Hinkel, a German Arduino and Electronics expert.
See this link.

Hint to @ignacij:
There is an updated version of the library on his German site.

Scroll down and look for AH_EasyDriver_2013-03-21.

That's all I can do as I don't use this library. Looking at Alexander's site there is no information if the library supports more than 1 drive.

My favourite for dealing with multiple steppers is the AccelStepper library - be aware that it doesn't support the microstepping adjustment by software. This must be done hardwired.

Can you please tell me, what are the commands for controlling speed and direction of stepper?

thanks!

Have a look at this Simple Stepper Code - it shows how to control a stepper directly without a library. Under the hood the libraries do pretty much the same thing.

AFAIK the Easydriver defaults to micro-stepping so take that into account.

The speed of a stepper motor is determined by the interval between steps.

...R
Stepper Motor Basics

Thanks!

I made my first sketch without library, second was with AH_easydriver and I want to try with this one too. Is there any command ln accelstepper (like in AHeasydriver) stepper.Move (for direction) and setSpeedRPM (for speed).

Thanks!

Is there any command ln accelstepper (like in AHeasydriver) stepper.Move (for direction) and setSpeedRPM (for speed).

Aunt Google and the forum search are your friends:

Have a look at this.
You will find a lot of discussions around this library in this forum.

There are plenty of features and functions in that library including direction and speed modification.
I am using this library for very big projects and as long as you don't need extensive speed it is a fantastic and easy going library to control multiple motors (non-blocking code).

The price you pay is the speed limit (AccelStepper only supports up to 4000 steps /second).

ignacij:
Is there any command ln accelstepper (like in AHeasydriver) stepper.Move (for direction) and setSpeedRPM (for speed).

Yes. Study the Accelstepper documentation

There are also example programs

...R

#include <AccelStepper.h>

AccelStepper stepper1(1, 3, 2);
int MS11 = 4;
int MS21 = 5;

AccelStepper stepper3(1, 8, 7);
int MS13 = 9;
int MS23 = 10;

AccelStepper stepper2(1, 23, 22);
int MS12 = 24;
int MS22 = 25;

AccelStepper stepper4(1, 28, 27);
int MS14 = 29;
int MS24 = 30;

void setup()
{  
  Serial.begin(115200); // begin serial output @ 115200 baud

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);

  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);

  pinMode(22, OUTPUT);
  pinMode(23, OUTPUT);
  pinMode(24, OUTPUT);
  pinMode(25, OUTPUT);

  pinMode(27, OUTPUT);
  pinMode(28, OUTPUT);
  pinMode(29, OUTPUT);
  pinMode(30, OUTPUT);

  digitalWrite(MS11, LOW);  //     MS1    MS2    (hitrost korakanja motorjev)
  digitalWrite(MS21, LOW);  //     LOW    LOW    POLNOKORAČNO
  digitalWrite(MS12, LOW);  //     HIGH   LOW    POLKORAČNO
  digitalWrite(MS22, LOW);  //     LOW    HIGH   ČETRKORAČNO
  digitalWrite(MS13, LOW);  //     HIGH   HIGH   OSMINSKOKORAČNO
  digitalWrite(MS23, LOW); 
  digitalWrite(MS14, LOW);
  digitalWrite(MS24, LOW);
}

void loop()
{
  //preračun hitrosti
  float Pi= 3.1416;
  float Xm= 1.0; //hitrost X smer
  float Ym= 2.0; //hitrost Y smer
  float fi= 3.0; //zasuk

  int koraki = 200; //število korakov motorja za en obrat
  float r = 0.029; //polmer kolesa
  float l = 0.09; //širina
  float d = 0.09; //dolžina

  float obseg= 2*r*Pi;

  float v1= (Xm - Ym - (l+d)*fi)/sqrt(2);  //hitrost prvega motorja
  float v2= (Xm + Ym - (l+d)*fi)/sqrt(2);  //hitrost drugega motorja
  float v3= (Xm - Ym + (l+d)*fi)/sqrt(2);  //hitrost tretjega motorja
  float v4= (Xm + Ym + (l+d)*fi)/sqrt(2);  //hitrost četrtega motorja

  float obrati1 = v1 / obseg; //obrati prvega kolesa
  float obrati2 = v2 / obseg; //obrati drugega kolesa
  float obrati3 = v3 / obseg; //obrati tretjega kolesa
  float obrati4 = v4 / obseg; //obrati četrtega kolesa  

  int stobrt1 = abs((int)fabs(obrati1));  //pretvorba float-->int
  int stobrt2 = abs((int)fabs(obrati2));
  int stobrt3 = abs((int)fabs(obrati3));
  int stobrt4 = abs((int)fabs(obrati4));

  int SetMotorSpeed1 = stobrt1*200/60;  // *200korakov na obrat/60sekund =RPS
  int SetMotorSpeed2 = stobrt2*200/60;
  int SetMotorSpeed3 = stobrt3*200/60;
  int SetMotorSpeed4 = stobrt4*200/60;

  Serial.print(stobrt1);
  Serial.print("\t");
  Serial.print(SetMotorSpeed1);
  Serial.print("\t");
  Serial.print(stobrt2);
  Serial.print("\t");
  Serial.print(SetMotorSpeed2);
  Serial.print("\t");
  Serial.print(stobrt3);
  Serial.print("\t");
  Serial.print(SetMotorSpeed3);
  Serial.print("\t");
  Serial.print(stobrt4);
  Serial.print("\t");
  Serial.print(SetMotorSpeed4);
  Serial.print("\n");

  stepper1.setCurrentPosition(0);
  stepper2.setCurrentPosition(0);
  stepper3.setCurrentPosition(0);
  stepper4.setCurrentPosition(0);

  int MAX= 500;
  stepper1.setMaxSpeed(MAX);
  stepper2.setMaxSpeed(MAX);
  stepper3.setMaxSpeed(MAX);
  stepper4.setMaxSpeed(MAX);

  int pospesek= 100;
  stepper1.setAcceleration(SetMotorSpeed1);
  stepper2.setAcceleration(SetMotorSpeed2);
  stepper4.setAcceleration(SetMotorSpeed3);
  stepper4.setAcceleration(SetMotorSpeed4);
int cilj=100000;
  stepper1.moveTo(cilj);
  stepper2.moveTo(cilj);
  stepper3.moveTo(cilj);
  stepper4.moveTo(cilj);

  stepper1.setSpeed(SetMotorSpeed1);
  stepper2.setSpeed(SetMotorSpeed2);
  stepper3.setSpeed(SetMotorSpeed3);
  stepper4.setSpeed(SetMotorSpeed4);

  while((stepper1.currentPosition()) != 10000)
  {
    stepper1.run();
    stepper2.run();
    stepper3.run();
    stepper4.run();
  }


  stepper1.stop(); 
  stepper2.stop(); 
  stepper3.stop(); 
  stepper4.stop(); 

  while (stepper1.run() && stepper2.run() && stepper3.run() && stepper4.run()) ;

}

I made some code… and now I have some problem… only three steppers are working as they have to, and one is just buzzing (motor 3). I tried to change pins (motor 1 to motor 3) and then it is working motor 3 and motor 1 not. All the pins are connected correctly I double checked.

Is it possyble that accelStepper supports only 3 motors?

Thanks

You don't need this line

  while((stepper1.currentPosition()) != 10000)

just allow loop() to deal with the repetition.

And you don't need the calls to stepper.stop() - it will stop automatically when it gets to its destination.

I think these things don't change and should be in setup() rather than loop().

  float Pi= 3.1416;
  float Xm= 1.0; //hitrost X smer
  float Ym= 2.0; //hitrost Y smer
  float fi= 3.0; //zasuk

  int koraki = 200; //število korakov motorja za en obrat
  float r = 0.029; //polmer kolesa
  float l = 0.09; //širina
  float d = 0.09; //dolžina

Try to avoid using floats as they make calculations very slow. And the stepper just needs integer values.

...R

Is it possyble that accelStepper supports only 3 motors?

As far as I know there is no limit mentioned, how many motors are supported at the same time - although there must be a limit. All sources are talking about "multiple" steppers, but none of them is precise what multiple means at its extreme.

I found this link, where somebody ran 4 motors with a Mega (which you are using apparently too).

So try to repeat your test with the sketch which was used in that example and see what happens. If it works, you might have to check your own sketch/wiring again.

Looking at your code I fully support what @Robin2 said about float.

I did a similar calculation in one of my projects, but

  1. the calculation should be in setup()
  2. calculating steps, speed and other motor parameters -> have them rounded to integer values

All the serial.print stuff should also be in setup -> it will slow the main loop down to a level, which might cause you stepper control problems which could be unpredictable.

As you can read in the AccelStepper library documentation:
Let the stepper control loop run as often as possible, which means, throw out all unnessary code out of loop() - either omitting it or push it to setup().

Especially when you are using multiple motors at different speeds, you should pay a lot of attention to a short and powerful loop() if you want to have your motors running smoothly.

Thank you all, it works now!

Pls tell all the readers what made it work - what did you change (wiring issue?, sketch change?)

Here it is my final version that’s working. But I still have one problem. My motors don’t accelerate, anybody knows why?

#include <AccelStepper.h>
#include <SoftwareSerial.h>// import the serial library
#include "math.h" 

SoftwareSerial Genotronex(10, 11); // RX, TX
int BluetoothData; // the data given from Computer

float Xm;
float Ym;
float W;
char junk = ' ';

AccelStepper stepper1(1, 3, 2);   //MOTOR 1  driver, step, dir
int MS11 = 4;
int MS21 = 5;
int SLP1 = 6;

AccelStepper stepper3(1, 8, 7);   // MOTOR 3
int MS13 = 9;
int MS23 = 12;
int SLP2 = 13;

AccelStepper stepper2(1, 23, 22); // MOTOR 2
int MS12 = 24;
int MS22 = 25;
int SLP3 = 26;

AccelStepper stepper4(1, 28, 27); // MOTOR 4
int MS14 = 29;
int MS24 = 30;
int SLP4 = 31;


//preračun hitrosti
float Pi= 3.1416;

int koraki = 200; //število korakov motorja za en obrat
float r = 0.029; //polmer kolesa
float l = 0.09; //širina
float d = 0.09; //dolžina

float obseg= 2*r*Pi;    // obseg kolesa

void setup()
{  
  Genotronex.begin(9600); // begin serial output @ 115200 baud
  Genotronex.println("");
  Genotronex.flush();

  pinMode(2, OUTPUT);       //MOTOR 1
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);

  pinMode(7, OUTPUT);       // MOTOR 3
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);

  pinMode(22, OUTPUT);      // MOTOR 2
  pinMode(23, OUTPUT);
  pinMode(24, OUTPUT);
  pinMode(25, OUTPUT);
  pinMode(26, OUTPUT);

  pinMode(27, OUTPUT);      // MOTOR 4
  pinMode(28, OUTPUT);
  pinMode(29, OUTPUT);
  pinMode(30, OUTPUT);
  pinMode(31, OUTPUT);

  digitalWrite(MS11, LOW);   // MOTOR 1            MS1    MS2    (hitrost korakanja motorjev)
  digitalWrite(MS21, LOW);                  //     LOW    LOW    POLNOKORAČNO
  digitalWrite(MS12, LOW);   // MOTOR 2            HIGH   LOW    POLKORAČNO
  digitalWrite(MS22, LOW);                  //     LOW    HIGH   ČETRKORAČNO
  digitalWrite(MS13, LOW);   // MOTOR 3            HIGH   HIGH   OSMINSKOKORAČNO
  digitalWrite(MS23, LOW); 
  digitalWrite(MS14, LOW);   // MOTOR 4
  digitalWrite(MS24, LOW);

  
}

void loop()
{
  digitalWrite(SLP1, LOW);
  digitalWrite(SLP2, LOW);
  digitalWrite(SLP3, LOW);
  digitalWrite(SLP4, LOW);
  Genotronex.println("Enter parameter value 'Xm', Press ENTER");
  while (Genotronex.available() == 0) ;
  {
    Xm = Genotronex.parseFloat(); 
    Genotronex.print("Xm = "); 
    Genotronex.println(Xm, DEC);
    while (Genotronex.available() > 0)  // .parseFloat() can leave non-numeric characters
    { 
      junk = Genotronex.read() ;  // clear the keyboard buffer
    }      
  }


  Genotronex.println("Enter parameter value 'Ym', Press ENTER");
  while (Genotronex.available() == 0) ;
  {
    Ym = Genotronex.parseFloat(); 
    Genotronex.print("Ym = "); 
    Genotronex.println(Ym, DEC);
    while (Genotronex.available() > 0)  // .parseFloat() can leave non-numeric characters
    { 
      junk = Genotronex.read() ; // clear the keyboard buffer
    }
  }


  Genotronex.println("Enter parameter value 'W', Press ENTER");
  while (Genotronex.available() == 0) ;
  {
    W = Genotronex.parseFloat(); 
    Genotronex.print("W = "); 
    Genotronex.println(W, DEC);
    while (Genotronex.available() > 0)  // .parseFloat() can leave non-numeric characters
    { 
      junk = Genotronex.read() ; // clear the keyboard buffer
    }      
    float v1= -0.7071*Xm + 0.7071*Ym + 0.1273*W; 
    float v3= -0.7071*Xm -0.7071*Ym + 0.1273*W;
    float v2= 0.7071*Xm -0.7071*Ym + 0.1273*W;
    float v4= 0.7071*Xm + 0.7071*Ym + 0.1273*W;

    float obrati1 = v1 / obseg; //obrati prvega kolesa
    float obrati2 = v2 / obseg; //obrati drugega kolesa
    float obrati3 = v3 / obseg; //obrati tretjega kolesa
    float obrati4 = v4 / obseg; //obrati četrtega kolesa  

    Genotronex.print("Obrati 1. kolesa = ");
    Genotronex.println(obrati1, DEC); 
    Genotronex.println("\n");
    Genotronex.println();

    Genotronex.print("Obrati 2. kolesa = ");
    Genotronex.println(obrati2, DEC); 
    Genotronex.println("\n");
    Genotronex.println();

    Genotronex.print("Obrati 3. kolesa = ");
    Genotronex.println(obrati3, DEC); 
    Genotronex.println("\n");
    Genotronex.println();

    Genotronex.print("Obrati 4. kolesa = ");
    Genotronex.println(obrati4, DEC); 
    Genotronex.println("\n");
    Genotronex.println();

    float SetMotorSpeed1 = obrati1*koraki*1.2;  
    float SetMotorSpeed2 = obrati2*koraki*1.2;
    float SetMotorSpeed3 = obrati3*koraki*1.2;
    float SetMotorSpeed4 = obrati4*koraki*1.2;

    digitalWrite(SLP1, HIGH);
    digitalWrite(SLP2, HIGH);
    digitalWrite(SLP3, HIGH);
    digitalWrite(SLP4, HIGH);

    

    while (1)
    {
      int MAX= 2000;                  // MAX HITROST (steps/s)
  stepper1.setMaxSpeed(MAX);
  stepper2.setMaxSpeed(MAX);
  stepper3.setMaxSpeed(MAX);
  stepper4.setMaxSpeed(MAX);

  int pospesek= 10;
  stepper1.setAcceleration(10);
  stepper2.setAcceleration(10);
  stepper4.setAcceleration(10);
  stepper4.setAcceleration(10);
  
      stepper1.setSpeed(SetMotorSpeed1);    // hitrost posameznega kolesa
    stepper2.setSpeed(SetMotorSpeed2);
    stepper3.setSpeed(SetMotorSpeed3);
    stepper4.setSpeed(SetMotorSpeed4);
    
      stepper1.runSpeed();
      stepper2.runSpeed();
      stepper3.runSpeed();
      stepper4.runSpeed();
      
      if (Genotronex.available()!=0)
      {
        while (Genotronex.available() > 0)  // .parseFloat() can leave non-numeric characters
        { 
          junk = Genotronex.read() ; // clear the keyboard buffer
        }
        break;
      }	

    }

  }
}

Change the value for acceleration parameter:

int pospesek= 10;

(which imho is way too small)

to

int pospesek= 1000;
  stepper1.setAcceleration(pospesek);
  stepper2.setAcceleration(pospesek);
  stepper4.setAcceleration(pospesek);
  stepper4.setAcceleration(pospesek);

You should play a bit with "pospesek" value to see how the acceleration changes.

I tried a lot of values for pospesek.. but it is not working. I tried with bigger, but then I though that it's not working because of to big values. I will try even bigger, I hope it will work.

Thanks!

Nothing. It's not working with small values (0.5) and it's not working with big values (1000) or even bigger.

ignacij:
My motors don't accelerate, anybody knows why?

RTFM

The runSpeed() function does not do acceleration. Use run()

...R