DNC Via Arduino Serial

Take a look at GRBL and UGS which together forms the backbone of a CNC machine.

GRBL is installed on the Arduino to form the interpreter for G-CODE commands.
UGS forms the sender program allowing you to send most standard CNC programs directly to the CNC.

There are other g-code senders available too but they almost all require GRBL to be installed.

It would be a simple matter of fitting a relay instead of a spindle to perform the punch move.

There is a version of GRBL for the MEGA board but most versions use the UNO. That is the prefered method using a simple CNC shield.

There may be feedback. For a hobby 3D printer, which is much the same principle, it homes at startup and then counts steps assuming that it won't miss any.

A CNC machine may do the same, but if the consequences of missing steps are likely to be expensive, there will be encoders to verify position too. Closed loop steppers in effect.

Some motors have feedback elements built into them - like pulse wheel/photo sensors. So, if the computer commands to move 100 steps, the feedback counts how many steps are actually moved.

To build a G-code parser is just very easy. Just "switch-break" and/or "if- else" statements.
The problem here is I want to build my own parser for Punching-a point to point positioning control.
I've tried to search on web but never found an open source firmware for this application!
Firmware like GRBL, Marlin are for 3D printers or 3D Millers which all are continuous positioning systems.

What I'm trying to figure out is how I can send commands to arduino serially and each command get executed without interference.

I'm trying to do it by first positioning the axes by sending one line of code containing axes distance, speed and unit mode.

What I experienced is if I send another line while the previous is being executed the motors stop and then execute the other code.

I want would like it to continue with the previous command, finish it then execute the other.

Can you help me to implement command queuing system? Because what I'm experiencing is if I send command before the previous finishes to execute arduino stops execution of the command and execute the one I send on top.

It sounds like you need to implement a First In, First Out (FIFO) buffer probably using an array of C style strings. Put each command in the buffer as it is received and take it from the buffer and use it when required

Please post your current code that is causing you problems

The easier you make it to read and copy your code the more likely it is that you will get help

Please follow the advice given in the link below when posting code , use code tags and post the code here to make it easier to read and copy for examination


//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
char receivedCommand;
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
  {
    receivedCommand = Serial.read(); // pass the value to the receivedCommad variable
    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;
}

How can I do it? This is a full code including cylinder control. I have not tested it though but I expect it to work.


//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
char receivedCommand;
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
  ispunched = digitalRead(PUNCHED_SENSOR);
  isretracted = digitalRead(RETRACTED_SENSOR);

  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
  {
    receivedCommand = Serial.read(); // pass the value to the receivedCommad variable
    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;
}

@UKHeliBob this is my full code.Now I want to add command queuing system to it.Because when I send commands before the previous execution finishes it stop excuting the current command and execute the new one...when finishes it just stop. I want commands to be queued or a GUI which can send commands one line at a time and wait until execution of a line finish then send the other.


//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
char receivedCommand;
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
  ispunched = digitalRead(PUNCHED_SENSOR);
  isretracted = digitalRead(RETRACTED_SENSOR);

  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
  {
    receivedCommand = Serial.read(); // pass the value to the receivedCommad variable
    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;
}

I'm using steppers without feedback. I think they might be software way of implementing queuing system without relying on the mechanical feedback.

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