non blocking delay within a seperate function

Hi,

Im working on making one of my existing projects “better”

it isnt a very robust code, all changes I make mess something else up , so Im going to rewrite it and try to make it a bit “better”
It currently has a few voids which are using the delay() function, I would like to make the whole code non blocking if possible.

one such void is this

void ChangeMode(){
  if(Status==1){
    PressMode();
    delay(90);
    PressMode();
    delay(90);
    PressMode();
    delay(90);
    PressMode();
    delay(90);
    Status=3;
  }

the PressMode() is this

void pressMode(){

  pinMode(mode, OUTPUT);
  digitalWrite(mode,LOW);
  delay (100);
  pinMode(mode, INPUT);
}

im looking at the blink without delay example to work this out, I assume I have to set the previousmillis within the void as the “timestamp” and then keep setting the currentmillis in the main loop.

The problem that I forsee happening is that the void gets called, and the pause between push criteria wont have been met, therefore it will do one button push and nothing else, and in theory I would have to call the void again once the interval time had passed .

has anyone got any pointers for me while I’m trying to work this out ?

thanks,

non blocking delay within a seperate void

There are no voids in your program. There are FUNCTIONS!

ok , any advice on how to do it in a function?

I assume I have to set the previousmillis within the void

Within the void, huh? I don't think so!

The problem that I forsee happening is that the void gets called,

voids don't get called. Neither do ints, floats, Strings, or any other TYPE!

and the pause between push criteria wont have been met, therefore it will do one button push and nothing else, and in theory I would have to call the void again once the interval time had passed .

I don't understand what you are asking, here. If you are trying to replace all that delay() crap with things happening when it is time (ala the blink without delay example), you need to implement a state machine, so that on any pass though loop(), you know what to do next, based on what was done last and how long ago that was done.

and the pause between push criteria wont have been met, therefore it will do one button push and nothing else, and in theory I would have to call the void again once the interval time had passed .

I don’t understand what you are asking, here. If you are trying to replace all that delay() crap with things happening when it is time (ala the blink without delay example), you need to implement a state machine, so that on any pass though loop(), you know what to do next, based on what was done last and how long ago that was done.
[/quote]

i will look into how to make a state machiene then ,

your other two quotes were pretty dumb, considering that you know I previously used the word void instead of function.

The trick with @Pauls is to filter out the sarcasm and just focus on the advice - which is usually good.

I note that you have seen my Several Things at the Same Time Thread and I wonder if that has advanced things for you in your questions here? (And thank you for your kind comments).

...R

I have learnt that trick with PaulS in the past, But sarcasm is something that a keyboard cannot convey very well and how it is interpreted greatly depends on the mood of who is reading it at the time,

back on subject, after looking at your severalthingsatonce I have now made this function:

void PressTrigger(){
  if(TriggerState==0){
    TpreviousMillis=currentMillis;
  }
  
  
  if(TriggerState==1){
    pinMode(trigger, OUTPUT);
    digitalWrite(trigger,LOW);
      if (currentMillis - TpreviousMillis >= ButtonPushInterval) {
        pinMode(trigger, INPUT);
        TriggerState=0;
    }
  
}

My main loop looks like this :

void loop(){
  
  currentMillis = millis();
  keypad.getKey();
  ReadSwitches();
  Modem();
  PressTrigger()
  
  
}

Am I correct in thinking that if at some point in one of the other functions I set TriggerState to 1 that my desired result will only happen "in a non blocking way" for the period of time defined in ButtonPushInterval??

I hope so, I cant really test it yet because I have a lot of other blocking functions to make non blocking first, its probably a bad idea to do that before testing the first hurdle has been cleared though ..........

I notice that in your code snippet you only update TpreviousMillis when TriggerState is 0. Without knowing how the code is supposed to work I don't know if that will be a problem.

You have some nested IFs (which is not a problem in itself) and I wonder if it might make sense to test the time first so that no time is wasted on code until the interval has elapsed.

I like to write the occasional minimalist sketch to try out new ideas using the structure I am planning to use but without anything irrelevant to the idea I need to explore.

...R

Why are you changing the trigger pin between input & output modes? Not that you can't - I just can't figure out what you're doing.

robin , today i will make a test sketch, I have to implement a few other btis and bobs to test it works, but like you say, it may save time in the future,

Wildbill, I have that pin connected up to a camera trigger pin, i dont particularly understand the reason for doing i like this, I found it in the forum somewhere and it works,

The pin needs to be pulled low to tirgger, I dont know if the camera can handle it going high to stop the trigger or if just not pulling it low is enough , Im not in a hurry to break the camera finding out,

int Switch=A0;
int TriggerState=0;
unsigned long currentMillis = 0;
long TpreviousMillis;
long ButtonPushInterval=1000;
int SwitchVal = 0;

void setup(){
  pinMode(13, OUTPUT);
  pinMode(Switch, INPUT_PULLUP);
}


void loop(){
  ReadSwitches();
  trigger();
  currentMillis = millis();
  if(SwitchVal==LOW){
    TriggerState=1;
  }
   
  
}
void ReadSwitches(){

  SwitchVal = digitalRead(A0);
}


void trigger(){
   if(TriggerState==0){
    TpreviousMillis=currentMillis;
  }
  
  
  if(TriggerState==1){
    
    digitalWrite(13,HIGH);
      if (currentMillis - TpreviousMillis >= ButtonPushInterval) {
        digitalWrite(13,LOW);
        TriggerState=0;
    }
  
}
}

well , I made that test sketch, it is basically doing the same thing as the REAL one I would like to use, and it appears to work,

Ie i press the switch and the LED turns on for one second, I guess I should check it can still do other stuff during that second, but i dont see why it wouldnt,

You should probably put currentMillis = millis() at the top of loop() other wise trigger() will be using the older value.

...R

thanks for that, I also noticed that if the button is kept pressed then the code tries to light and turn off the led very quickly resulting in about 50% brightness,

But I have added a function to also send a message via the attached radio modem every second, that is working with no noticeable problems at the same time,

now i just need to implement a funtion to trigger the camera severaltimes in short succession,

void trigger(){
   if(TriggerState==0){
    TpreviousMillis=currentMillis;
    if((TriggerCount>0)&&(TriggerCount<=5)&&(currentMillis - TppreviousMillis >= ButtonPushInterval)){
      TriggerState=1;
    }
    if(TriggerCount>5){
      TriggerCount=0;
    }
  }
  
  
  if(TriggerState==1){
    
    digitalWrite(13,HIGH);
      if (currentMillis - TpreviousMillis >= ButtonPushInterval) {
        digitalWrite(13,LOW);
        TppreviousMillis=currentMillis;
        TriggerState=0;
        TriggerCount=++TriggerCount;
    }
  
}
}

this now flashes the light six times from one button push without blcoking the modem ping function.

just have to see what happens if the button is held, or pressed again during the flashing sequence,