Stepper motors runing too slow. Why if they are fast wth GRBL?

Hello there!

I'm currently using a setup of 2 stepper motors with DM556 drivers, 24V 10A power supply, and arduino Uno.
In my project I was using GRBL to control those steppers in a machine to make bowstrings for archery.
I'm using macros to make them spin for a long distance sincronized in the same direction. And with another macro to spin for 10 turns each in oposite directions. It was enough for me to do the job, but I decided to try to run it standalone, without a PC and the GRBL, but the speeds using regular libraries like Stepper.h, AccelStepper, or SpeedyStepper does not gave me the same speeds as with the GRBL.
I'm not a programmer and I'm actually using ChatGPT to generate the sketches.

I was trying to edit the GRBL's source code to include just the buttons I need to control the steppers without the need of a PC, but it's very hard for me as a non programer guy.

Is there any faster library to use with?

Here is the best I found with the SpeedyStepper.h library but now reaching just half of the speed I was expecting and with very noisy results.

#include <SpeedyStepper.h>

// Definições dos pinos
const int LED_NORMAL_PIN = 0;       // LED para indicar rotação normal
const int LED_INVERT_PIN = 1;       // LED para indicar rotação invertida
const int STEP_PIN1 = 2;            // Pulso motor 1
const int DIR_PIN1 = 5;             // Direcao motor 1
const int STEP_PIN2 = 3;            // Pulso motor 2
const int DIR_PIN2 = 6;             // Direcao motor 2
const int BUTTON_PIN = 8;           // Botão para iniciar/parar os motores
const int NEW_BUTTON_PIN_1 = 9;      // Botão para iniciar/parar os motores com 50% da velocidade
const int NEW_BUTTON_PIN_2 = 10;     // Botão para ligar/desligar os motores com 25% da velocidade
const int NEW_BUTTON_PIN_3 = 11;     // Botão para ligar/desligar os motores com 10% da velocidade
const int TEN_ROTATE_BUTTON_PIN = 12; // Botão para girar os motores por 10 voltas em sentidos opostos
const int ONE_ROTATE_BUTTON_PIN = 7; // Botão para girar os motores por 1 volta em sentidos opostos
const int ROTATE_BUTTON_PIN = A0;    // Botão para inverter o sentido de rotação dos motores
const int EMERGENCY_STOP_PIN = A1;   // Botão de emergência


SpeedyStepper stepper1;
SpeedyStepper stepper2;

bool motorRunning = false;
bool invertDirection = false;  // Controla a inversão de sentido de ambos os motores
bool lastButtonState = HIGH;
bool lastNewButtonState1 = HIGH;
bool lastNewButtonState2 = HIGH;
bool lastNewButtonState3 = HIGH;
bool lastRotateButtonState = HIGH;
bool lastOneRotateButtonState = HIGH;
bool lastTenRotateButtonState = HIGH;
bool lastEmergencyStopState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 500;

const int MAX_SPEED = 6000;
const int QUARTER_MAX_SPEED = MAX_SPEED / 5;
const int ACCELERATION = 10000;
const int QUICK_DECELERATION = 16000;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_1, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_2, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_3, INPUT_PULLUP);
  pinMode(ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(EMERGENCY_STOP_PIN, INPUT_PULLUP);
  pinMode(ONE_ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(TEN_ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_NORMAL_PIN, OUTPUT);
  pinMode(LED_INVERT_PIN, OUTPUT);

  stepper1.connectToPins(STEP_PIN1, DIR_PIN1);
  stepper2.connectToPins(STEP_PIN2, DIR_PIN2);

  stepper1.setSpeedInStepsPerSecond(MAX_SPEED);
  stepper1.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);

  stepper2.setSpeedInStepsPerSecond(MAX_SPEED);
  stepper2.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
}

void toggleMotors(bool run, int speed, bool invert) {
  if (run) {
    // Define a velocidade para ambos os motores
    stepper1.setSpeedInStepsPerSecond(speed);
    stepper2.setSpeedInStepsPerSecond(speed);

    // Movimento relativo com base na direção atual dos motores
    stepper1.setupRelativeMoveInSteps(invert ? -200000 : 200000);
    stepper2.setupRelativeMoveInSteps(invert ? 200000 : -200000);
  } else {
    // Para o movimento dos motores com desaceleração rápida
    stepper1.setAccelerationInStepsPerSecondPerSecond(QUICK_DECELERATION);
    stepper2.setAccelerationInStepsPerSecondPerSecond(QUICK_DECELERATION);
    stepper1.setupStop();
    stepper2.setupStop();
    // Volta à aceleração normal
    stepper1.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
    stepper2.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
  }
}

void rotateMotors(int numVoltas) {
  // Configura uma nova velocidade para girar os motores
  stepper1.setSpeedInStepsPerSecond(QUARTER_MAX_SPEED);
  stepper2.setSpeedInStepsPerSecond(QUARTER_MAX_SPEED);

  // Calcula o número de passos necessário para as voltas desejadas
  long numPassos = numVoltas * 200; // 200 passos por volta (exemplo)

  // Move os motores relativamente e simultaneamente
  stepper1.setupRelativeMoveInSteps(invertDirection ? -numPassos : numPassos);
  stepper2.setupRelativeMoveInSteps(invertDirection ? -numPassos : numPassos); // Movimento no sentido oposto se invertDirection for true

  // Inicia o movimento simultaneamente
  while ((!stepper1.motionComplete()) || (!stepper2.motionComplete())) {
    stepper1.processMovement();
    stepper2.processMovement();
  }
}

void emergencyStop() {
  stepper1.setAccelerationInStepsPerSecondPerSecond(QUICK_DECELERATION);
  stepper2.setAccelerationInStepsPerSecondPerSecond(QUICK_DECELERATION);
  stepper1.setupStop();
  stepper2.setupStop();
  stepper1.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
  stepper2.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
  motorRunning = false;
}

void updateLEDs() {
  digitalWrite(LED_NORMAL_PIN, invertDirection ? LOW : HIGH);
  digitalWrite(LED_INVERT_PIN, invertDirection ? HIGH : LOW);
}

void loop() {
  bool buttonState = digitalRead(BUTTON_PIN);
  bool newButtonState1 = digitalRead(NEW_BUTTON_PIN_1);
  bool newButtonState2 = digitalRead(NEW_BUTTON_PIN_2);
  bool newButtonState3 = digitalRead(NEW_BUTTON_PIN_3);
  bool rotateButtonState = digitalRead(ROTATE_BUTTON_PIN);
  bool oneRotateButtonState = digitalRead(ONE_ROTATE_BUTTON_PIN);
  bool tenRotateButtonState = digitalRead(TEN_ROTATE_BUTTON_PIN);
  bool emergencyStopState = digitalRead(EMERGENCY_STOP_PIN);
  unsigned long currentMillis = millis();

  if (emergencyStopState == LOW && lastEmergencyStopState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    emergencyStop();
    lastDebounceTime = currentMillis;
  }

  if (rotateButtonState == LOW && lastRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    invertDirection = !invertDirection; // Inverte o sentido de rotação armazenado
    updateLEDs(); // Atualiza os LEDs
    lastDebounceTime = currentMillis;
  }

  if (buttonState == LOW && lastButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (newButtonState1 == LOW && lastNewButtonState1 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 2, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (newButtonState2 == LOW && lastNewButtonState2 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 4, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (newButtonState3 == LOW && lastNewButtonState3 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 10, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (oneRotateButtonState == LOW && lastOneRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    rotateMotors(1); // Exemplo: Girar 1 volta
    lastDebounceTime = currentMillis;
  }

  if (tenRotateButtonState == LOW && lastTenRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    rotateMotors(10); // Exemplo: Girar 10 voltas
    lastDebounceTime = currentMillis;
  }

  lastButtonState = buttonState;
  lastNewButtonState1 = newButtonState1;
  lastNewButtonState2 = newButtonState2;
  lastNewButtonState3 = newButtonState3;
  lastRotateButtonState = rotateButtonState;
  lastOneRotateButtonState = oneRotateButtonState;
  lastTenRotateButtonState = tenRotateButtonState;
  lastEmergencyStopState = emergencyStopState;

  stepper1.processMovement();
  stepper2.processMovement();
}
  digitalWrite(LED_NORMAL_PIN, !invertDirection);
  digitalWrite(LED_INVERT_PIN, invertDirection);

this can be read in one go:

byte ButtonStates = PINB&B11111; 

of course better to place all buttons/switches on one register, D have 8 accessible pins, enough for your project.
and than instead of:

  lastButtonState = buttonState;
  lastNewButtonState1 = newButtonState1;
  lastNewButtonState2 = newButtonState2;
  lastNewButtonState3 = newButtonState3;
  lastRotateButtonState = rotateButtonState;
  lastOneRotateButtonState = oneRotateButtonState;
  lastTenRotateButtonState = tenRotateButtonState;
  lastEmergencyStopState = emergencyStopState;

using

byte LastButtonStates = ButtonStates;

before you implement library to your project, test it, examine how quick you can spin motors

Thank you @kolaha ! I will try this

Depending on what arduino you're using, there's also FastDigitalWrite(pin) as an option. MUCH faster.

I just got around 880rpms in my original code. I tried FastDigitalWrite and reached about 1070rpm's, but some functionalities of my original code wasnt available with it.

Let me try to explain my thoughts:

I have a ready Arduino code that uses the SpeedyStepper.h library to achieve higher speeds for the stepper motors I use, but I am not satisfied with the speeds and acceleration ramps obtained with this library, although the logic of the code is satisfactory.

I already tried to use two arduinos connected to use one with my code as a remote control with all the buttons I need, and another one with GRBL as the main device with the motors attached to.

I want to try replacing the SpeedyStepper library with the some of the GRBL library source font, which allows for much better and faster stepper motor movements. Is it possible to include this library in the following code and take advantage of its benefits? Or just modifiy the original GRBL to use with the additional buttons?
Is there anything contained in GRBL's source code that we can use and perhaps create a new library that optimizes the speed of the stepper motors?
Wich files on the GRBL's library I should modify to include the buttons?

In my code, I need the following operating modes:

  • Button 1 - "100% Free Spin" - move two stepper motors in opposite directions at 100% speed for an indefinite period
  • Button 2 - "50% Free Spin" - move two stepper motors in opposite directions at 50% speed for an indefinite period
  • Button 3 - "25% Free Spin" - move two stepper motors in opposite directions at 25% speed for an indefinite period
  • Button 4 - "10% Free Spin" - move two stepper motors in opposite directions at 10% speed for an indefinite period
  • Button 5 - "10 Turns Twist" - move two stepper motors 5 turns in the same direction at 10% speed
  • Button 6 - "1 Turn Twist" - move two stepper motors 1 turn in the same direction at 10% speed
  • Button 7 - "Reverse Direction" - reverse the rotation direction of the two stepper motors for all previous modes
  • Button 8 - "Emergency Stop" - stop the movement of the two stepper motors with programmable deceleration
  • Potentiometer - a potentiometer to change the maximum speed programmed in the code for all the above modes and buttons
#include <SoftwareSerial.h>
#include <TimerOne.h>  // Biblioteca para o timer

// Definições dos pinos
const int BUTTON_PIN = 4;              // Botão para iniciar/parar os motores
const int NEW_BUTTON_PIN_1 = 5;        // Novo botão para iniciar/parar os motores com 50% da velocidade
const int NEW_BUTTON_PIN_2 = 6;        // Novo botão para ligar/desligar os motores com 25% da velocidade
const int NEW_BUTTON_PIN_3 = 8;        // Novo botão para ligar/desligar os motores com 10% da velocidade
//espaco
const int ONE_ROTATE_BUTTON_PIN = 7;   // Botão para girar os motores por 1/2 volta em sentidos opostos
const int TEN_ROTATE_BUTTON_PIN = 9;  // Botão para girar os motores por 5 voltas em sentidos opostos
//espaco
const int EMERGENCY_STOP_PIN = 12;     // Botão de emergência
//espaco
const int ROTATE_BUTTON_PIN = 11;      // Botão para inverter o sentido de rotação dos motores
//espaco
const int GRBL_RESET_PIN = 13;          // Pino digital no Arduino de controle remoto conectado ao reset do Arduino com GRBL
const int LED_NORMAL_PIN = 20;         // LED para indicar rotação normal
const int LED_INVERT_PIN = 21;         // LED para indicar rotação invertida

// Parâmetros de velocidade
const int MAX_SPEED = 1500;            // mm/min (ajustado para teste, ajuste conforme necessário)
const int ACCELERATION = 1000;         // mm/s^2 (ajustado para teste, ajuste conforme necessário)
const int QUICK_DECELERATION = 6000;   // mm/s^2 (ajustado para teste, ajuste conforme necessário)

bool motorRunning = false;
bool invertDirection = false;         // Controla a inversão de sentido de ambos os motores
bool lastButtonState = HIGH;
bool lastNewButtonState1 = HIGH;
bool lastNewButtonState2 = HIGH;
bool lastNewButtonState3 = HIGH;
bool lastRotateButtonState = HIGH;
bool lastOneRotateButtonState = HIGH;
bool lastTenRotateButtonState = HIGH;
bool lastEmergencyStopState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 500;    // Reduzido para 100ms para debounce mais rápido

SoftwareSerial grblSerial(2, 3);      // RX, TX para comunicação com Arduino 1

// Protótipos das funções
void rotateMotorsOneTurn();
void rotateMotorsTenTurns();

// Declaração da função timerCallback
void timerCallback() {
  // Nenhuma ação necessária aqui neste exemplo
}

void setup() {
  Serial.begin(115200);       // Comunicação serial para monitoramento
  grblSerial.begin(115200);   // Comunicação serial com GRBL

  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_1, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_2, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_3, INPUT_PULLUP);
  pinMode(ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(EMERGENCY_STOP_PIN, INPUT_PULLUP);
  pinMode(ONE_ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(TEN_ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_NORMAL_PIN, OUTPUT);
  pinMode(LED_INVERT_PIN, OUTPUT);
  pinMode(GRBL_RESET_PIN, OUTPUT);
  digitalWrite(GRBL_RESET_PIN, HIGH);  // Garantir que o reset esteja em estado alto inicialmente

  // Configuração do timer para chamar a função a cada segundo (1000000 microssegundos)
  Timer1.initialize(1000000);             // Configura o timer para chamar a função a cada segundo
  Timer1.attachInterrupt(timerCallback);  // Associa a função timerCallback ao timer

  // Mensagens iniciais
  Serial.println("Sistema iniciado. Aguardando comandos...");
  
  // Inicializar LEDs
  updateLEDs();
}

void sendGcode(const char* gcode) {
  Serial.println(gcode);        // Para monitoramento
  grblSerial.println(gcode);    // Enviar comando para GRBL
  delay(50);                    // Pequeno atraso para garantir que o comando foi enviado
}

void toggleMotors(bool run, int speed, bool invert) {
  if (run) {
    sendGcode("G91");           // Modo de coordenadas relativo
    char gcode[50];
    sprintf(gcode, "G1 F%d", speed);   // Define a velocidade de avanço
    sendGcode(gcode);

    // Movimento relativo com base na direção atual dos motores
    sprintf(gcode, "G1 X%d Y%d", invert ? -200 : 200, invert ? 200 : -200);  // Exemplo de comando G-code
    sendGcode(gcode);

    sendGcode("G90");           // Retornar ao modo absoluto
  } else {
    //sendGcode("M5");           // Parar os motores
  }
}

void rotateMotorsOneTurn() {
  char gcode[50];
  sprintf(gcode, "G1 F150");  // Define a velocidade de avanço
  sendGcode(gcode);

  // Número de passos por volta (ajuste conforme necessário)
  float numPassos = 0.5;  

  // Multiplicamos por 100 para tratar o valor como inteiro e evitar problemas com sprintf e float
  int xSteps = int(numPassos * 100);
  int ySteps = int(-numPassos * 100);

  sprintf(gcode, "G91 G1 X%d.%02d Y%d.%02d", xSteps / 100, abs(xSteps % 100), ySteps / 100, abs(ySteps % 100));
  sendGcode(gcode);

  // Retornar ao modo absoluto após a rotação
  sendGcode("G90");
}

void rotateMotorsTenTurns() {
  char gcode[50];
  sprintf(gcode, "G1 F150");  // Define a velocidade de avanço
  sendGcode(gcode);

  // Número de passos por volta (ajuste conforme necessário)
  float numPassos = 5.0;  

  // Multiplicamos por 100 para tratar o valor como inteiro e evitar problemas com sprintf e float
  int xSteps = int(numPassos * 100);
  int ySteps = int(-numPassos * 100);

  sprintf(gcode, "G91 G1 X%d.%02d Y%d.%02d", xSteps / 100, abs(xSteps % 100), ySteps / 100, abs(ySteps % 100));
  sendGcode(gcode);

  // Retornar ao modo absoluto após a rotação
  sendGcode("G90");
}


void emergencyStop() {
  Serial.println("Botão de emergência pressionado");
  if (motorRunning) {
    Serial.println("Enviando comando de pausa...");
    sendGcode("!");             // Enviar comando de pausa
    delay(1000);                // Aguardar um pouco para garantir que o comando de pausa foi processado

    // Acionar o reset do GRBL
    Serial.println("Ativando reset do GRBL...");
    digitalWrite(GRBL_RESET_PIN, LOW);    // Acionar o reset
    delay(50);                            // Manter o reset ativo por um curto período
    digitalWrite(GRBL_RESET_PIN, HIGH);   // Liberar o reset

    // Aguardar um breve momento após o reset antes de continuar
    delay(50);

    // Reiniciar o estado dos motores, se necessário
    motorRunning = false;
  } else {
    // Se os motores não estavam em execução, apenas enviar o comando de pausa
    Serial.println("Enviando comando de pausa...");
    sendGcode("!");             // Enviar comando de pausa
    delay(50);                  // Aguardar um pouco para garantir que o comando de pausa foi processado
  }
}

void updateLEDs() {
  digitalWrite(LED_NORMAL_PIN, invertDirection ? LOW : HIGH);
  digitalWrite(LED_INVERT_PIN, invertDirection ? HIGH : LOW);
}

void loop() {
  bool buttonState = digitalRead(BUTTON_PIN);
  bool newButtonState1 = digitalRead(NEW_BUTTON_PIN_1);
  bool newButtonState2 = digitalRead(NEW_BUTTON_PIN_2);
  bool newButtonState3 = digitalRead(NEW_BUTTON_PIN_3);
  bool rotateButtonState = digitalRead(ROTATE_BUTTON_PIN);
  bool oneRotateButtonState = digitalRead(ONE_ROTATE_BUTTON_PIN);
  bool tenRotateButtonState = digitalRead(TEN_ROTATE_BUTTON_PIN);
  bool emergencyStopState = digitalRead(EMERGENCY_STOP_PIN);
  unsigned long currentTime = millis();

  if (buttonState != lastButtonState && (currentTime - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = currentTime;
    if (buttonState == LOW) {
      Serial.println("Girando os motores com 100% da velocidade");
      motorRunning = !motorRunning;
      toggleMotors(motorRunning, MAX_SPEED, invertDirection);
    }
  }

  if (newButtonState1 != lastNewButtonState1 && (currentTime - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = currentTime;
    if (newButtonState1 == LOW) {
      Serial.println("Girando os motores com 50% da velocidade");
      motorRunning = !motorRunning;
      toggleMotors(motorRunning, MAX_SPEED / 2, invertDirection);
    }
  }

  if (newButtonState2 != lastNewButtonState2 && (currentTime - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = currentTime;
    if (newButtonState2 == LOW) {
      Serial.println("Girando os motores com 25% da velocidade");
      motorRunning = !motorRunning;
      toggleMotors(motorRunning, MAX_SPEED / 4, invertDirection);
    }
  }

  if (newButtonState3 != lastNewButtonState3 && (currentTime - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = currentTime;
    if (newButtonState3 == LOW) {
      Serial.println("Girando os motores com 10% da velocidade");
      motorRunning = !motorRunning;
      toggleMotors(motorRunning, MAX_SPEED / 10, invertDirection);
    }
  }

  if (rotateButtonState != lastRotateButtonState && (currentTime - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = currentTime;
    if (rotateButtonState == LOW) {
      Serial.println("Invertendo o sentido de rotação dos motores");
      invertDirection = !invertDirection;
      updateLEDs();  // Atualizar LEDs
      if (motorRunning) {
        toggleMotors(motorRunning, MAX_SPEED, invertDirection);
      }
    }
  }

  if (oneRotateButtonState != lastOneRotateButtonState && (currentTime - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = currentTime;
    if (oneRotateButtonState == LOW) {
      Serial.println("Girando os motores por 1/2 volta em sentidos opostos");
      rotateMotorsOneTurn();  // Chamar a função para girar meio volta
    }
  }

  if (tenRotateButtonState != lastTenRotateButtonState && (currentTime - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = currentTime;
    if (tenRotateButtonState == LOW) {
      Serial.println("Girando os motores por 5 voltas em sentidos opostos");
      rotateMotorsTenTurns();  // Chamar a função para girar cinco voltas
    }
  }

  if (emergencyStopState != lastEmergencyStopState && (currentTime - lastDebounceTime) > debounceDelay) {
    lastDebounceTime = currentTime;
    if (emergencyStopState == LOW) {
      Serial.println("Botão de emergência pressionado");
      emergencyStop();  // Chamar a função para o botão de emergência
    }
  }

  lastButtonState = buttonState;
  lastNewButtonState1 = newButtonState1;
  lastNewButtonState2 = newButtonState2;
  lastNewButtonState3 = newButtonState3;
  lastRotateButtonState = rotateButtonState;
  lastOneRotateButtonState = oneRotateButtonState;
  lastTenRotateButtonState = tenRotateButtonState;
  lastEmergencyStopState = emergencyStopState;
}

In the following code, I got around 1070 rpms but I lost the functionalities of pins A1, A3 and 13.

"By migrating to the faster and optimized version of the code using digitalWriteFast.h and reading the pin states with PINB, I lost the ability to use pins A1, A3, and 13. This happens because digitalWriteFast.h and direct port manipulation (PINB) are incompatible with using analog pins A1 and A3, as well as pin 13, which is usually shared with the built-in LED on Arduino boards."

#include <SpeedyStepper.h>
#include <digitalWriteFast.h>

// Definições dos pinos
const int LED_NORMAL_PIN = A2;
const int LED_INVERT_PIN = A0;
const int STEP_PIN1 = 2;
const int DIR_PIN1 = 5;
const int STEP_PIN2 = 4;
const int DIR_PIN2 = 7;
const int BUTTON_PIN = 11;
const int NEW_BUTTON_PIN_1 = 10;
const int NEW_BUTTON_PIN_2 = 9;
const int NEW_BUTTON_PIN_3 = 12;
const int TEN_ROTATE_BUTTON_PIN = A3;
const int ONE_ROTATE_BUTTON_PIN = A1;
const int ROTATE_BUTTON_PIN = 13;
const int EMERGENCY_STOP_PIN = 14;

SpeedyStepper stepper1;
SpeedyStepper stepper2;

bool motorRunning = false;
bool invertDirection = false;
bool lastButtonState = HIGH;
bool lastNewButtonState1 = HIGH;
bool lastNewButtonState2 = HIGH;
bool lastNewButtonState3 = HIGH;
bool lastRotateButtonState = HIGH;
bool lastOneRotateButtonState = HIGH;
bool lastTenRotateButtonState = HIGH;
bool lastEmergencyStopState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 500;

const int MAX_SPEED = 8000;
const int QUARTER_MAX_SPEED = MAX_SPEED / 5;
const int ACCELERATION = 10000;
const int QUICK_DECELERATION = 16000;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_1, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_2, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_3, INPUT_PULLUP);
  pinMode(ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(EMERGENCY_STOP_PIN, INPUT_PULLUP);
  pinMode(ONE_ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(TEN_ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_NORMAL_PIN, OUTPUT);
  pinMode(LED_INVERT_PIN, OUTPUT);

  stepper1.connectToPins(STEP_PIN1, DIR_PIN1);
  stepper2.connectToPins(STEP_PIN2, DIR_PIN2);

  stepper1.setSpeedInStepsPerSecond(MAX_SPEED);
  stepper1.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);

  stepper2.setSpeedInStepsPerSecond(MAX_SPEED);
  stepper2.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
}

void toggleMotors(bool run, int speed, bool invert) {
  if (run) {
    stepper1.setSpeedInStepsPerSecond(speed);
    stepper2.setSpeedInStepsPerSecond(speed);
    stepper1.setupRelativeMoveInSteps(invert ? -200000 : 200000);
    stepper2.setupRelativeMoveInSteps(invert ? 200000 : -200000);
  } else {
    stepper1.setAccelerationInStepsPerSecondPerSecond(QUICK_DECELERATION);
    stepper2.setAccelerationInStepsPerSecondPerSecond(QUICK_DECELERATION);
    stepper1.setupStop();
    stepper2.setupStop();
    stepper1.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
    stepper2.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
  }
}

void rotateMotors(int numVoltas) {
  stepper1.setSpeedInStepsPerSecond(QUARTER_MAX_SPEED);
  stepper2.setSpeedInStepsPerSecond(QUARTER_MAX_SPEED);
  long numPassos = numVoltas * 200;
  stepper1.setupRelativeMoveInSteps(invertDirection ? -numPassos : numPassos);
  stepper2.setupRelativeMoveInSteps(invertDirection ? -numPassos : numPassos);
  while ((!stepper1.motionComplete()) || (!stepper2.motionComplete())) {
    stepper1.processMovement();
    stepper2.processMovement();
  }
}

void emergencyStop() {
  stepper1.setAccelerationInStepsPerSecondPerSecond(QUICK_DECELERATION);
  stepper2.setAccelerationInStepsPerSecondPerSecond(QUICK_DECELERATION);
  stepper1.setupStop();
  stepper2.setupStop();
  stepper1.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
  stepper2.setAccelerationInStepsPerSecondPerSecond(ACCELERATION);
  motorRunning = false;
}

void updateLEDs() {
  digitalWriteFast(LED_NORMAL_PIN, !invertDirection);
  digitalWriteFast(LED_INVERT_PIN, invertDirection);
}

void loop() {
  // Lê os estados dos pinos 8 a 12 simultaneamente
  byte buttonStates = PINB & B11111;

  // Extrai os estados individuais dos botões
  bool buttonState = bitRead(buttonStates, BUTTON_PIN - 8);
  bool newButtonState1 = bitRead(buttonStates, NEW_BUTTON_PIN_1 - 8);
  bool newButtonState2 = bitRead(buttonStates, NEW_BUTTON_PIN_2 - 8);
  bool newButtonState3 = bitRead(buttonStates, NEW_BUTTON_PIN_3 - 8);
  bool rotateButtonState = bitRead(buttonStates, ROTATE_BUTTON_PIN - 8);
  bool oneRotateButtonState = bitRead(buttonStates, ONE_ROTATE_BUTTON_PIN - 8);
  bool tenRotateButtonState = bitRead(buttonStates, TEN_ROTATE_BUTTON_PIN - 8);
  bool emergencyStopState = digitalReadFast(EMERGENCY_STOP_PIN);
  unsigned long currentMillis = millis();

  if (emergencyStopState == LOW && lastEmergencyStopState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    emergencyStop();
    lastDebounceTime = currentMillis;
  }

  if (rotateButtonState == LOW && lastRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    invertDirection = !invertDirection;
    updateLEDs();
    lastDebounceTime = currentMillis;
  }

  if (buttonState == LOW && lastButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (newButtonState1 == LOW && lastNewButtonState1 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 2, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (newButtonState2 == LOW && lastNewButtonState2 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 4, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (newButtonState3 == LOW && lastNewButtonState3 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 10, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (oneRotateButtonState == LOW && lastOneRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    rotateMotors(1);
    lastDebounceTime = currentMillis;
  }

  if (tenRotateButtonState == LOW && lastTenRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    rotateMotors(10);
    lastDebounceTime = currentMillis;
  }

  lastButtonState = buttonState;
  lastNewButtonState1 = newButtonState1;
  lastNewButtonState2 = newButtonState2;
  lastNewButtonState3 = newButtonState3;
  lastRotateButtonState = rotateButtonState;
  lastOneRotateButtonState = oneRotateButtonState;
  lastTenRotateButtonState = tenRotateButtonState;
  lastEmergencyStopState = emergencyStopState;

  stepper1.processMovement();
  stepper2.processMovement();
}

From that, I'm assuming you're unable to juggle your pins to do fastDigital where it matters(for example, push some of the buttons up to the analogs, use the digitals for digital outputs), or that you're not willing to. Sorry, can't help much more.
Took a look at your IO assignment, sorted it in pin order:

const int STEP_PIN1 = 2;
const int STEP_PIN2 = 4;
const int DIR_PIN1 = 5;
const int DIR_PIN2 = 7;
const int NEW_BUTTON_PIN_2 = 9;
const int NEW_BUTTON_PIN_1 = 10;
const int BUTTON_PIN = 11;
const int NEW_BUTTON_PIN_3 = 12;
const int ROTATE_BUTTON_PIN = 13;
const int EMERGENCY_STOP_PIN = 14;
const int LED_INVERT_PIN = A0;
const int ONE_ROTATE_BUTTON_PIN = A1;
const int LED_NORMAL_PIN = A2;
const int TEN_ROTATE_BUTTON_PIN = A3;

Seems like you have some holes in the list(pins 3, 6, 8), but maybe they're for other things?
Certainly this:

const int EMERGENCY_STOP_PIN = 14;
const int LED_INVERT_PIN = A0;

makes me wonder.

GRBL also optimizes the step/DIR writing to multiple steppers by putting them on PORTD bits 2-7. By using the Bresenham algorithm, the accelerations only need be calculated for the fastest axis, and all the rest of the moves are slaved to that fast axis, and the single PORTD write simultaneously steps one, two, or three steppers as needed.

I would think that all axes would be slaved to the slowest axis. If you tried to make them all go as fast as the fastest axis, the slow ones would fail.

How does the GRBL determine which axis to use as the master, or is it designated by the designer?

That's in the magic of the Bresenham algorithm. The fastest axis needs to step at a higher frequency than the slower axes, and the slower axes are at some integer ratio slower than the fast axis. If the Y axis is 1/2 as fast/far as the X axis, step Y every other time you step X, etc...

I'm not sure how GRBL's internals actuall does it exactly but when I was playing with it, I found it was easy to setup the math with an extra virtual axis and let all of the other axes follow off of it:

Thank you guys for your replys! But I´m really looking for a way to customize the GRBL code to include some phisical buttons to a single arduino with the GRBL installed on it, and wanna know wich files I should edit to include my code?

Is there a simple way to do it? As I said, I´m not a programmer and I´m actually using CHAT-GPT to help me generate those codes. And asking to it about to edit the GRBL´s source code, it gave me these answers:

  1. Download and Prepare the GRBL Source Code First, download the GRBL source code from the official GRBL repository on GitHub. Extract the content and open it in your Arduino development environment.
  2. Configure the Pins for the Buttons You can define the button pins in the config.h file or directly in the main firmware file. We will define the pins directly in the code for simplicity.
  3. Add the Button Reading Logic You need to add the button reading logic and G-code command sending in the main loop of GRBL. To do this, you can modify the report.c file (or another suitable file that contains the report_status_message function).

Here is an example of how to add this logic:

Step 1: Define the button pins and other constants At the beginning of the report.c file (or another suitable file), add the definitions for the button pins and other constants:

#include <Arduino.h> // Certifique-se de incluir a biblioteca Arduino

const int BUTTON_PIN = 4;
const int NEW_BUTTON_PIN_1 = 7;
const int NEW_BUTTON_PIN_2 = 8;
const int NEW_BUTTON_PIN_3 = 9;
const int ROTATE_BUTTON_PIN = 13;
const int EMERGENCY_STOP_PIN = 12;
const int ONE_ROTATE_BUTTON_PIN = 11;
const int TEN_ROTATE_BUTTON_PIN = 10;

const int MAX_SPEED = 4000; // mm/min
const int QUARTER_MAX_SPEED = MAX_SPEED / 4;
bool invertDirection = false;  // Controla a inversão de sentido de ambos os motores
bool motorRunning = false;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_1, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_2, INPUT_PULLUP);
  pinMode(NEW_BUTTON_PIN_3, INPUT_PULLUP);
  pinMode(ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(EMERGENCY_STOP_PIN, INPUT_PULLUP);
  pinMode(ONE_ROTATE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(TEN_ROTATE_BUTTON_PIN, INPUT_PULLUP);
  
  Serial.begin(115200);
}

void sendGcode(const char* gcode) {
  Serial.println(gcode); // Para monitoramento
  grblSerial.println(gcode); // Enviar comando para GRBL
  delay(50); // Pequeno atraso para garantir que o comando foi enviado
}

void toggleMotors(bool run, int speed, bool invert) {
  if (run) {
    sendGcode("G91"); // Modo de coordenadas relativo
    char gcode[50];
    sprintf(gcode, "G1 F%d", speed); // Define a velocidade de avanço
    sendGcode(gcode);

    // Movimento relativo com base na direção atual dos motores
    sprintf(gcode, "G1 X%d Y%d", invert ? -2000 : 2000, invert ? 2000 : -2000); // Exemplo de comando G-code
    sendGcode(gcode);

    sendGcode("G90"); // Retornar ao modo absoluto
  } else {
    sendGcode("M5"); // Parar os motores
  }
}

void rotateMotors(int numVoltas) {
  char gcode[50];
  sprintf(gcode, "G1 F%d", QUARTER_MAX_SPEED); // Define a velocidade de avanço
  sendGcode(gcode);

  long numPassos = numVoltas * 200; // 200 passos por volta (exemplo)

  sprintf(gcode, "G91 G1 X%d Y%d", invertDirection ? -numPassos : numPassos, invertDirection ? numPassos : -numPassos); // Exemplo de comando G-code
  sendGcode(gcode);

  // Retornar ao modo absoluto após a rotação
  sendGcode("G90");
}

void emergencyStop() {
  sendGcode("!"); // Comando de pausa em GRBL
  motorRunning = false;
}

Step 2: Add the Button Reading Logic in the Main Loop
In the main loop (usually located in report.c or grbl_main.c), add the logic to read the button states and send the corresponding G-code commands:

Copy code
void loop() {
  bool buttonState = digitalRead(BUTTON_PIN);
  bool newButtonState1 = digitalRead(NEW_BUTTON_PIN_1);
  bool newButtonState2 = digitalRead(NEW_BUTTON_PIN_2);
  bool newButtonState3 = digitalRead(NEW_BUTTON_PIN_3);
  bool rotateButtonState = digitalRead(ROTATE_BUTTON_PIN);
  bool oneRotateButtonState = digitalRead(ONE_ROTATE_BUTTON_PIN);
  bool tenRotateButtonState = digitalRead(TEN_ROTATE_BUTTON_PIN);
  bool emergencyStopState = digitalRead(EMERGENCY_STOP_PIN);
  unsigned long currentMillis = millis();

  if (emergencyStopState == LOW && lastEmergencyStopState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    emergencyStop();
    lastDebounceTime = currentMillis;
  }

  if (rotateButtonState == LOW && lastRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    invertDirection = !invertDirection; // Inverte o sentido de rotação armazenado
    updateLEDs(); // Atualiza os LEDs
    lastDebounceTime = currentMillis;
  }

  if (buttonState == LOW && lastButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    // Comando customizado para o botão do pino 4
    sendGcode("$G");
    sendGcode("G10 P0 L20 X0 Y0 Z0");
    sendGcode("G1 X-1000 Y1000 F1500");
    sendGcode("G10 P0 L20 X0 Y0 Z0");
    lastDebounceTime = currentMillis;
  }

  if (newButtonState1 == LOW && lastNewButtonState1 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 2, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (newButtonState2 == LOW && lastNewButtonState2 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 4, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (newButtonState3 == LOW && lastNewButtonState3 == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    motorRunning = !motorRunning;
    toggleMotors(motorRunning, MAX_SPEED / 10, invertDirection);
    lastDebounceTime = currentMillis;
  }

  if (oneRotateButtonState == LOW && lastOneRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    rotateMotors(1); // Exemplo: Girar 1 volta
    lastDebounceTime = currentMillis;
  }

  if (tenRotateButtonState == LOW && lastTenRotateButtonState == HIGH && currentMillis - lastDebounceTime > debounceDelay) {
    rotateMotors(10); // Exemplo: Girar 10 voltas
    lastDebounceTime = currentMillis;
  }

  lastButtonState = buttonState;
  lastNewButtonState1 = newButtonState1;
  lastNewButtonState2 = newButtonState2;
  lastNewButtonState3 = newButtonState3;
  lastRotateButtonState = rotateButtonState;
  lastOneRotateButtonState = oneRotateButtonState;
  lastTenRotateButtonState = tenRotateButtonState;
  lastEmergencyStopState = emergencyStopState;
}

step 3: Compile and upload the code

I already tried that, but was unable to compile and upload the grblUpload.ino file