Controlling stepper motors / serial monitor input issues

Hi,

i have a problem and it drives me nuts.

I want so control 5 stepmotors via a arduino mega and 5 motordrivers.

so far so good.

If i want to change the speed of the motors via the serial monitor and type in 'v' it automatically sets the New speed for motor 1 to 0. i can only adjust the speeds for motor 2, 3, 4 and 5.

If i then give the speeds as an input like: 1 2 3 4 5
it sets motor 2 to 1, motor 3 to 2, motor 4 to 3 and motor 5 to 4.

If i give the speeds as an input one by one i can adjust motor 2, then motor 3 is set to 0 automatically. if i then give an input for motor 4, it sets the input correctly as the new speed. after that motor 5 is set to 0 automatically again.

any ideas?

sorry for my rusty english.

This is the code i have:

#include <AccelStepper.h>
#include <MultiStepper.h>

#define PI 3.1415926535897932384626433832795

// Feed unit parameters
float v_ve[5] = {1.00, 1.00, 1.00, 1.00, 1.00}; // Feed speeds in m/min
float d_ve[5] = {0.05, 0.05, 0.05, 0.05, 0.05}; // Roller diameters in m
int uev_ve[5] = {1, 1, 1, 1, 1}; // Gear ratios
int stpu_ve[5] = {200, 200, 200, 200, 200}; // Steps per revolution

// Calculated parameters
float U_ve[5], um_ve[5], sm_ve[5], spm_ve[5], sps_ve[5];
int spsr_ve[5];

// Pin assignments
const int ve_ena[5] = {41, 44, 47, 50, 53};
const int ve_dir[5] = {40, 43, 46, 49, 52};
const int ve_pul[5] = {39, 42, 45, 48, 51};

// Switch pins
const int startStopSwitchPin = 2;
const int directionSwitchPin = 3;

// Motor objects
AccelStepper ve[5] = {
  AccelStepper(1, ve_dir[0], ve_pul[0]),
  AccelStepper(1, ve_dir[1], ve_pul[1]),
  AccelStepper(1, ve_dir[2], ve_pul[2]),
  AccelStepper(1, ve_dir[3], ve_pul[3]),
  AccelStepper(1, ve_dir[4], ve_pul[4])
};

bool motorsRunning = false;
bool direction = true; // true = forward; false = backward

void calculateParameters() {
  for (int i = 0; i < 5; i++) {
    U_ve[i] = 2 * PI * (d_ve[i] / 2); // Roller circumference
    um_ve[i] = 1 / U_ve[i]; // Revolutions per meter
    sm_ve[i] = um_ve[i] * stpu_ve[i] * uev_ve[i]; // Steps per meter
    spm_ve[i] = v_ve[i] * sm_ve[i]; // Steps per minute
    sps_ve[i] = spm_ve[i] / 60; // Steps per second
    spsr_ve[i] = int(sps_ve[i]); // Convert to int
  }
}

void updateParameters() {
  for (int i = 0; i < 5; i++) {
    ve[i].setMaxSpeed(spsr_ve[i]);
  }
}

void setup() {
  Serial.begin(9600); // Initialize serial communication
  delay(10000); // Allow time for initialization

  // Switch setup
  pinMode(startStopSwitchPin, INPUT_PULLUP);
  pinMode(directionSwitchPin, INPUT_PULLUP);

  // Calculate initial parameters
  calculateParameters();
  updateParameters();

  // Motor setup
  for (int i = 0; i < 5; i++) {
    ve[i].setAcceleration(500);
    Serial.print("Motor ");
    Serial.print(i + 1);
    Serial.print(": Steps per second = ");
    Serial.println(spsr_ve[i]);
  }
}

void handleSerialInput() {
  if (Serial.available() > 0) {
    char input = Serial.read();

    // Adjust feed speeds via serial input
    if (input == 'v') {
      Serial.println("Enter new feed speeds (m/min) for motors 1 to 5:");
      for (int i = 0; i < 5; i++) {
        while (Serial.available() == 0); // Wait for input
        float newSpeed = Serial.parseFloat();
        v_ve[i] = newSpeed;
        Serial.print("New speed for Motor ");
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.println(v_ve[i]);
      }
      calculateParameters();
      updateParameters();
    }

    // Adjust roller diameters via serial input
    else if (input == 'd') {
      Serial.println("Enter new roller diameters (m) for motors 1 to 5:");
      for (int i = 0; i < 5; i++) {
        while (Serial.available() == 0); // Wait for input
        float newDiameter = Serial.parseFloat();
        d_ve[i] = newDiameter;
        Serial.print("New diameter for Motor ");
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.println(d_ve[i]);
      }
      calculateParameters();
      updateParameters();
    }

    // Adjust gear ratios via serial input
    else if (input == 'u') {
      Serial.println("Enter new gear ratios for motors 1 to 5:");
      for (int i = 0; i < 5; i++) {
        while (Serial.available() == 0); // Wait for input
        int newRatio = Serial.parseInt();
        uev_ve[i] = newRatio;
        Serial.print("New gear ratio for Motor ");
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.println(uev_ve[i]);
      }
      calculateParameters();
      updateParameters();
    }

    // Adjust steps per revolution via serial input
    else if (input == 's') {
      Serial.println("Enter new steps per revolution for motors 1 to 5:");
      for (int i = 0; i < 5; i++) {
        while (Serial.available() == 0); // Wait for input
        int newSteps = Serial.parseInt();
        stpu_ve[i] = newSteps;
        Serial.print("New steps per revolution for Motor ");
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.println(stpu_ve[i]);
      }
      calculateParameters();
      updateParameters();
    }
  }
}

void loop() {
  handleSerialInput();

  // Read switch states
  bool startStopSwitchState = digitalRead(startStopSwitchPin) == LOW;
  bool directionSwitchState = digitalRead(directionSwitchPin) == LOW;

  // Check if the Start/Stop Switch is pressed
  if (startStopSwitchState) {
    motorsRunning = !motorsRunning; // Toggle the running state
    delay(200); // Debounce delay
  }

  // Check the direction switch
  direction = directionSwitchState;

  // Set the speed and direction for each motor
  for (int i = 0; i < 5; i++) {
    if (motorsRunning) {
      int speed = direction ? spsr_ve[i] : -spsr_ve[i];
      ve[i].setSpeed(speed);
      ve[i].runSpeed();
    } else {
      ve[i].stop();
    }
  }

  delay(50); // Small delay for debouncing and smooth operation
}

What have you got the Line Ending set to in the Serial monitor ?

Make sure line ending in serial monitor is NOT set to No line ending
Add this statement to setup(): Serial.setTimeout(30000);
It will give you 30 seconds to enter each speed.
If you timeout it will go to the next

its set to carriage return

now its working! but why? i want to understand the issue. if i wait 30 seconds it sets the motor 1 to 0 again. but i dont understand where he takes the zero from. if he has set new speed for motor 1 to zero after waiting he does not do it for motor 2. where is the difference? :thinking:

I don't think you have defined enough digits of pi in your code.

# define PI 3.1415926535897932384626433832795

a7

hahaha just copied it from a forum :rofl:

You should carefully read the documentation for all the Arduino functions that you use in your program.
The problem was with Serial.parseFloat(). It will look for a float in the serial buffer and it does not find one within a given time period it will terminate. The default timeout is one second. So unless you can type real fast it will always timeout.

Serial.setTimeout(30000) give you 30 seconds to respond.

PI is already defined in the Arduino system. You don't need to redefine it.
Just use PI in your code.

Anything else?

no now im happy! thanks a lot!

Have a nice day!