Replacing Delay() between steps

Hi There,

I have finished my program. Long story short it turns out I have to replace all the Delay() functions in my program with a Timer. I have read all the post about millis and non blocking timers.
A really helpful one I would suggest is:

Now my question is, I can follow the tutorial and update most of my code to use this type of timers. But I was wondering about the delay() function in between steps when moving my stepper motor?

ex.

while (!digitalRead(home_switch)==LOW) { // Do this until the switch is activated

    digitalWrite(dirPin, HIGH); 
    digitalWrite(stepPin, LOW);
    delay(delayTime);                       
    digitalWrite(stepPin, HIGH);
    delay(delayTime);                       
    
  }

How will I change this not to use the delay() blocking function. and also if it non-blocking will it still run my code outside of the while loop?? Am I missing something here?

A while loop is blocking by its very nature and a delay() in a while loop magnifies the length of the blocking

The solution is to use an if instead of a while and millis() for timing. No doubt you have seen the BlinkWithoutDelay example which uses this method

So, your code would in essence look like this

if the switch is activated
  if the step period has elapsed as measured using millis
    take a step
    save the time of the step
  end if
end if  

why do you think so ?

Is that a school assignment?

Hello
Take some time and study the BLINKWITHOUTDELAY example. This example can be used to design your own timer function as needed for your project.
Have a nice day and enjoy coding in C++.

Yes, the Arduino API makes it easy to time events without messing with hardware timers. It does that with micros() and millis(), both use the hardware timers but are much easier to use in 99% of cases.

Thank you Paul. I have studied this example as it was suggested to me before. I appreciate it though. But it still does not solve my problem. The problem is this code needs the delay() in order to work, meaning it needs to wait until the motor has moved before performing any operations as there is also a solenoid in the system. A Timer is non-blocking and will also allow other code to run while this one is running which could be catastrophic for my project... Therefore is there any way to replace the Delay() and make it non-blocking code but not run the rest of the loop? any other method or function?

Kolaha, I'm building a ATC and need to integrate this with mach3, in order for arduino to communicate as a slave to mach3 I have to remove the Delay() functions or else it will stop each time it encounters the delay() function within arduino.

Thank you UKHeliBob

If you compare BlinkWithoutDelay with the basic Blink sample, you should notice that there's no replace delay() by millis() . It's a completely different approach with an infinite number of loop() rounds, all taking no time at all (more or less).

Instead of "waiting" think of "not doing anything now".

Generally, homing an axis is an action you would want to complete before any other operations take place (so you know where you are starting from). This may be a case where the delays are not a problem.

This makes no sense. In essence you are asking how to block non-blocking code.

a7

Thank you John, you are correct as I'm doing this in the setup code for homing. then after words using the same method in the loop code.

No in essence I'm asking for someone who has extensive programming experience to provide me with a different method.

Thanks Michael. I'll see what I can do...

What do you need to send to mach3 while you're stepping the ATC? I'll guess ATC is Automatic Tool Changer.

It might make things clearer if you post your code.

Hi Wildbill yes sorry here is my code, Mach 3 will send an integer to Arduino each time it encounters the M6 G-code. But with the way mach3 communicates I am going to integrate some excellent code for modbus posted by Zafar on the mach3 forums. But before I do this it is essential to remove the Delay() functions and replace them with something more suitable.

//     **********************************************
//     *                                            *
//     *       Automatic, 12-Tool Toolchanger       *
//     *                2022-01-10                  *
//     *           Christiaan von Stade             *
//     *                                            *
//     **********************************************

//Include the Stepper library
#include <AccelStepper.h>

//Include the Button library
#include <ezButton.h>

//Include the Seria1 library
#include <SoftwareSerial.h>

#define LOOP_STATE_STOPPED 0
#define LOOP_STATE_STARTED 1

String readString;

SoftwareSerial Bluetooth(50, 49); // RX, TX

ezButton button(48);  // create ezButton object that attach to pin 48;
int loopState = LOOP_STATE_STOPPED;

int Tool[]={1,2,3,4,5,6,7,8,9,10,11,12}; //An array to store the amount of tools
int toolCount = 12;

const byte stepPin = 2;
const byte dirPin = 5;
const byte enablePin = 8;

const int solenoidPin = 53; //This is the solenoid output pin
const int home_switch = 52; // Pin 52 connected to Homing Switch (Sensor)

float counter = 0;
float CalibrationValue = 1.006927083; // 1600 steps per revolution / 12 = 133.3333333 + 60 steps to pass the pawl = 193.33/192 = 1.006927083 with 0 included in the first run 
static int TurretPosition = 1;
int delayTime = 1; // decrease the delay to increase the speed

static int Input = 1; //Initial value for the bluetooth received or serial monitor

int StepsBack = 70;

AccelStepper x_stepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup()
{
   Serial.begin(9600);

  Bluetooth.begin(9600);
  Bluetooth.println("Choose between 1 to 12 for a tool position");

   pinMode(enablePin, OUTPUT);
   digitalWrite(enablePin, LOW);
   pinMode(solenoidPin, OUTPUT);

   digitalWrite(solenoidPin, HIGH); //Switch Solenoid ON

   //delay(1000);
   
   while (!digitalRead(home_switch)==LOW) { // Do this until the switch is activated

    digitalWrite(dirPin, HIGH); 
    digitalWrite(stepPin, LOW);
    delay(delayTime);                       
    digitalWrite(stepPin, HIGH);
    delay(delayTime);                       
    
  }
  

   digitalWrite(dirPin, LOW); 
      for (int lp=0;lp<StepsBack;lp++) 
        { 
        digitalWrite(stepPin, LOW);
        delay(delayTime);                    
        digitalWrite(stepPin, HIGH);
        delay(delayTime);                       
      }

  
  delay(2000);

  digitalWrite(solenoidPin, LOW); //Switch Solenoid OFF
    
button.setDebounceTime(50); // set debounce time to 50 milliseconds
}

void loop()
{

ReceiveData();
BluetoothInput();

button.loop(); // MUST call the loop() function first

  if (button.isPressed()) {
    if (loopState == LOOP_STATE_STOPPED)
      loopState = LOOP_STATE_STARTED;

      
    else // if(loopState == LOOP_STATE_STARTED)
      loopState = LOOP_STATE_STOPPED;

  }

  if (counter>193.2){
      loopState = LOOP_STATE_STOPPED;
      counter = 0;
      Input = 0;
       digitalWrite(solenoidPin, LOW); //Switch Solenoid OFF
  }

  if (loopState == LOOP_STATE_STARTED) {

                
         if ((solenoidPin) != HIGH)
            {
              digitalWrite(solenoidPin, HIGH); //Switch Solenoid ON
            }
            else
            {
              
            }

                 while (counter<193.2) {
                
                    digitalWrite(dirPin, HIGH); 
                    digitalWrite(stepPin, LOW);
                    delay(delayTime);                       
                    digitalWrite(stepPin, HIGH);
                    delay(delayTime);                       

                    counter=counter+CalibrationValue;
                  }
        
            if (counter>193.2){
                digitalWrite(dirPin, LOW); 
                for (int lp=0;lp<StepsBack;lp++) 
                  { 
                  digitalWrite(stepPin, LOW);
                  delay(delayTime);                    
                  digitalWrite(stepPin, HIGH);
                  delay(delayTime);                    
                }
                delay(1000);
                digitalWrite(solenoidPin, LOW); //Switch Solenoid OFF
                Input = 0;
              Serial.print("Turret Position ");
              Serial.println(TurretPosition);
              
                    if (TurretPosition != 12)
                      {
                        TurretPosition =  TurretPosition + 1;
                      }
                      else
                      {
                        TurretPosition = 1;
                      }

            }

  }
  

            if (Input >= 1 && Input < 13)
                {
                  ToolChange();
                  Input == 0;
                }
                
             if (Input == 0)
              {
                      Serial.print("Turret Position ");
                      Serial.println(TurretPosition);
              }
            if (Input < 0 || Input > 12)
              {
                      Serial.println("No such tool - Please choose between 1 to 12");
                      
              }

            
 }


void ReceiveData() {

  while (Serial.available()) {
    delay(1);  
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    //int n;
    char carray[6]; //converting string to number
    readString.toCharArray(carray, sizeof(carray));
    Input = atoi(carray); 
    
    readString="";
  } 
  
}

void BluetoothInput() {

  while (Bluetooth.available()) {
    delay(1);  
    if (Bluetooth.available() >0) {
      char c = Bluetooth.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    //int n;
    char carray[6]; //converting string to number
    readString.toCharArray(carray, sizeof(carray));
    Input = atoi(carray);

    if (Input >= 1 && Input < 13)
                {
                  Bluetooth.print("Turret Position ");
                  Bluetooth.println(Input);
                }
                
    readString="";
  } 
  
}

void ToolChange(){

                                                      Serial.print("Input ");
                                                      Serial.println(Input);
                                                      Serial.print("Turret Position ");
                                                      Serial.println(TurretPosition);
                                                      
  for (int thisTool = 0 ; thisTool < toolCount ; thisTool++)
    {

      
            if (Tool[thisTool] = Input)
                {
                                                      
                                                      
                            while (TurretPosition != Input) 
                                 { 
                          
                                       counter = 0;

                                                      //Serial.print("Input ");
                                                      //Serial.println(Input);
                                                      //Serial.print("Turret Position ");
                                                      //Serial.println(TurretPosition);


                                        if ((solenoidPin) != HIGH)
                                                  {
                                                    digitalWrite(solenoidPin, HIGH); //Switch Solenoid ON
                                                  }
                                                  else
                                                  {
                                                    //do nothing
                                                  }
                                      
                                          while (counter<193.2) { 
                                      
                                          digitalWrite(dirPin, HIGH); 
                                          digitalWrite(stepPin, LOW);
                                          delay(delayTime);                       
                                          digitalWrite(stepPin, HIGH);
                                          delay(delayTime);                       
                                      
                                          counter=counter+CalibrationValue;

                                          
                                        }
                                                                         
                                              
                                                  if (counter>193.2){
                                                      digitalWrite(dirPin, LOW); 
                                                      for (int lp=0;lp<StepsBack;lp++) 
                                                        { 
                                                        digitalWrite(stepPin, LOW);
                                                        delay(delayTime);                    
                                                        digitalWrite(stepPin, HIGH);
                                                        delay(delayTime);                    
                                                      }
                                                      delay(1000);
                                                      digitalWrite(solenoidPin, LOW); //Switch Solenoid ON
                                                      

                                                        
                                                          if (TurretPosition != 12)
                                                            {
                                                              TurretPosition =  TurretPosition + 1;
                                                            }
                                                            else
                                                            {
                                                              TurretPosition = 1;
                                                            }

                                                  }         

                                  }

                   }

    }


}

Replace the delay calls with millis() comparison, create a state machine to handle the nested logic that uses the delays.

Here's some code from a similar project:

void HandleStepper()
{
static unsigned long StepperTime=0;

if(digitalRead(AcornRotatePin)==LOW)
  {
  if(!SawIndexPulse)
    {
    HomeOnCommand();  // Find Index, we haven't seen it yet.    
    }
  else
    {  
    if(micros()-StepperTime > StepInterval)
      {
      ToolJustChanged=HandleGrayCode();  //Check before we step. Last step may have been the one that changed tools.
      ExecuteStep();  
      StepperTime=micros();  
      }
    }
  }
}

// Actually step the stepper motor. Shared between calibration and normal operations.
// Timing concerns are handled elsewhere.

void ExecuteStep()
{
static byte StepperStepPinState=LOW;
digitalWrite(StepperStepPin,StepperStepPinState);
if(StepperStepPinState==LOW)
  {
  StepperStepPinState=HIGH;  
  }
else
  {
  StepperStepPinState=LOW;  
  }
StepCount++;  
if(StepCount>StepsPerRotation)
  {
  StepCount=0;    
  }
}

It doesn't match yours - the CNC controller asks the turret to rotate with a high signal, not a tool number.
This is the bit that might interest you:

    if(micros()-StepperTime > StepInterval)

Study this tutorial carefully: