 # Serial commands from serial monitor queuing

Hi there!
I'm trying to build my own G-code interpreter in which the commands have to come from Arduino serial Monitor.
The problem is if I send a command while the other is being executed the current execution stops and execute the command I just sent.

I want it to queue the commands that the commands sent must wait until current execution finishes then execute the next command.

I want to build A CNC punching machine using Stepper motors-lead screw drive and a hydraulic cylinder whose stroke is controlled by opening and closing a valve. Arduino Mega is the controller.
The code I've written so far is shown below which I used accelstepper library and some arduino builtin functions. However, I've not yet written valve control chunk of code, I think it won't be difficult because it is just ON or OFF control(HIGH or LOW)

Could anyone help me to implement command queuing that every comands wait for the other to be executed first?

The code I've written so far is shown below.

//Transforming the motor's rotary motion into linear motion by using a threaded rod:
//Threaded rod's pitch = 2 mm. This means that one revolution will move the nut 2 mm.
//Default stepping = 400 step/revolution.
// 400 step = 1 revolution = 8 mm linear motion. (4 start 2 mm pitch screw)
// 1 cm = 10 mm =>> 10/8 * 400 = 4000/8 = 500 steps are needed to move the nut by 1 cm.

#define HOMING_SPEED 600
#define MM_PER_REV 8
#define INCH_PER_REV 0.314960629
#define STEPS_PER_REV 200
//character for commands
/*
'C' : Prints all the commands and their functions.
'P' : Rotates the motor in positive (CW) direction, relative.
'N' : Rotates the motor in negative (CCW) direction, relative.
'R' : Rotates the motor to an absolute positive position (+).
'r' : Rotates the motor to an absolute negative position (-).
'S' : Stops the motor immediately.
'A' : Sets an acceleration value.
'L' : Prints the current position/location of the motor.
`Preformatted text` 'H' : Goes back to 0 position from the current position (homing).
'U' : Updates the position current position and makes it as the new 0 position.
*/

#include <AccelStepper.h>

//User-defined values
long x_steps = 0; //Number of steps
long receivedSpeed = 0; //Steps / second
long receivedAcceleration = 0; //Steps / second^2
float Speed;
float unit_per_sec;
long y_steps;
bool homing;
bool isnegative;
bool unit_inch;
bool unit_mm;

//-------------------------------------------------------------------------------
int directionMultiplier = 1; // = 1: positive direction, = -1: negative direction
bool newData, runallowed = false; // booleans for new data from serial, and runallowed flag
bool isabsolute, isrelative, print_allowed;
//AcceleSteper yourstepper(interface_type, step,direction)

AccelStepper x_stepper(1, 8, 9);// direction Digital 9 (CCW), pulses Digital 8 (CLK)
AccelStepper y_stepper(1, 10, 11);
void setup()
{
Serial.begin(19200); //define baud rate

``````//Transforming the motor's rotary motion into linear motion by using a threaded rod:
//Threaded rod's pitch = 2 mm. This means that one revolution will move the nut 2 mm.
//Default stepping = 400 step/revolution.
// 400 step = 1 revolution = 8 mm linear motion. (4 start 2 mm pitch screw)
// 1 cm = 10 mm =>> 10/8 * 400 = 4000/8 = 500 steps are needed to move the nut by 1 cm.

#define HOMING_SPEED 600
#define MM_PER_REV 8
#define INCH_PER_REV 0.314960629
#define STEPS_PER_REV 200
//character for commands
/*
'C' : Prints all the commands and their functions.
'P' : Rotates the motor in positive (CW) direction, relative.
'N' : Rotates the motor in negative (CCW) direction, relative.
'R' : Rotates the motor to an absolute positive position (+).
'r' : Rotates the motor to an absolute negative position (-).
'S' : Stops the motor immediately.
'A' : Sets an acceleration value.
'L' : Prints the current position/location of the motor.
'H' : Goes back to 0 position from the current position (homing).
'U' : Updates the position current position and makes it as the new 0 position.
*/

#include <AccelStepper.h>

//User-defined values
long x_steps = 0; //Number of steps
long receivedSpeed = 0; //Steps / second
long receivedAcceleration = 0; //Steps / second^2
float Speed;
float unit_per_sec;
long y_steps;
bool homing;
bool isnegative;
bool unit_inch;
bool unit_mm;

//-------------------------------------------------------------------------------
int directionMultiplier = 1; // = 1: positive direction, = -1: negative direction
bool newData, runallowed = false; // booleans for new data from serial, and runallowed flag
bool isabsolute, isrelative, print_allowed;
//AcceleSteper yourstepper(interface_type, step,direction)

AccelStepper x_stepper(1, 8, 9);// direction Digital 9 (CCW), pulses Digital 8 (CLK)
AccelStepper y_stepper(1, 10, 11);
void setup()
{
Serial.begin(19200); //define baud rate
Serial.println("Demonstration of AccelStepper Library"); //print a messages
Serial.println("Send 'C' for printing the commands.");

//setting up some default values for maximum speed and maximum acceleration
Serial.println("Default speed: 400 steps/s, default acceleration: 800 steps/s^2.");
x_stepper.setMaxSpeed(600); //SPEED = Steps / second
y_stepper.setMaxSpeed(600);
[quote="mbise1997, post:1, topic:886405, full:true"]
Hi there!
I'm trying to build my own  G-code interpreter in which the commands have to come from Arduino serial Monitor.
The problem is if I send a command while the other is being executed the current execution stops and execute the command I just sent.

I want it to queue the commands that the commands sent must wait until current execution finishes then execute the next command.

I want to build A CNC punching machine using Stepper motors-lead screw drive and a hydraulic cylinder whose stroke is controlled by opening and closing a valve. Arduino Mega is the controller.
The code I've written so far is shown below which I used accelstepper library and some arduino builtin functions.  However, I've not yet written valve control chunk of code, I think it won't be difficult because it is just ON or OFF control(HIGH or LOW)

Could  anyone help me to implement command queuing that every comands wait for the other to be executed first?

The code I've written so far is shown below.

//Transforming the motor's rotary motion into linear motion by using a threaded rod:
//Threaded rod's pitch = 2 mm. This means that one revolution will move the nut 2 mm.
//Default stepping = 400 step/revolution.
// 400 step = 1 revolution = 8 mm linear motion. (4 start 2 mm pitch screw)
// 1 cm = 10 mm =>> 10/8 * 400 = 4000/8 = 500 steps are needed to move the nut by 1 cm.

#define HOMING_SPEED 600
#define MM_PER_REV 8
#define INCH_PER_REV 0.314960629
#define STEPS_PER_REV 200
//character for commands
/*
'C' : Prints all the commands and their functions.
'P' : Rotates the motor in positive (CW) direction, relative.
'N' : Rotates the motor in negative (CCW) direction, relative.
'R' : Rotates the motor to an absolute positive position (+).
'r' : Rotates the motor to an absolute negative position (-).
'S' : Stops the motor immediately.
'A' : Sets an acceleration value.
'L' : Prints the current position/location of the motor.
'H' : Goes back to 0 position from the current position (homing).
'U' : Updates the position current position and makes it as the new 0 position.
*/

#include <AccelStepper.h>

//User-defined values
long x_steps = 0; //Number of steps
long receivedSpeed = 0; //Steps / second
long receivedAcceleration = 0; //Steps / second^2
float Speed;
float unit_per_sec;
long y_steps;
bool homing;
bool isnegative;
bool unit_inch;
bool unit_mm;

//-------------------------------------------------------------------------------
int directionMultiplier = 1; // = 1: positive direction, = -1: negative direction
bool newData, runallowed = false; // booleans for new data from serial, and runallowed flag
bool isabsolute, isrelative, print_allowed;
//AcceleSteper yourstepper(interface_type, step,direction)

AccelStepper x_stepper(1, 8, 9);// direction Digital 9 (CCW), pulses Digital 8 (CLK)
AccelStepper y_stepper(1, 10, 11);
void setup()
{
Serial.begin(19200); //define baud rate
Serial.println("Demonstration of AccelStepper Library"); //print a messages
Serial.println("Send 'C' for printing the commands.");

//setting up some default values for maximum speed and maximum acceleration
Serial.println("Default speed: 400 steps/s, default acceleration: 800 steps/s^2.");
x_stepper.setMaxSpeed(600); //SPEED = Steps / second
y_stepper.setMaxSpeed(600);
x_stepper.setAcceleration(1000); //ACCELERATION = Steps /(second)^2
y_stepper.setAcceleration(1000);
// stepper.disableOutputs(); //disable outputs
}

void loop()
{
//Constantly looping through these 2 functions.
//We only use non-blocking commands, so something else (should also be non-blocking) can be done during the movement of the motor

checkSerial(); //check serial port for new commands
RunTheMotor(); //function to handle the motor

}

void RunTheMotor() //function for the motor
{
if (runallowed == true)
{
//stepper.enableOutputs(); //enable pins
x_stepper.run();
y_stepper.run();
//step the motor (this will step the motor by 1 step at each loop)
}
else //program enters this part if the runallowed is FALSE, we do not do anything
{
// stepper.disableOutputs(); //disable outputs
return;
}
}

void checkSerial() //function for receiving the commands
{
if (Serial.available() > 0) //if something comes from the computer
{
newData = true; //indicate that there is a new data by setting this bool to true

if (newData == true) //we only enter this long switch-case statement if there is a new command from the computer
{
switch (receivedCommand) //we check what is the command
{

case '-' :
isnegative = true;
if (isnegative)directionMultiplier = -1;
else directionMultiplier = 1;
break;
case 'X': //P uses the move() function of the AccelStepper library, which means that it moves relatively to the current position.

float  x_received_distance = Serial.parseFloat(); //value for distance to move

x_steps = convert_distance_to_motor_steps(x_received_distance); //value for distance to move
//receivedSpeed = Serial.parseFloat(); //value for the speed
directionMultiplier = 1; //We define the direction
if (isrelative)
x_RotateRelative(); //Run the function
else if (isabsolute)
x_RotateAbsolute();
Serial.println("Positive direction."); //print the action
break;

case 'Y': //P uses the move() function of the AccelStepper library, which means that it moves relatively to the current position.

float  y_received_distance = Serial.parseFloat(); //value for distance to move

y_steps = convert_distance_to_motor_steps(y_received_distance); //value for distance to move
//y_receivedSpeed = Serial.parseFloat(); //value for the speed
directionMultiplier = 1; //We define the direction
Serial.println("Positive direction."); //print the action
y_RotateRelative(); //Run the function

//example: P2000 400 - 2000 steps (5 revolution with 400 step/rev microstepping) and 400 steps/s speed
//In theory, this movement should take 5 seconds

break;

case 'S': // axes speed
unit_per_sec = Serial.parseFloat();
Speed = convert_speed_to_motor_steps_per_sec(unit_per_sec);
break;

case 's': // Stops the motor
stopMotors();

runallowed = false; //disable running

break;

case 'G':
int int_value = Serial.parseInt();
switch (int_value) {

case 30:
homing = true;
Serial.println("Homing"); //Print the message
GoHome();// Run the function
break;

case 20:
unit_inch = true;
break;

case 21:
unit_mm = true;
break;
case 90:
isabsolute = true; break;
case 91:
isrelative = true; break;

} break;

case 'C':
print_allowed = true;
PrintCommands(); //Print the commands for controlling the motor
break;

default:

break;
}
}
//after we went through the above tasks, newData is set to false again, so we are ready to receive new commands again.
newData = false;
}
}

void GoHome()
{
if (x_stepper.currentPosition() == 0)
{
if (y_stepper.currentPosition() == 0)
Serial.println("We are at the home position.");
// x_stepper.disableOutputs(); //disable power
}
else

{
home_steppers();

}
}

void x_RotateRelative()
{
//We move X steps from the current position of the stepper motor in a given direction.
//The direction is determined by the multiplier (+1 or -1)

runallowed = true; //allow running - this allows entering the RunTheMotor() function.
x_stepper.setMaxSpeed(Speed); //set speed
x_stepper.move(directionMultiplier * x_steps); //set relative distance and direction
}

void x_RotateAbsolute()
{
//We move to an absolute position.
//The AccelStepper library keeps track of the position.
//The direction is determined by the multiplier (+1 or -1)
//Why do we need negative numbers? - If you drive a threaded rod and the zero position is in the middle of the rod...

runallowed = true; //allow running - this allows entering the RunTheMotor() function.
x_stepper.setMaxSpeed(Speed); //set speed
x_stepper.moveTo(directionMultiplier * x_steps); //set relative distance
}

void y_RotateAbsolute()
{
//We move to an absolute position.
//The AccelStepper library keeps track of the position.
//The direction is determined by the multiplier (+1 or -1)
//Why do we need negative numbers? - If you drive a threaded rod and the zero position is in the middle of the rod...

runallowed = true; //allow running - this allows entering the RunTheMotor() function.
y_stepper.setMaxSpeed(Speed); //set speed
y_stepper.moveTo(directionMultiplier * y_steps); //set relative distance
}

void y_RotateRelative()
{
//We move X steps from the current position of the stepper motor in a given direction.
//The direction is determined by the multiplier (+1 or -1)

runallowed = true; //allow running - this allows entering the RunTheMotor() function.
y_stepper.setMaxSpeed(Speed); //set speed
y_stepper.move(directionMultiplier * y_steps); //set relative distance and direction
}

void PrintCommands()
{
if (print_allowed) {
//Printing the commands
Serial.println(" 'C' : Prints all the commands and their functions.");
Serial.println(" 'P' : Rotates the motor in positive (CW) direction, relative.");
Serial.println(" 'N' : Rotates the motor in negative (CCW) direction, relative.");
Serial.println(" 'R' : Rotates the motor to an absolute positive position (+).");
Serial.println(" 'r' : Rotates the motor to an absolute negative position (-).");
Serial.println(" 'S' : Stops the motor immediately.");
Serial.println(" 'A' : Sets an acceleration value.");
Serial.println(" 'L' : Prints the current position/location of the motor.");
Serial.println(" 'H' : Goes back to 0 position from the current position (homing).");
Serial.println(" 'U' : Updates the position current position and makes it as the new 0 position. ");
}

}
void home_steppers() {
if (homing == true) {
x_stepper.setMaxSpeed(HOMING_SPEED); //set speed manually to 400. In this project 400 is 400 step/sec = 1 rev/sec.

y_stepper.setMaxSpeed(HOMING_SPEED);
x_stepper.moveTo(0);
y_stepper.moveTo(0); //set abolute distance to move
}
}

void stopMotors() {
x_stepper.stop(); //stop motor
y_stepper.stop(); //stop motor
//X_stepper.disableOutputs(); //disable power
Serial.println("Stopped."); //print action
}

long convert_distance_to_motor_steps(float distance) {
long steps;
if (unit_inch)
steps = (distance * STEPS_PER_REV) / INCH_PER_REV;
else if (unit_mm)
steps = (distance * STEPS_PER_REV) / MM_PER_REV;
return steps;
}

long convert_speed_to_motor_steps_per_sec(float _speed) {
long steps_per_sec;
if (unit_inch)
steps_per_sec = (_speed * STEPS_PER_REV) / INCH_PER_REV;
else if (unit_mm)
steps_per_sec = (_speed * STEPS_PER_REV) / MM_PER_REV;
return steps_per_sec;
}`

`* Preformatted text`

`
[/quote]

``````

type or paste code here

How many commands are you going to queue? The serial port has a 64 byte buffer, so for a first attempt, you can just ignore serial when you're executing motor commands and pick up the next one later.

How can I do it? this is a full code for my CNC, the sensors are used to control the cylinder stroke.

``````

//Transforming the motor's rotary motion into linear motion by using a threaded rod:
//Threaded rod's pitch = 2 mm and lead 8mm. This means that one revolution will move the nut 8 mm.
//Default stepping = 200 step/revolution.
// 200 step = 1 revolution = 8 mm linear motion. (4 start 2 mm pitch screw)
// 1 cm = 10 mm =>> 10/8 * 200 = 2000/8 = 250 steps are needed to move the nut by 1 cm.

#define HOMING_SPEED 600
#define MM_PER_REV 8
#define INCH_PER_REV 0.314960629
#define STEPS_PER_REV 200
#define PUNCHED_SENSOR 12
#define RETRACTED_SENSOR 13
#define PUNCH_PIN 6
#define RETRACT_PIN 7
//character for commands
/*
'C' : Prints all the commands and their functions.
'P' : Rotates the motor in positive (CW) direction, relative.
'N' : Rotates the motor in negative (CCW) direction, relative.
'R' : Rotates the motor to an absolute positive position (+).
'r' : Rotates the motor to an absolute negative position (-).
'S' : Stops the motor immediately.
'A' : Sets an acceleration value.
'L' : Prints the current position/location of the motor.
'H' : Goes back to 0 position from the current position (homing).
'U' : Updates the position current position and makes it as the new 0 position.
*/

#include <AccelStepper.h>

//User-defined values
long x_steps = 0; //Number of steps
long receivedSpeed = 0; //Steps / second
long receivedAcceleration = 0; //Steps / second^2
float Speed;
float unit_per_sec;
long y_steps;
bool homing;
bool isnegative;
bool unit_inch;
bool unit_mm;
bool punch, ispunched, isretracted;
volatile bool punch;

//-------------------------------------------------------------------------------
int directionMultiplier = 1; // = 1: positive direction, = -1: negative direction
bool newData, runallowed = false; // booleans for new data from serial, and runallowed flag
bool isabsolute, isrelative, print_allowed;
//AcceleSteper yourstepper(interface_type, step,direction)

AccelStepper x_stepper(1, 8, 9);// direction Digital 9 (CCW), pulses Digital 8 (CLK)
AccelStepper y_stepper(1, 10, 11);
void setup()
{
Serial.begin(19200); //define baud rate
Serial.println("Demonstration of AccelStepper Library"); //print a messages
Serial.println("Send 'C' for printing the commands.");
pinMode(RETRACT_PIN, OUTPUT);
pinMode(PUNCH_PIN, OUTPUT);
pinMode(RETRACTED_SENSOR, INPUT);
pinMode(PUNCHED_SENSOR, INPUT);
//setting up some default values for maximum speed and maximum acceleration
Serial.println("Default speed: 400 steps/s, default acceleration: 800 steps/s^2.");
x_stepper.setMaxSpeed(600); //SPEED = Steps / second
y_stepper.setMaxSpeed(600);
x_stepper.setAcceleration(1000); //ACCELERATION = Steps /(second)^2
y_stepper.setAcceleration(1000);
// stepper.disableOutputs(); //disable outputs
}

void loop()
{
//Constantly looping through these 2 functions.
//We only use non-blocking commands, so something else (should also be non-blocking) can be done during the movement of the motor

checkSerial(); //check serial port for new commands
RunTheMotor(); //function to handle the motor

}

void RunTheMotor() //function for the motor
{
if (runallowed == true)
{
//stepper.enableOutputs(); //enable pins
x_stepper.run();
y_stepper.run();
//step the motor (this will step the motor by 1 step at each loop)
}
else //program enters this part if the runallowed is FALSE, we do not do anything
{
// stepper.disableOutputs(); //disable outputs
return;
}
}

void checkSerial() //function for receiving the commands
{
if (Serial.available() > 0) //if something comes from the computer
{
newData = true; //indicate that there is a new data by setting this bool to true

if (newData == true) //we only enter this long switch-case statement if there is a new command from the computer
{
switch (receivedCommand) //we check what is the command
{

case '-' :
isnegative = true;
if (isnegative)directionMultiplier = -1;
else directionMultiplier = 1;
break;
case 'X': //P uses the move() function of the AccelStepper library, which means that it moves relatively to the current position.

float  x_received_distance = Serial.parseFloat(); //value for distance to move

x_steps = convert_distance_to_motor_steps(x_received_distance); //value for distance to move
//receivedSpeed = Serial.parseFloat(); //value for the speed
directionMultiplier = 1; //We define the direction
if (isrelative)
x_RotateRelative(); //Run the function
else if (isabsolute)
x_RotateAbsolute();
Serial.println("Positive direction."); //print the action
break;

case 'Y': //P uses the move() function of the AccelStepper library, which means that it moves relatively to the current position.

float  y_received_distance = Serial.parseFloat(); //value for distance to move

y_steps = convert_distance_to_motor_steps(y_received_distance); //value for distance to move
//y_receivedSpeed = Serial.parseFloat(); //value for the speed
directionMultiplier = 1; //We define the direction
Serial.println("Positive direction."); //print the action
y_RotateRelative(); //Run the function

//example: P2000 400 - 2000 steps (5 revolution with 400 step/rev microstepping) and 400 steps/s speed
//In theory, this movement should take 5 seconds

break;

case 'S': // axes speed
unit_per_sec = Serial.parseFloat();
Speed = convert_speed_to_motor_steps_per_sec(unit_per_sec);
break;

case 's': // Stops the motor
stopMotors();

runallowed = false; //disable running

break;
case 'M':
int_ = Serial.parseInt();
if (int_ = 7)
punch();
break;
case 'G':
int int_value = Serial.parseInt();
switch (int_value) {

case 30:
homing = true;
Serial.println("Homing"); //Print the message
GoHome();// Run the function
break;
case 20:
unit_inch = true; break;
case 21: unit_mm = true; break;
case 90: isabsolute = true; break;
case 91: isrelative = true; break;
} break;

case 'C':
print_allowed = true;
PrintCommands(); //Print the commands for controlling the motor
break;

default:

break;
}
}
//after we went through the above tasks, newData is set to false again, so we are ready to receive new commands again.
newData = false;
}
}

void GoHome()
{
if (x_stepper.currentPosition() == 0)
{
if (y_stepper.currentPosition() == 0)
Serial.println("We are at the home position.");
// x_stepper.disableOutputs(); //disable power
}
else

{
home_steppers();

}
}

void x_RotateRelative()
{
//We move X steps from the current position of the stepper motor in a given direction.
//The direction is determined by the multiplier (+1 or -1)

runallowed = true; //allow running - this allows entering the RunTheMotor() function.
x_stepper.setMaxSpeed(Speed); //set speed
x_stepper.move(directionMultiplier * x_steps); //set relative distance and direction
}

void x_RotateAbsolute()
{
//We move to an absolute position.
//The AccelStepper library keeps track of the position.
//The direction is determined by the multiplier (+1 or -1)
//Why do we need negative numbers? - If you drive a threaded rod and the zero position is in the middle of the rod...

runallowed = true; //allow running - this allows entering the RunTheMotor() function.
x_stepper.setMaxSpeed(Speed); //set speed
x_stepper.moveTo(directionMultiplier * x_steps); //set relative distance
}

void y_RotateAbsolute()
{
//We move to an absolute position.
//The AccelStepper library keeps track of the position.
//The direction is determined by the multiplier (+1 or -1)
//Why do we need negative numbers? - If you drive a threaded rod and the zero position is in the middle of the rod...

runallowed = true; //allow running - this allows entering the RunTheMotor() function.
y_stepper.setMaxSpeed(Speed); //set speed
y_stepper.moveTo(directionMultiplier * y_steps); //set relative distance
}

void y_RotateRelative()
{
//We move X steps from the current position of the stepper motor in a given direction.
//The direction is determined by the multiplier (+1 or -1)

runallowed = true; //allow running - this allows entering the RunTheMotor() function.
y_stepper.setMaxSpeed(Speed); //set speed
y_stepper.move(directionMultiplier * y_steps); //set relative distance and direction
}

void PrintCommands()
{
if (print_allowed) {
//Printing the commands
Serial.println(" 'C' : Prints all the commands and their functions.");
Serial.println(" 'P' : Rotates the motor in positive (CW) direction, relative.");
Serial.println(" 'N' : Rotates the motor in negative (CCW) direction, relative.");
Serial.println(" 'R' : Rotates the motor to an absolute positive position (+).");
Serial.println(" 'r' : Rotates the motor to an absolute negative position (-).");
Serial.println(" 'S' : Stops the motor immediately.");
Serial.println(" 'A' : Sets an acceleration value.");
Serial.println(" 'L' : Prints the current position/location of the motor.");
Serial.println(" 'H' : Goes back to 0 position from the current position (homing).");
Serial.println(" 'U' : Updates the position current position and makes it as the new 0 position. ");
}

}
void home_steppers() {
if (homing == true) {
x_stepper.setMaxSpeed(HOMING_SPEED); //set speed manually to 400. In this project 400 is 400 step/sec = 1 rev/sec.

y_stepper.setMaxSpeed(HOMING_SPEED);
x_stepper.moveTo(0);
y_stepper.moveTo(0); //set abolute distance to move
}
}

void stopMotors() {
x_stepper.stop(); //stop motor
y_stepper.stop(); //stop motor
//X_stepper.disableOutputs(); //disable power
Serial.println("Stopped."); //print action
}

long convert_distance_to_motor_steps(float distance) {
long steps;
if (unit_inch)
steps = (distance * STEPS_PER_REV) / INCH_PER_REV;
else if (unit_mm)
steps = (distance * STEPS_PER_REV) / MM_PER_REV;
return steps;
}

long convert_speed_to_motor_steps_per_sec(float _speed) {
long steps_per_sec;
if (unit_inch)
steps_per_sec = (_speed * STEPS_PER_REV) / INCH_PER_REV;
else if (unit_mm)
steps_per_sec = (_speed * STEPS_PER_REV) / MM_PER_REV;
return steps_per_sec;
}

void punch() {
punch = true;
if (punch == true)
{
digitalWrite(PUNCH_PIN, HIGH);

if (ispunched) {
digitalWrite(PUNCH_PIN, LOW);
digitalWrite(RETRACT_PIN, HIGH);
}

if (isretracted)
{ digitalWrite(RETRACT_PIN, LOW);
}
}
punch = false;
}``````

Queuing is another name for CIRCULAR BUFFER. Search the forum for those words and see if there is any help there. The first thing for you to do is determine the length of the longest command you will ever send to the machine. That length will be the length of each entry in your queue.
Paul

Thanks. I'm onna try it.

Multi-tasking in Arduino has a complete stepper example using AccelStepper and controlled by Serial input and a sensor.
Your PrintCommands() method can slow things down. see Arduino Serial I/O for the Real World for a buffered non-blocking Serial print.

How many commands (bytes) are you talking about?
Do you have enough ram to hold them all?

A simple way is to just increase the Serial input buffering using my
BufferedInput :- adding extra Input buffering so you don't miss input data while processing the last input. Provides statistics to help choose the correct buffer size.

If you don't have enough RAM then you need a send cmd and ack response to release the next cmd from the sender.

When a command is received and an action starts, set a flag, busyFlag = true. When the activity is finished set the flag = false. Only look for new commands, checkSerial(), when busyFlag == false.

That is the crucial part. How will the program know that ?

That's up to OP to decide. Now new commands interfere with the old. What does OP say? When does a new command interrupt the previous and when doesn't it?

Quite critical! The CNC program knows or should know based on the status of whatever it has been doing. I suspect the OP has designed his system so there is no indication of the POSITION of his punch.
Paul

Just what I thought. Different commands take different amount of time to complete. On way is to send the new command when the human eye tells that the previous command is finished. To make a controller read OPs mind looks hard to achieve....

@Railroader I thought of too, that I might need a Software(GUI) like GRBL controller which monitors the execution of the current command and once finished it sends the other. I think every CNC controller has it's own communication protocol, I tried quite a few like GRBL controller, Estlcam, Metalix V16 DNC but neither of them work. It looked like each one of them needed a chunk of code for communication protocol which isn't present in my code.

@drmpf Thanks very much. I've read the description of safeString library and it looks like I'm gonna get something useful. Let me try to use the library.