Non Blocking Function

Hi,
Before posting here i was preparing my-self for saving myself torning apart by some eagles :grin:... I see many many posts where the poster just seems to me a white sheep infront of some giant volchurs :smiley:
I have said too much :cold_sweat: :cold_sweat: (Pardon me in advance)

PROBLEM DEFINITION: I need a non-blocking function which move the DC motor for a given time period and then make it shutdown.
SOLUTION: Use a blink without delay example and move afterword
SIMPLE SOLUTION: use delay(), but this block the code for a certain period..actually not the solution but a last option...
MY WORK:
Here is the piece of sketch which is called from the void loop(),

void MoveEastback(){
  unsigned long currentMillis = millis();

        if (!moveLeftHalted){
            MOTOR_LEFT;
            MOTOR_ON;}
          
  if( (millis()-currentMillis ) > (ManualReturn*1000)) {   //example ManualReturn=10 i.e. i want the motor OFF after 10sec
      MOTOR_OFF;
      Serial.print(millis()-currentMillis);
   
  }
}

where following is defined in the void setup()

 //MOTOR ON and OFF
#define MOTOR_ON analogWrite(MOTOR_EN, M_PWM)     //Turn on  Digital Pin 6 on Arduino and take 'M_PWM' for PWM
#define MOTOR_OFF digitalWrite(MOTOR_EN, LOW)    //Turn OFF  Digital Pin 6 on Arduino)
//MOTOR DIRECTION CONTROL CW/CCW
#define MOTOR_LEFT digitalWrite(MOTOR_DIR, HIGH)     //Turn on  Digital Pin 4 on Arduino
#define MOTOR_RIGHT digitalWrite(MOTOR_DIR, LOW)    //Turn OFF Digital Pin 4 on Arduino

My above function is not working, if i use while loop then this will block the code for 10 sec and i will not be able to do other work.. what should i do?

if i use while loop then this will block the code for 10 sec and i will not be able to do other work.. what should i do?

Don't use a while loop.

(that's a partial answer. I'll post the full answer when you post the full code :wink: )

where following is defined in the void setup()
Code:

//MOTOR ON and OFF
#define MOTOR_ON analogWrite(MOTOR_EN, M_PWM) //Turn on Digital Pin 6 on Arduino and take 'M_PWM' for PWM
#define MOTOR_OFF digitalWrite(MOTOR_EN, LOW)

Why? MOTOR_ON; looks bizarre. digitalWrite(MOTOR_EN, M_PWM); looks normal.

Adding an additional level of indirection accomplishes nothing of value.

You need to have a function that starts the motors going is they are not going, AND records when that happens, and stops them after they have been running long enough. You need to call that function quite often.

You've provided no evidence that you are doing 2 of those three things.

AWOL:

if i use while loop then this will block the code for 10 sec and i will not be able to do other work.. what should i do?

Don't use a while loop.

(that's a partial answer. I'll post the full answer when you post the full code :wink: )

Thank You AWOL for answering me... Actually i shall post the full code but then you all will play with me :grin: I am not a programmer i am very bad programmer...
Just need a simple solution how a function can be called from the main loop that
1- work accordingly as desired...
2- Its work without blocking other code...
3- Its work till the completion

For example, i want a motor run for 10 sec....

No, I won't play with you - I don't like guessing games.

PaulS:
Why? MOTOR_ON; looks bizarre. digitalWrite(MOTOR_EN, M_PWM); looks normal.

You are right but for me it has many advantages:
1- Its easily readable, that MOTOR is ON....

PaulS:
Adding an additional level of indirection accomplishes nothing of value.

You are ~27year experience in programming...I am learnining daily from you... thank you for suggestion:)

PaulS:
You need to have a function that starts the motors going is they are not going, AND records when that happens, and stops them after they have been running long enough. You need to call that function quite often.

You've provided no evidence that you are doing 2 of those three things.

I want to Start the motor for 10 sec and after 10sec i want it to stop...This 10sec is a variable i defined in MENWIZ menu libraray and the 10 sec can be anything between 1 to 120sec...

Khalid:
I want to Start the motor for 10 sec and after 10sec i want it to stop...This 10sec is a variable i defined in MENWIZ menu libraray and the 10 sec can be anything between 1 to 120sec...

You need to cook something for 10 minutes. You have a stopwatch, pen and paper. How would you do it? (See Blink Without Delay example for how "stopwatch", "pen" and "paper" translate into the programming world.)

I got it..
First thanks to PaulS, then AWOL and now you Arrch...

I am trying now make a sketch with some global long variable and one boolean (flag)... The theme is the function shall be called many time within the loop as PaulS enlightenment...For the first time when the function is called from the main loop, a global Flag shall be set within the function and Global long Millis() shall be stored in another variable...The second time the function called from the loop shall check the flag and time.. if the time >10sec the motor shall be Off and the flag shall be set again along with the time reset :grin:

Will post here if this strategy work...

AWOL :grin: I dont believe you 8)...You are a good player and i do not want to be a rolling football between Paul and you ]:smiley: ]:slight_smile:

Here is the sketch for non-blocking function. Can we simplify?

int ManualReturn=10;
int buttonState = 0; 
long previousMillis = 0;  
long currentMillis=0;
byte M_PWM=240;
boolean moveLeftHalted=false;
boolean fstTimeCall=true;
boolean EastFunctionActive=false;
void setup() {
 //MOTOR ON and OFF
#define MOTOR_ON analogWrite(6, M_PWM)     //Turn on  Digital Pin 6 on Arduino and take 'M_PWM' for PWM
#define MOTOR_OFF digitalWrite(6, LOW)    //Turn OFF  Digital Pin 6 on Arduino)
//MOTOR DIRECTION CONTROL CW/CCW
#define MOTOR_LEFT digitalWrite(5, HIGH)     //MOTOR_DIR  Digital Pin 5 on Arduino
#define MOTOR_RIGHT digitalWrite(5, LOW)    //MOTOR_DIR Digital Pin 5 on Arduino
  pinMode(4,INPUT);
  pinMode(13, OUTPUT);  
}

void loop()
{
  buttonState = digitalRead(4);
  if (buttonState == HIGH)
  {
    fstTimeCall=true;
  }
  MoveEastback();
}


void MoveEastback(){

  if (fstTimeCall)//&& (!moveLeftHalted))
  {
     MOTOR_LEFT;
     MOTOR_ON;
    fstTimeCall=false;
    EastFunctionActive=true;
    currentMillis=millis();
    digitalWrite(13, HIGH);
  }

  if( ((millis()-currentMillis ) > (ManualReturn*1000)) && (EastFunctionActive=true)) {   //example ManualReturn=10 i.e. i want the motor OFF after 10sec
     MOTOR_OFF;
    fstTimeCall=false;
    EastFunctionActive=false;
    digitalWrite(13, LOW);
  }
}

I see many many posts where the poster just seems to me a white sheep infront of some giant volchurs
I have said too much (Pardon me in advance)

We are here to help you, not tear you to pieces.

#define MOTOR_ON analogWrite(6, M_PWM)     //Turn on  Digital Pin 6 on Arduino and take 'M_PWM' for PWM
#define MOTOR_OFF digitalWrite(6, LOW)    //Turn OFF  Digital Pin 6 on Arduino)

Don't do this, please. It just is confusing. Besides which it isn't symmetric. Why not analogWrite (6, 0) to stop the motor?

  if( ((millis()-currentMillis ) > (ManualReturn*1000)) && (EastFunctionActive=true))

I presume this should be "EastFunctionActive == true" otherwise there is no point.

long previousMillis = 0;

millis values should be unsigned long, not long.

void setup() {
 //MOTOR ON and OFF
#define MOTOR_ON analogWrite(6, M_PWM)     //Turn on  Digital Pin 6 on Arduino and take 'M_PWM' for PWM
#define MOTOR_OFF digitalWrite(6, LOW)    //Turn OFF  Digital Pin 6 on Arduino)
//MOTOR DIRECTION CONTROL CW/CCW
#define MOTOR_LEFT digitalWrite(5, HIGH)     //MOTOR_DIR  Digital Pin 5 on Arduino
#define MOTOR_RIGHT digitalWrite(5, LOW)    //MOTOR_DIR Digital Pin 5 on Arduino
  pinMode(4,INPUT);
  pinMode(13, OUTPUT);  
}

Don't shove defines inside functions, it looks terrible.

The whole point of these suggestions is to improve your coding style, so that you will be able to see for yourself what needs fixing.

Nick thank you for pointing me the right direction and the rectification in the sketch.
Now its working fine.. THIS IS THE NON-BLOCKING FUNCTION :grin:

int ManualReturn=10;
unsigned  long currentMillis=0;
boolean fstTimeCall=true;
boolean EastFunctionActive=false;

void setup() { 
  pinMode(4,INPUT);
  pinMode(13, OUTPUT);  
}

void loop()
{
  int buttonState = digitalRead(4);
  if (buttonState == HIGH)
  {
    fstTimeCall=true;
  }
  MoveEastback();
}


void MoveEastback(){

  if (fstTimeCall)//&& (!moveLeftHalted))
  {
    fstTimeCall=false;
    EastFunctionActive=true;
    currentMillis=millis();
    digitalWrite(13, HIGH);
  }

  if( ((millis()-currentMillis ) > (ManualReturn*1000)) && (EastFunctionActive==true)) {   //example ManualReturn=10 i.e. i want the motor OFF after 10sec
    fstTimeCall=false;
    EastFunctionActive=false;
    digitalWrite(13, LOW);
  }
}

Edit:
1-buttonState was made local to the Void loop() as per AWOL suggestion

There's no need for "buttonState" to have global scope, and some of the other variables would be better as "static" within their respective functions.
Pin names would be good.

AWOL:
There's no need for "buttonState" to have global scope

Thank you, i rectified the above sketch.

AWOL:
, and some of the other variables would be better as "static" within their respective functions.
Pin names would be good.

Good point..I somewhere studied that STATIC variable retain their values in the function.Am i right?
Kindly, please tell what variable i can make static?

These two code listings are functionally equivalent, however the second version ( static foo ) is only accessible within the owning function.
The lifetime of both foo variables are bound to global scope ( unlike standard 'automatic' variables declared in functions without 'static' ).

int foo = 0;

void DoSomething( void )
  {
    foo = foo + 1;
  }

void DoSomething( void )
  {
    static int foo = 0;
    foo = foo + 1;
  }

MY WORK:

Way too complicated:

unsigned char timesup(unsigned long duration) {
  static unsigned long time_init=millis(); //initial time
  return ((millis() - time_init) >= duration)?1:0;
}

unsigned char RunMotor(unsigned long duration) {
  static unsigned char motor_running = 0;
  if (timesup(duration)) {//time is up
    turn_off_motor();
    motor_running = 0;
    return motor_running;
  }
  if (motor_running == 0) {  //first time calling this routine
    turn_on_motor();
    motor_running = 1;
  }
  return motor_running;
}

If you wish to reuse timesup(), you have to establish a protocol to reset time_init. But the rest remains the same.

Thank you drHenry...That is some clever work:)
Actually now i am stuck...
1- I made a non-blocking function
2- It start and stop the motor at certain time interval
3- BUT the PWM do not work.. Actually the initial value stored in M_PWM is used, but if i change the values of PWM in menu, nothing happen..this is because the function only start and stop the motor, but not contineously monitor the PWM value...

Actually i am building a suntracking system with lots of options.... I want the user to move the panels toward east for certain time interval.. If he find the Motor PWM is high and the panel running too fast toward the EAST he has no control...

So, now i should think now how can i change the motor PWM value which effect the motor rotation real time..

I think one function should be made more which will run contineously, if the PWM variable not change it should bypass and if changes in PWM variable happen, it should get into the core and reduce/increase the motor speed based on the change PWM value..

I am not that smart..i am a not a programmer( Actually if i say myself programmer then someone professional will beat me ]:D)...

Lets see whats the outcome...

I made a non-blocking function

But I'm not going to show it to you.

3- BUT the PWM do not work.. Actually the initial value stored in M_PWM is used, but if i change the values of PWM in menu, nothing happen..this is because the function only start and stop the motor, but not contineously monitor the PWM value...

Now, I need help with this function. Please help me, right away!

Do you see a (small) problem here?

PaulS:
But I'm not going to show it to you.

I think i showed in the previous page.... :grin: You were sleeping, or taking bear or enjoying on a beach with your beautiful girl friend..

3- BUT the PWM do not work.. Actually the initial value stored in M_PWM is used, but if i change the values of PWM in menu, nothing happen..this is because the function only start and stop the motor, but not continuously monitor the PWM value...

Now, I need help with this function. Please help me, right away!

Do you see a (small) problem here?
[/quote]

PaulS, :grin: I didn't call for help..atleast in this post.. ]:smiley: ]:slight_smile:

Here is the code...

int ManualReturn=10;
unsigned  long currentMillis=0;
boolean fstTimeCall=true;
boolean EastFunctionActive=false;

void Setup(){
pinMode(13,OUTPUT);
 #define  MOTOR_DIR   5    /// Change Direction
 #define  MOTOR_EN  7    /// On/OFF and PWM of DC Motor
 #define  PIN_KEYPAD  A5    //A5 pin Attached to Keyboard
pinMode(MOTOR_EN,OUTPUT);
pinMode(MOTOR_DIR,OUTPUT);
 #define MOTOR_ON analogWrite(MOTOR_EN, M_PWM*102)     //Turn on  Digital Pin 7 on Arduino and take 'M_PWM' for PWM M_PWM range 0~100
#define MOTOR_OFF digitalWrite(MOTOR_EN, LOW)    //Turn OFF  Digital Pin 7 on Arduino)
//MOTOR DIRECTION CONTROL CW/CCW
#define MOTOR_LEFT digitalWrite(MOTOR_DIR, HIGH)     //Turn on  Digital Pin 5 on Arduino
#define MOTOR_RIGHT digitalWrite(MOTOR_DIR, LOW)    //Turn OFF Digital Pin 5 on Arduino
}

void loop()
{
  int buttonState = digitalRead(4);
  if (buttonState == HIGH)
  {
    fstTimeCall=true;
  }
  MoveEastback();
}

void MoveEastback(){

  if ((fstTimeCall)&& (!moveLeftHalted))
  {
    fstTimeCall=false;
    EastFunctionActive=true;
    currentMillisEast=millis();
            MOTOR_LEFT;
            MOTOR_ON;
    digitalWrite(13, HIGH);
  }

  if( ((millis()-currentMillisEast ) > (ManualReturn*1000)) && (EastFunctionActive==true)) {   //example ManualReturn=10 i.e. i want the motor OFF after 10sec
    fstTimeCall=false;
    EastFunctionActive=false;
//                
       MOTOR_OFF;     
      Serial.print(millis()-currentMillisEast);
      digitalWrite(13, LOW); 
  }
}
void loop()
{
  int buttonState = digitalRead(4);
  if (buttonState == HIGH)
  {
    fstTimeCall=true;
  }
  MoveEastback();
}

How many times through loop() will the pin be HIGH when you press the switch? More than once is my reading. Is that OK?

Or, do you need to detect when the switch was LOW and is now HIGH, and set fstTimeCall only when that transition occurs.

I didn't call for help..atleast in this post..

Then, this post belongs in the Exhibition/Gallery (hey, look what I did) forum, doesn't it? The fact that there are questions in it suggests not.