Multiple stepper motor control

Hello. I want to control multiple stepper motors that run in the same time. I mean by that, they will start movement in the same time and will stop movement in the same time. I tried to use accelstepper library for that and even tried to write my own motor movement functions to achieve proper motor movement. I want to move 3 stepper motors and I want to always send command via serial monitor where I tell how many steps should every motor do and then calculate in the program proper speeds of all motors.

However I just could not manage it to work properly. They even didn ´t move in the same time or motors did not move proper amount of steps and so on.

Any ideas how to solve this problem?

Please tell us you got ONE motor to function with your parameters, then went to two motors, etc. Hopefully you did NOT put all the stuff and code together before beginning to test.

What stepper motors (data sheets, please)?

What stepper motor drivers?

What Arduino board?

Nema 17 stepper motors and DRV8825 stepper drivers. I use arduino nano to control them. Motors moves properly and all the circuits are correct. I have just problem with program

I tested one motor and it worked fine and then I added more motors and at first I achieved that all the motors moved proper amount of steps. I mean one motor ran, then the other and then the last. However that is not what I want from them

If what you are wanting to do is coordinate their movements then consider using GRBL which does exactly this for 3 axes for CNC.

I want to control 3 motors at the moment, but later on I want to add 4th and then 5th motor

Would you show this code for one motor working?

5 axis coordinated movement is complex and few professional CNC controllers can manage it. Can you say more about the application?

// NO library
// Simultaneous movement of three stepper motors

int stepPin[] = {9, 7, 5}; // motor driver board STEP pins
int dirPin[]  = {8, 6, 4}; // motor driver board DIRECTION pins

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 5; i++) { // configure STEP and DIRECTION pins
    pinMode(stepPin[i], OUTPUT);
    pinMode(dirPin[i], OUTPUT);
  }
}

void loop() {
  delay(10); // slow the simulation

  for (int i = 0; i < 3; i++) {
    digitalWrite(stepPin[i], HIGH); // start of start pulse
  }
  delayMicroseconds(2000);

  for (int i = 0; i < 3; i++) {
    digitalWrite(stepPin[i], LOW); // end of start pulse
  }
  delayMicroseconds(2000);
}

I am working on school project and I have to manage work of 5 motors on 4 axis robotic arm. Fifth motor is extruder motor. And I´ve searched for many videos... and talked to many different AI(chatGPT...) and didn´t manage to find solution yet.

If I was assigned this project, I would make a large spreadsheet showing each motor across the X axis and showing what you want to do on the Y axis. For each corresponding entry show what movement that motor will need to do in order to achieve your desired outcome. These will need to have one exact movement per entry.

So I tried to work with multiple stepper motors and this is code that I ended up with. It still doesn´t work properly... My plan is to send commands from GUI written in python and syntax of command that is sent via serial looks like this: 0|1|365|0|365|1. Where first, third and fifth parameter are steps for different motors and second, fourth and sixth parameter are directions of motors.(I didn´t pay attention to proper direction in code yet.) So this is my code at the moment:

const int motorM1StepPin = 9;
const int motorM1DirPin = 8;
const int motorM2StepPin = 11;
const int motorM2DirPin = 10;
const int motorBaseStepPin = 3;
const int motorBaseDirPin = 2;

unsigned long previousMotorBaseTime = millis();
unsigned long previousMotorM1Time = millis();
unsigned long previousMotorM2Time = millis();

long motorBaseInterval = 0;
long motorM1Interval = 0;
long motorM2Interval = 0;

long ratioB = 0;
long ratioM2 = 0;

// Direction variables
int M1direction = 0;
int M2direction = 0;

int M1stepTotal = 100;
int M2stepTotal = 0;

int BaseStepsTotal = 0;
int BaseDirection = 0;

void Calc_Interval(unsigned long StepB, unsigned long StepM1, unsigned long StepM2);

void setup() {
  Serial.begin(9600);
  pinMode(motorM1StepPin, OUTPUT);
  pinMode(motorM1DirPin, OUTPUT);
  pinMode(motorM2StepPin, OUTPUT);
  pinMode(motorM2DirPin, OUTPUT);
  pinMode(motorBaseStepPin, OUTPUT);
  pinMode(motorBaseDirPin, OUTPUT);
  digitalWrite(motorBaseDirPin, HIGH);
  digitalWrite(motorM1DirPin, HIGH);
  digitalWrite(motorM2DirPin, HIGH);

}

void loop() {
  if (Serial.available() > 0) {
    Serial.println("Command RECEIVED!");
    String command = Serial.readStringUntil('\n');
    command.trim();
  
    unsigned long currentMotorBaseTime = millis();
    unsigned long currentMotorM1Time = millis();
    unsigned long currentMotorM2Time = millis();
    digitalWrite(motorBaseStepPin, LOW);
    digitalWrite(motorM1StepPin, LOW);
    digitalWrite(motorM2StepPin, LOW);



    // Use strtok to split the command into tokens based on the '|' delimiter
    char *token = strtok(const_cast<char*>(command.c_str()), "|");
    int values[5]; // Assuming there are four values: BaseSteps, BaseDir, M1step, M1direction, M2step, M2direction

    int i = 0;
    while (token != NULL && i < 9) {
      values[i++] = atoi(token);
      token = strtok(NULL, "|");
    }

    BaseStepsTotal = values[0];
    BaseDirection = values[1];
    M1stepTotal = values[2];
    M1direction = values[3];
    M2stepTotal = values[4];
    M2direction = values[5]; 

    Calc_Interval(BaseStepsTotal, M1stepTotal, M2stepTotal);
    
    for (int step = 0; step < M1stepTotal; step++){
      digitalWrite(motorBaseStepPin, LOW);
      digitalWrite(motorM1StepPin, LOW);
      digitalWrite(motorM2StepPin, LOW);
      if (currentMotorBaseTime - previousMotorBaseTime > motorBaseInterval){
        digitalWrite(motorBaseStepPin, HIGH);
        previousMotorBaseTime = currentMotorBaseTime;
      }
      if (currentMotorM1Time - previousMotorM1Time > motorM1Interval){
        digitalWrite(motorM1StepPin, HIGH);
        previousMotorM1Time = currentMotorM1Time;
      }
      if (currentMotorM2Time - previousMotorM2Time > motorM2Interval){
        digitalWrite(motorM2StepPin, HIGH);
      }
      Serial.println(step);
    }   
  }
}

void Calc_Interval(unsigned long StepB, unsigned long StepM1, unsigned long StepM2){
  ratioB = StepM1 / StepB;
  ratioM2 = StepM2 / StepB;
  motorM1Interval = 1000;
  motorBaseInterval = motorM1Interval * ratioB; 
  motorM2Interval = motorM1Interval * ratioM2; 
}








Code compiled properly and motor loop run properly as well(I mean it sends number of loop everytime it runs through it), however motors don´t move...

Any ideas on how to fix that ?

Thank you very much

What does your code need (post #13) that my code does not have (post #10)? Take my code and add the things you need.

Can you explain to me how your code works, so I can understand it better?

In this code I managed to make motors move together and they move proper amount of steps.

This code is still not finished, however works very well. Next adjustments will be in python code(atleast most of them).

const int motorM1StepPin = 9;
const int motorM1DirPin = 8;
const int motorM2StepPin = 11;
const int motorM2DirPin = 10;
const int motorBaseStepPin = 3;
const int motorBaseDirPin = 2;

unsigned long previousMotorBaseTime = millis();
unsigned long previousMotorM1Time = millis();
unsigned long previousMotorM2Time = millis();

long motorBaseInterval = 50;
long motorM1Interval = 5;
long motorM2Interval = 1;

long ratioB = 0;
long ratioM2 = 0;

// Direction variables
int M1direction = 0;
int M2direction = 0;

int M1stepTotal = 200;
int M2stepTotal = 0;

int BaseStepsTotal = 0;
int BaseDirection = 0;

void Calc_Interval(unsigned long StepB, unsigned long StepM1, unsigned long StepM2);

void setup() {
  Serial.begin(9600);
  pinMode(motorM1StepPin, OUTPUT);
  pinMode(motorM1DirPin, OUTPUT);
  pinMode(motorM2StepPin, OUTPUT);
  pinMode(motorM2DirPin, OUTPUT);
  pinMode(motorBaseStepPin, OUTPUT);
  pinMode(motorBaseDirPin, OUTPUT);
  digitalWrite(motorBaseDirPin, HIGH);
  digitalWrite(motorM1DirPin, HIGH);
  digitalWrite(motorM2DirPin, HIGH);

}

void loop() {
  if (Serial.available() > 0) {
    Serial.println("Command RECEIVED!");
    String command = Serial.readStringUntil('\n');
    command.trim();
    // Use strtok to split the command into tokens based on the '|' delimiter
    char *token = strtok(const_cast<char*>(command.c_str()), "|");
    int values[5]; // Assuming there are four values: BaseSteps, BaseDir, M1step, M1direction, M2step, M2direction

    int i = 0;
    while (token != NULL && i < 9) {
      values[i++] = atoi(token);
      token = strtok(NULL, "|");
    }

    motorBaseInterval = values[0];
    motorM1Interval = values[1];
    motorM2Interval = values[2];
    M1stepTotal = values[3];
  }
  if (M1stepTotal > 0){
    unsigned long currentMotorBaseTime = millis();
    unsigned long currentMotorM1Time = millis();
    unsigned long currentMotorM2Time = millis();
    digitalWrite(motorBaseStepPin, LOW);
    digitalWrite(motorM1StepPin, LOW);
    digitalWrite(motorM2StepPin, LOW);

    //Calc_Interval(BaseStepsTotal, M1stepTotal, M2stepTotal);

    if (currentMotorBaseTime - previousMotorBaseTime > motorBaseInterval){
      digitalWrite(motorBaseStepPin, HIGH);
      previousMotorBaseTime = currentMotorBaseTime;
    }
    if (currentMotorM1Time - previousMotorM1Time > motorM1Interval){
      digitalWrite(motorM1StepPin, HIGH);
      previousMotorM1Time = currentMotorM1Time;
      M1stepTotal --;
      Serial.println(M1stepTotal);
    }
    if (currentMotorM2Time - previousMotorM2Time > motorM2Interval){
      digitalWrite(motorM2StepPin, HIGH);
      previousMotorM2Time = currentMotorM2Time;
    }
  }
}

void Calc_Interval(unsigned long StepB, unsigned long StepM1, unsigned long StepM2){
  ratioB = StepM1 / StepB;
  ratioM2 = StepM2 / StepB;
  motorM1Interval = 1000;
  motorBaseInterval = motorM1Interval * ratioB; 
  motorM2Interval = motorM1Interval * ratioM2; 
}







Thanks to everyone. Everything you told me helped and I found solution. (solution is code above if someone wants to use it)

Look for the "comment marks" which are two slashes (//)... after those slashes are the "comments" that explain what the line (or lines) of code is doing.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.