Millis () Delay for a motor.

Hello guys,

I'm dealing with a problem more than 2 days and I can't find a solution. The problem is that in my sketch there is a function that moves one motor CW, CWW, and STOPS it. The problem is that when it stops I would like a delay to be used in order to stop the motor for some specific time. This is my code:

motionUpdate();

  if (Rvoltage < (Vvoltage - threshold)) // Threshold is a number given by the user.
  {
   
    motor1StopState = LOW;
    motor1Direction = CW;
  }
 else if (Rvoltage > (Vvoltage + threshold)) // Threshold is a number given by the user.
  {
   
    motor1StopState = LOW;
    motor1Direction = CCW;
  }
else
  {

    motor1StopState=HIGH; // Update the stop state to 'HIGH'.
    motor.brake(motor1);     // brakes the motor.

   unsigned long currentTime=millis();
    if ( currentTime-previousTime >= DEL)
    {
      motor1StopState = LOW;
      previousTime = currentTime;
    }
   
  }

Any help is really appreciated. Thank you in advance.

Instead of 3 states you want to have 4

CW / CCW / STOP / STOP_END

I guess, while in STOP (waiting) you don't want to check, whether the conditions for CW or CCW are met.

Another question is, if you really want to change from CW to CCW without stopping and waiting in between.
(in case Vvoltage changes quickly)

The code you posted is not a comlete sketch. Please post your complete sketch. From the very first line to the very last one. The solutin depends on how the code that you have posted is workng together with the rest.
Best regards Stefan

michael_x:
I guess, while in STOP (waiting) you don't want to check, whether the conditions for CW or CCW are met.

What I want is when the STOP(waiting) toggles, the motor move based on the upon conditions.

Also, no matter how fast the Vvoltage changes, the STOP state has to be enabled while in threshold.

electp:
I would like a delay to be used in order to stop the motor for some specific time.

if there no other code that needs to run, simply call delay (msec)

This function is a part of a big project which I need 3 comments to upload.

In a few words what it does is:

  1. Read from 2 Potentiometers a voltage given by the Arduino.
    2)Creates a menu printed on an LCD on which the user chooses a number by keypad : 1)Threshold, 2)Delay ( this is what we are talking about), 3)Reference voltage, 4)prints the voltages on LCD real-time.

I can't use delay() because the sketch run a MENU which is printed on an LCD. When delay() is called, the sketch - the LCD - Menu etc. "freezes". Thus, I think millis() is the only solution.

A simple delay isn't the solution, agreed.

when the STOP(waiting) toggles

What does that mean?
"when the stop waiting time ends ?"

Better not only think of 4 states, but also implement them in your sketch and define the allowed transitions:

  • in CW you can either stay in CW or go to STOP (similar for CCW)
  • in STOP you do nothing until time has elapsed -> STOP_END
  • in STOP_END you stay there or go to either CW or CCW

one approach is to recognize the transition when motor1StopState becomes HIGH and capture the timestamp at that time and wait for it to pass before taking action. requires tracking the state and having

untested

    if (HIGH == motor1StopState)  {
        static unsigned long previousTime = 0;
        if (HIGH != lastState)
            previousTime = millis();

        if (millis() - previousTime >= DEL)
        {
            motor1StopState = LOW;
        }
    }
    lastState = motor1StopState;

michael_x:
Better not only think of 4 states, but also implement them in your sketch and define the allowed transitions:

  • in CW you can either stay in CW or go to STOP (similar for CCW)
  • in STOP you do nothing until time has elapsed -> STOP_END
  • in STOP_END you stay there or go to either CW or CCW

Yes, I mean when the stop waiting time ends. Is there any possibility to implement it in code because I understood what you mean but I don't know how to do it.

gcjr:
one approach is to recognize the transition when motor1StopState becomes HIGH and capture the timestamp at that time and wait for it to pass before taking action. requires tracking the state and having

untested

    if (HIGH == motor1StopState)  {

static unsigned long previousTime = 0;
       if (HIGH != lastState)
           previousTime = millis();

if (millis() - previousTime >= DEL)
       {
           motor1StopState = LOW;
       }
   }
   lastState = motor1StopState;

Great idea! I tried it but it didn't work. The motor never gets at the STOP state.

I think the problem is here

   unsigned long currentTime=millis();
    if ( currentTime-previousTime >= DEL)
    {
      motor1StopState = LOW;
      previousTime = currentTime;
    }

I don't think you are setting perviousTime in the right place. It would be better called motorOffStartTime and it should be set at the point in the program where the motor stops. Then the piece of code I have quoted would be changed to

   unsigned long currentTime=millis();
    if ( currentTime - motorOffStartTime >= motorOffDuration)
    {
      motor1StopState = LOW;
    }

and if you are not using currentTime anywhere else it could be simplified to

    if ( millis() - motorOffStartTime >= motorOffDuration)
    {
      motor1StopState = LOW;
    }

...R

Robin2:
I think the problem is here

   unsigned long currentTime=millis();

if ( currentTime-previousTime >= DEL)
    {
      motor1StopState = LOW;
      previousTime = currentTime;
    }




I don't think you are setting perviousTime in the right place. It would be better called motorOffStartTime and it should be set at the point in the program where the motor stops. Then the piece of code I have quoted would be changed to


unsigned long currentTime=millis();
    if ( currentTime - motorOffStartTime >= motorOffDuration)
    {
      motor1StopState = LOW;
    }



and if you are not using currentTime anywhere else it could be simplified to


if ( millis() - motorOffStartTime >= motorOffDuration)
    {
      motor1StopState = LOW;
    }




...R

So you mean something like that?

 motor1StopState = HIGH;
  motor.brake(motor1);

  unsigned long currentTime=millis();
  unsigned long motorOffStartTime=0;

    if ( millis()- motorOffStartTime >= DEL)
    {
      motor1StopState = LOW;
    }
motorOffStartTime = currentTime;
}
}

electp:
Great idea! I tried it but it didn't work. The motor never gets at the STOP state.

could you post your code?

gcjr:
could you post your code?

  { 
            motor1StopState = HIGH;
            motor.brake(motor1);
    if (motor1StopState == HIGH)  {
        static unsigned long previousTime = 0;
        
        if (LOW != lastState){
            previousTime = millis();

        if (millis() - previousTime >= DEL)
        {
            motor1StopState = LOW;
        }
    }
    }
    lastState = motor1StopState;
    
  }
}

This is what i have gone so far. Stops but doesn't start again after the delay.

The motor never gets at the STOP state.

without seeing the rest of the code it's hard to tell why the fragment of code you posted, which sets the motor state and "brakes" the motor isn't executed.

what are there an extra set of braces in the code you posted? is this block conditional on something that you're not showing?

i don't think i understand what the delay is about. when should the motor be stopped, before or after the delay?

    {
        motor1StopState = HIGH;
        motor.brake(motor1);
        if (motor1StopState == HIGH)  {
            static unsigned long previousTime = 0;
            if (LOW != lastState){
                previousTime = millis();
                if (millis() - previousTime >= DEL)
                {
                    motor1StopState = LOW;
                }

            }

        }

        lastState = motor1StopState;
    }
}

electp:
So you mean something like that?

I can't make sense of that. Please post the complete program.

...R

Simply attach your INO file to your next post if it is too long to fit within the confines of the post body.

Hello, I made some progress at the code but it isn't ready still. The code is the below :

void updateState2()
{

  if (INvoltage > 0) // If INvoltage (RVoltage) is given by the user via MENU.
  {
    Rvoltage = INvoltage;      //Given Voltage as Rvoltage.        
    analogValue1 = analogRead(A2);              
    Vvoltage = analogValue1 * (5.0 / 1023.0); //Change Analog input in Voltage.  
  }

  if (INvoltage <= 0) // If Rvoltage is read by a pot.
  {
    analogValue = analogRead(A0);            
    analogValue1 = analogRead(A2);         
    Rvoltage = analogValue * (5.0 / 1023.0);    //Change Analog input in Voltage.         
    Vvoltage = analogValue1 * (5.0 / 1023.0);   //Change Analog input in Voltage.          
  }

  if (Rvoltage < (Vvoltage - threshold)) // CW MOVEMENT.
  {
    
    motor1StopState = LOW;
    motor1Direction = CW;
  }
 else if (Rvoltage > (Vvoltage + threshold)) // CCW MOVEMENT.
  {
    
    motor1StopState = LOW;
    motor1Direction = CCW;
  }
else  // STOP (?)
  { 
        motor1StopState = HIGH;
        motor.brake(motor1);
        static unsigned long Time = 0;
        static unsigned long previousTime = 0;
        Time = millis();
  
        if ((Time - previousTime >= DEL) )
        {
         
        Serial.print("Delay time in millis : ");
        Serial.println(Time);
        Serial.print("Delay : ");
        Serial.println(DEL); 
        Serial.print ("Previous Time : ");
        Serial.println(previousTime);
            previousTime = Time;
            motor1StopState = LOW;
        }
    }
}

So what is a Threshold in electronics? It is a value (often used in Voltages) that makes a gap between two states.

Let's say we have two voltages. One Reference voltage (RVoltage) which is a specific voltage given by the user and a Volatile voltage (Vvoltage) in this case by a potentiometer.

If :

  • RVoltage = Vvoltage ->Motor stops.
  • Rvoltage < Vvoltage ->Motor moves CW.
  • Rvoltage > Vvoltage ->Motor moves CCW.

But there is a threshold needed in order to have this functionality.

For example:

Rvoltage = 3 and Threshold= 0.5

If :

RVoltage compared with Vvoltage and Vvoltage have something between 2.5 to 3.5 -> Motor Stops.

RVoltage compared with Vvoltage and Vvoltage < 2.5 -> Motor runs CW.

Rvoltage compared with Vvoltage and Vvoltage > 3.5 -> Motor runs CCW.

Back at the code.
The motor stops for the delay as it has to. BUT the problem is when it starts again, it moves for something like one sec and then Delays again, and so on.

I'm pretty sure that the problem is here.

if ((Time - previousTime >= DEL) )
        
            previousTime = Time;            <-----------------
            motor1StopState = LOW;
        }

But I can't find a solution. I tried assigning an integer globally such as, "static int y=0", and change the parameters of the loop such as " if (Time-previousTime >=DEL && y==0)", in order to run it once, but nothing changed.

Any suggestions?

electp:
Any suggestions?

Yes. Please see Reply #15

Help us to help you.

...R

Here is the complete sketch. I hope there is a way to find a solution soon.

Arduino_Forum_Project.ino (16.7 KB)