Question about wait() and program logic



  • Hello,

    I'm planning to rewrite a sketch which actually is handling a RGB led strip. For now I've written the sketch to fade out from Red 100% to off in some minutes. The fade out is managed by the Controller (OpenHAB). It sends the command to the node every 'x' seconds with a new lower dimmer value until it comes to zero, in this way:

    Controller -> Red color 100% -> Node
    after minutes
    Controller -> Red color 90% -> Node
    after minutes
    Controller -> Red color 80% -> Node
    (...)
    Controller -> Red color 0% -> Node

    The procedure stops.

    It works most of the time.

    Sometimes happens the Node doesn't answer well. So It happens the led remains on even if the Controller has sent the command to turn the light off. I'll debug it better from hardware side, but I was thinking a different approach as well.
    I would like to move the logic on the Node in this way:

    Controller -> send V_LIGHT status set to 1 -> Node
    In the void receive() I check if the message.sensor is set to the Sensor-ID associated to my trigger and in case it starts a function that turns the RedLight off... something like this:

    void receive(const MyMessage &message) {
      if (message.sensor == 10) {
        RedOff();
      }
    }
    
    RedOff() {
      // turn Red ON 100%
      analogWrite(RED_PIN, 255);
      // Fade Red Off
      for (r = 255; r > 0; r--) { 
        analogWrite(RED_PIN, r);
        wait(1000);
      } 
    }
    

    This procedure would fade out in 1000 * 255 = 255000 ms = 255 seconds = 4 minutes more or less.

    My question is:

    Would this the best approach to reach the goal?

    Then, in case I would STOP the fade even if the RedOff() procedure is not finished, in example turning on a different light attached to the same Node, how to do that?
    AFAYK the wait() function calls process() to handle incoming messages during the delay, but I'm missing the logic on how, if a different message is coming to the node, should STOP the RedOff() procedure.

    Any help would be really apreciated!

    Thanks!

    Simon


  • Contest Winner

    @xefil Dear Simon,

    Whether or not this will solve you problem. Your implementation is not a good strategy (in my opinion).

    You block everything in the main loop when you enter the redOff() function. So what happens if during the turnOff method you node receives a turn on?



  • @TheoL that's exactly what I would like to handle and don't know how.
    The wait() command should not stop to accept messages. Is there a way into the RedOff() function to stop the execution in case I get a message I need to handle? Like a turnOn as you said. Maybe @tekka or @hek have better ideas from their experience 😉
    Thanks!
    Simon


  • Admin



  • @hek , great - simply approach!
    If I'm not wrong, your fade function does NOT fade out until the end in one shot, but it simply it's called 'x' times between checks for button or rotary. Right??

    Another question: When is exactly the void receive() function called? At the end of every loop()? I'm missing a little bit this part.... 😉 but seems I'm understanding a way to solve what I would like to do!
    Thanks!!
    Simon


  • Admin

    receive() gets called here:

    https://github.com/mysensors/MySensors/blob/c85de960d40d140205fa5a752a07fabe8c09a2ea/core/MyTransport.cpp#L573

    Normally transportProcessMessage() gets called once every loop (unless you use wait()).



  • @hek , thanks for the clarifications.
    What do you mean:
    Normally transportProcessMessage() gets called once every loop (unless you use wait()).

    Does wait() call transportProcessMessage() as well on every use? That would make sense.

    I.e.:

    void loop(){
      // transportProcessMessage() is called in background somewhere here and so receive(_msg) as well.
    
      // some code..
      
      wait(100); // this calls transportProcessMessage() again and so receive(_msg) as well.
    
      // other code...
      
    }
    

    Is that above correct?

    If yes, then my initial aproach would work as well. a procedure where wait() is called like this:

    RedOff() {
      // turn Red ON 100%
      analogWrite(RED_PIN, 255);
      // Fade Red Off
      for (r = 255; r > 0; r--) { 
        analogWrite(RED_PIN, r);
        wait(1000);   // <<<<--------- here it checks for new messages and I could interrupt this procedure.
      } 
    }
    

    BTW I prefer your approach taken from 'DimmableLightWithRotaryEncoderButton.ino'. Seems more clean.

    I ask you that, only to understand correctly how the logic works.

    Thanks a lot,

    Simon


  • Admin

    @xefil said:

    Does wait() call transportProcessMessage() as well on every use? That would make sense.

    Yes it will call it multiple times depending on how long you wait for, which could call your receive() -> RedOff(), which would call wait(), and so on.. resulting in a unpredictable call-stack size. The arduino would probably crash if you receive many incoming color changes.



  • @hek ok, thank you!
    I'll adopt your example as starting point.
    Many thanks!

    Simon


 

424
Online

7.9k
Users

8.8k
Topics

93.8k
Posts