I need help as the stepper is not running smoothly

im using a nema 23 3a and nema 17 2a it is supposed to be a winding machine but when I run the motor it is not running smoothly it vibrates too much and it is so slow I'm wondering if anyone can help me with the code
the power supply Im using is 12V 5A on the other code where I just testing the motor to run it is rotating fast enough but when I'm using this code is is staggering and vibrating too much I'm using a arduino mega, 20x4 i2c LCD 4x3 keypad as for the driver I'm using tb6600 set at 800pulse per rev for both

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <AccelStepper.h>

#define DIRX 8
#define STEPX 9
#define ENAX 7
#define DIRY 11
#define STEPY 12
#define ENAY 10

AccelStepper stepperx(AccelStepper::DRIVER, STEPX, DIRX);
AccelStepper steppery(AccelStepper::DRIVER, STEPY, DIRY);

LiquidCrystal_I2C lcd(0x27, 20, 4);

// Keypad Setup (4x3)
const byte ROWS = 4;
const byte COLS = 3;
char keys[ROWS][COLS] = {
    {'1', '2', '3'},
    {'4', '5', '6'},
    {'7', '8', '9'},
    {'*', '0', '#'}
};

// Double-check if these match your actual **column wiring**
byte rowPins[ROWS] = {27, 33, 36, 34};  
byte colPins[COLS] = {28, 26, 35};  // <-- Verify column pins!

Keypad customkeypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

int sel = 40, ent = 41, start = 48, stop = 38, orient = 42;
String selectedMode = "Transformer";
String inputTurns = "";
long storedsteps = 0;
bool readytomove = false;
long lastturnreported = 0;
String selectedSpeed = "LOW"; // Default speed
int stepSpeed = 16000; // Default stepper speed

String orientation = "";

int oval = 0, oval_num = 0;
int selval = 0, sel_num = 0;
int entval = 0, ent_num = 0;
bool selPrevState = LOW;
bool entPrevState = LOW;
bool ovalPrevState = LOW;

bool updsel = false;

void setup() {
    Serial.begin(9600);
    lcd.init();
    lcd.begin(20, 4);
    lcd.backlight();
    
    pinMode(ENAX, OUTPUT);
    pinMode(ENAY, OUTPUT);

    pinMode(sel, INPUT);
    pinMode(ent, INPUT);
    pinMode(start, INPUT);
    pinMode(stop, INPUT);
    pinMode(orient, INPUT);

    digitalWrite(ENAY, LOW);
    digitalWrite(ENAX, LOW);

    lcd.setCursor(1, 0);
    lcd.print("PORTABLE AUTOMATIC ");
    lcd.setCursor(2, 1);
    lcd.print("WINDING MACHINE");
    lcd.setCursor(2, 2);
    lcd.print("FOR TRANSFORMERS");
    lcd.setCursor(2, 3);
    lcd.print("AND AC/DC MOTORS");
}

void loop() {
    char customKey = customkeypad.getKey();  // Always check keypad input
    selval = digitalRead(sel);
    entval = digitalRead(ent);
    oval = digitalRead(orient);

    if (entval == HIGH && entPrevState == LOW) { 
        ent_num++;
        delay(200);  // Debounce
        Serial.println(ent_num);
        lcd.clear();
    }

    if (selval == HIGH) { 
        sel_num++;
        delay(200);  // Debounce
        Serial.println(sel_num);
    }
    entPrevState = entval;

    if (oval == HIGH && ovalPrevState == LOW) { 
        oval_num++;  
        if (oval_num > 2) oval_num = 1;
        delay(200);  
        Serial.println(oval_num);
        lcd.clear();
    }
        ovalPrevState = oval;








    switch (ent_num) {
        case 1:
        if (ent_num == 1){
            phaseone(customKey);
            }  // Pass key input to function
            break;

        case 2:
        if (ent_num == 2){
            phasetwo();
            }
            break;
        case 3:
        
        if (ent_num == 3){
          phasethree();
        }
        break;
        case 4:
        
        if (ent_num == 4){
          phasefour();
        }
        break;
    }

     
}















// Function to set number of turns
void phaseone(char customKey) {
    lcd.setCursor(0, 0);
    lcd.print(" SET NUMBER OF TURNS ");
    lcd.setCursor(0, 1);
    lcd.print("N0. TURNS:            ");
    lcd.setCursor(11, 1);
    lcd.print(inputTurns); // Display current input
    lcd.setCursor(0, 2);
    lcd.print("                    ");
    lcd.setCursor(0, 3);
    lcd.print("                    ");

    if (customKey) {  // Only act if a key is pressed
        Serial.print("Key Pressed: ");
        Serial.println(customKey);  // Debugging output

        if (customKey >= '0' && customKey <= '9') {
            if (inputTurns.length() < 5) { // Limit to 5 digits
                inputTurns += customKey;
            }
        } else if (customKey == '*') {  // Backspace feature
            if (inputTurns.length() > 0) {
                inputTurns.remove(inputTurns.length() - 1);  // Remove last digit
            }
        } else if (customKey == '#') {  // Confirm input
      
            lcd.setCursor(0, 1);
            lcd.print("Turns Set: " + inputTurns);
            delay(1000);
            // ent_num++;  // Move to next step
        }

          else if (inputTurns.length()> 0){
                storedsteps = inputTurns.toInt() * 800; 
              }           
          else if (isdigit(customKey)) {  // Accept only numbers
                inputTurns += customKey;
            }

        // Update display
        lcd.setCursor(11, 1);
        lcd.print("     "); // Clear previous input
        lcd.setCursor(11, 1);
        lcd.print(inputTurns);
    }
}


void phasetwo() {
    if (selval == HIGH && selPrevState == LOW) { 
        sel_num++;  
        if (sel_num > 3) sel_num = 1;  // Loop selection
        delay(200);  
        lcd.clear();
    }
    selPrevState = selval;


    lcd.setCursor(0, 0);
    lcd.print("TURNS SET: " + inputTurns);
    lcd.setCursor(0, 1);
    lcd.print("SELECT SPEED: ");

    if (sel_num == 1) {
        selectedSpeed = "LOW";
        stepSpeed = 16000;
    } else if (sel_num == 2) {
        selectedSpeed = "MED";
        stepSpeed = 32000;
    } else if (sel_num == 3) {
        selectedSpeed = "HIGH";
        stepSpeed = 64000;
    }

    lcd.print(selectedSpeed); // Display selected speed

    stepperx.setMaxSpeed(stepSpeed);
    stepperx.setAcceleration(stepSpeed / 2);
}




void phasethree (){

    if (oval == HIGH && ovalPrevState == LOW) { 
        oval_num++;  
        if (oval_num > 2) oval_num = 1;
        delay(200);  
        Serial.println(oval_num);
        lcd.clear();
    }
        ovalPrevState = oval;


  lcd.setCursor(0, 0);
  lcd.print("Turns Set:" + inputTurns);
  lcd.setCursor(0, 1);
  lcd.print("Speed Set:" + selectedSpeed);
  lcd.setCursor(0, 2);
  lcd.print("Set Orientation:");

  if (oval_num == 1){
    orientation = "CW";
    digitalWrite(DIRX, LOW);
    Serial.println("cw");
  }
  if (oval_num == 2){
    orientation = "CCW";
    digitalWrite(DIRX, HIGH);
    Serial.println("ccw");
  }
  lcd.print(orientation);
}

void phasefour() {
    lcd.clear();
    
    // Display set parameters
    lcd.setCursor(0, 0);
    lcd.print("Turns Set: " + inputTurns);
    lcd.setCursor(0, 1);
    lcd.print("Speed Set: " + selectedSpeed);
    lcd.setCursor(0, 2);
    lcd.print("Orientation: " + orientation);
    lcd.setCursor(0, 3);
    lcd.print("READY TO RUN");

    Serial.println("Waiting for START button...");

    // Wait for the start button to be pressed
    while (digitalRead(start) == LOW) {
        if (digitalRead(stop) == HIGH) {
            Serial.println("STOP button pressed before starting.");
            return;
        }
    }

    Serial.println("START button pressed. Running...");

    lcd.setCursor(0, 3);
    lcd.print("TURN COUNT: 0");

    digitalWrite(ENAX, LOW); // Enable motor driver X
    digitalWrite(ENAY, LOW); // Enable motor driver Y

    stepperx.setMaxSpeed(stepSpeed);
    stepperx.setAcceleration(stepSpeed / 2);
    steppery.setMaxSpeed(stepSpeed);
    steppery.setAcceleration(stepSpeed / 2);

    long totalSteps = inputTurns.toInt() * 800; // Assuming 800 steps per turn
    stepperx.moveTo(totalSteps);
    steppery.moveTo(totalSteps);

    long turnsCompleted = 0;

    while (stepperx.distanceToGo() > 0 || steppery.distanceToGo() > 0) {
        stepperx.run();
        steppery.run();

        Serial.print("Stepper Position: ");
        Serial.println(stepperx.currentPosition()); // Debug position

        if (stepperx.distanceToGo() > 0) { 
            long newTurnCount = stepperx.currentPosition() / 800; 
            if (newTurnCount != turnsCompleted) {
                turnsCompleted = newTurnCount;
                lcd.setCursor(12, 3);
                lcd.print(turnsCompleted);
                lcd.print("    ");
            }
        }

        if (digitalRead(stop) == HIGH) {
            Serial.println("STOP button pressed. Stopping motor...");
            stepperx.stop();
            steppery.stop();
            lcd.setCursor(0, 3);
            lcd.print("STOPPED!      ");
            return;
        }
        delay(10); // Prevents false increments
    }

    Serial.println("Operation complete.");
    lcd.setCursor(0, 3);
    lcd.print("FINISHED!      ");
    digitalWrite(ENAX, HIGH); // Disable motor driver X
    digitalWrite(ENAY, HIGH); // Disable motor driver Y
}


1 Like

I can't help you but I'm sure that you will get questions like

  1. Please post the specs.
  2. How are you powering everything (wiring diagram might be useful)?
1 Like

thanks ill edit the post

At first glance there are several problems in your code:

int stepSpeed = 16000; // Default stepper speed

Aready that's far too much for AccelStepper on a Mega. At an AVR with 16MHz AccelStepper can reach a max. of maybe 5000 steps/sec for a single stepper ( and that's optimistic ). With two steppers turning at the same time it is only half as much.

        stepSpeed = 64000;

Even worse, as 64000 does not fit into an int.

Be aware, that the .run() method only creates one step at max per call. So all things you do in your while loop slows down the stepper. And you do really a lot there:

  • Serial prints in every loop cycle ( with only 9600 Baud!), which will fill the Serial buffer and block the code.
  • writing to the LCD - which also is slow.
  • a delay(10).
  • ...

No wonder, that your steppers turn very,very slowly.

what should i do?

Hi, @iinoteii
Welcome to the forum

Sorry no.. do not edit an old post.
Make a new post with the requested information.

Thanks... Tom.... :smiley: :+1: :coffee: :australia:

Tell us more about your project. And what rpm for the steppers do you really need? Why are there two steppers?
Than we can give some advices.

it is a coil winding machine the nema 23 is for the bobbin or winding head and the nema 17 is for the movement of the wire feeder as for the rpm I'm not quite sure yet what is applicable as I currently focusing on code. later on I want the nema 17 which is the steppery in the code to change direction if the conductive proximity sensor sense an object

Can you post a photo of your mechanics?

Well, the needed rpm are important when focusing on the code :wink:

If 2500 steps/sec is sufficent, you may try the MobaTools library for your steppers. With 800steps/rev this is 187 rpm. Because this lib creates the step pulses via timer interrupt in the background, coding the other tasks is more easy, because you need not care about creating the step pulses in your .ino code.

If you need faster steprates, you may need a more powerful board. There are also other libraries, that can create faster step rates, but usually they have other limitations.