Sync delay like Arduino delay function built-in

Posted on
  • Hi guys,

    I need your help because I need execute a sync delay similar to Arduino function built-in. Like this:

    module.moveServo(0,1000);
    module.wait(5000); // this code must be stop the execution until the time is completed
    module.moveServo(1,1000);
    

    I tried with:

    Contents of module_file.js:

    exports.wait = (time) =>{
      var i = 0;
      while(i < time * 10) {  i++; }
      console.log("Done!");
    }
    

    I tried also with:

    const startPoint = new Date().getTime()
      while (new Date().getTime() - startPoint <= ms) {/* wait */}
    

    And the result when tried to call more that 3000 ms is a dump and reset with this log:

    ets Jan 8 2013,rst cause:2, boot mode:(3,6)
    load 0x40100000, len 2408, room 16
    tail 8
    chksum 0xe5
    load 0x3ffe8000, len 776, room 0
    tail 8
    chksum 0x84
    load 0x3ffe8310, len 632, room 0
    tail 8
    chksum 0xd8
    csum 0xd8
    2nd boot version : 1.6
    SPI Speed : 80MHz
    SPI Mode : DIO
    SPI Flash Size & Map: 32Mbit(512KB+512KB)
    jump to run user1 @ 1000
    Œâìƒoä“r‚ûo|ì dldl`c²œð Ÿ|r’dœoàƒoã l ŒœoƒdŒûþLoading 4948 bytes from flash...

    What's happened? I'm very stressed with this.

    Thanks and XoXo,

  • @user97622, you are looking for a cycle waster? Nope, you ain't go-n-a get one, no matter how much I'm stressed you (try to) pull us over on... But let's start over on the good foot:

    Welcome @user97622 to Espruino and its forum!

    We all - including me - we understand where you are coming from... But come on a ride - with a thread of thought and Espruino - something you will never ever regret.

    Think about this scenario: instead of waiting and watching the clock painfully until it is time to do the next move, you set the timer / alarm clock and put your mind on something more enjoyable then constantly watching the hands moving or digits flipping and being terribly afraid to still miss the moment(s)...

    Espruino is event driven like JavaScript in the browser. When you do nothing in a Web page on the browser, (usually) nothing is going on. But when you hit a button in the Web page, things move. The way you set that up is that you tell the button '... onClick="doThis();" ...', or generalized: ...onEventXyz(doThis();...

    From your code, I cannot read what the application tries to get done. From what I though get is that the servo has to move, then wait for some time, and then move again...

    Your implementation of waiting until it is time is understandable. It though suffocates Espruino. Matter of fact it kills the whole system: the (error) message you get are its lasts words: "Your wasting of my cycles 'to wait' make me so busy that I cannot even do my home / house work, such as tending to Wifi, for what you like me so much!" :}

    The way out of this waiting business is to use one of these (time) event driven JavaScript language constructs:

    • setTimeout(thenDoThis,afterThisManyMilli­seconds)
    • setIterval(doThis,everSoManyMilliseconds­)

    Both use timers internally that take care of the deferring / postponing the business and let you - and your processing resource of the hook - to do something else until then. This is also the reason that the control returns immediately and is not stuck in waiting until time has passed. When set time will come, your business is taken care of without you having to do something. I intentionally use deferring or postponing instead of waiting, because waiting implies sitting idle or twiddling your fingers until the time of your appointment comes to pass... and that's not what you do and more so cannot afford in real life.

    Your requirement

    this code must be stop the execution until the time is completed

    gives me two options:

    • 1. When a particular time - real time - has come, you want the servo to move.
    • 2 . At a fixed time interval - for example every second - you want the servo to move.

    For option 1, lets take your alarm clock and your favorite music you want to be woken up by... so no matter when you go to bed, you set your alarm clock... of course you have now a phone that does that job. When you set the alarm and save it, it will give you feedback about how much time will pass until the alarm will ring... that's exactly what my (Android) phone does, and that's also what will implement here:

    Assume you have to get up at 6:30am... lets also assume you go to lala land
    before midnight...and with that we know the 'next' 6:30am will be the next day... actually, it does not matter. We can manage without making it too complicated.

    What we will do is to take the time now, calculate the time difference to 6:30am tomorrow, and tell Espruino to set the timer - timeout - for that time and upon timeout to turn the music on.To not get bogged down about how we would do the music thing, we just turn the red LED1 on.

    To get there, we need to know how many milliseconds (ms or MS) it is from now to tomorrow 6:30am

    Here comes the code... (c=`comment`; instead of // comment is used make to comment stick out vs. being dim and difficult to read. In real code you just use// comment and only where you think you need it to give a better understanding to the reader -will be yourself after a while you wrote the code....

    var wakeupHr = 6, wakupMin = 30; var c=`6:30am wakeup time`;
    var now = new Date();  c=`now is data and time, a Date class instance`;
    var wakup = new Date(now.getTime()); c=`we start w/ a copy of now and remove and add time units to get to the targeted wakeup date and time. `;
    wakeup.setHours(wakeupHr);  c=`setting the hours right`;
    wakup.setMinutes(wakeupTime); c=`setting the minutes right`;
    wakup.setMilliseconds(0); c=`blow the milliseconds away`;
    c=`---> wakeup date and time could be in the past... when going to bed between 6:30am midnight, but doing so between midnight and 6:30am, it is in the future. To make it right, we make former to be in the future by conditionally adjusting wakup (date and time), at the same time we convert date and times to milliseconds - the way we will need it after all to set the timer`;
    var wakupInMS = wakup.getTime();
    if (    (now.getHours() * 60 + now.getMinutes())
         > (wakupHr * 60 + wakupMin) ) { c=`hr and min is good enough!`;
        wakupInMS +=  24*60*60*1000; }
    var nowInMS = now.getTime(); c=`now in milliseconds`
    c=`finally, we calculate the time to defer and set the timer:`;
    var timerTimeoutTime = wakeupInMS - nowInMS;
    var timeoutTimerHandle = setTimeout(function(){
            LED1.set(); c=` turn red LED1 on in...
        }, timerTimeoutTime); c=`timerTimeoutTime milliseconds...`;
    

    And be assured that when power is not breaking down, your favorite music - sorry: just the red LED1 - will turn on 6:40am in the morning...

    There is a bonus to catch: your boss - friend? - calls you few minutes after you set this all up and tells you: lets hit the gym for 30 minutes before work or school or what ever you planned to do, you can use the timeoutTimerHandle to 'clear' the set timeout and set it for half an hour earlier:

    clearTimeout(timeoutTimerHandle);
    c=` .... do the same procedure as above to set the alarm - oops, music delight - to 6:00am straight...`;
    

    For option 2, you want to lite up the green LED2 for 5 seconds every minute and move the stepper motor 60 steps ahead. The code could look like below. To make it a bit better regarding CS in general and coding in particular, we define a function for what has to happen every minute:

    function blinkAndMove() {
        LED2.set(); // turn green LED2 on and...
        setTimeout(function(){
                LED2.reset(); // ...turn it off...
            },5000); // ...after/in 5000 ms
        // motor.stepForward(60); // do the 60 steps forward
    }
    
    var iId = setInterval(blinksAndMove, 60000); // get interval started
    

    To stop this ongoing blinking and moving, you use the interval Id (or handle) you got from interval setting and use it to clear the interval:

    clearInterval(iId); // stops the interval
    

    Often, the code needs to know if a set timeout or interval is still going on in order to branch accordingly. For that reason the defining of the handle and clearing of it looks 'better' when done like this, because starts correctly initialized and also clears the variable from the then 'defunct' timer handle...

    var intervalId; // declares it with value undefined
    
    // some other code
    
    intervalId = setInterval(someFunction, intervalTime);
    
    // some more code
    
    if (intervalId) intervalId = clearInterfal(intervalId)
    

    And if you deal w/ a setTimeout and the timed function is relate to one ant the same timeout handletimeoutId, first thing in the that function you clear the handle: timeoutId = undefined;

    Back to the way of coding events and times in Espruino:

    And before you even notice, your thinking has changed to the exciting and very powerful event driven way of doing things versus always running in a circle - down the check list, go back to the top, run down again, and again, and again, and so on and so fort - like in the Arduino main loop with constantly checking all kinds of flags... (that the modules have set on the actual events). So:

    Why not just attach the code to do to the actual event? There you go:

    Use Espruino!

    Driving directly by events is one of the reasons that things can run on a very small battery for a very very long time. The processor is active only when / while something is done...

    Related to these concepts you will encounter terms such as call back and Promise... but let's save that talk for later.

    I hope this helps you switch gears... enjoy, and come back and ask more questions, challenge the forum community, share your success to our joy, and pay forward...

    • ao
  • Wed 2019.02.06

    'What's happened? I'm very stressed with this'

    Deep breath, mantra tone ummmmmmmmm, another coffee, less coffee?

    It might be that the Javascript language is the culprit. I find that this resource is a good go-to when ideas are needed:

    https://www.w3schools.com/jsref/met_win_­settimeout.asp

    I believe that Option #2 in post #2 is what you are after.



    Should that darn servo just not want to cooperate, please post that code block using the 'code' button slightly above the edit window. You won't be able to scare us with what you have so far so no need to stress about that. Converting from C to Javascript does take a knack to get the hang of, but once one gets going, it is rather easy.

  • Just to add to this - the ESP8266 needs to be able to execute tasks every so often to handle things like WiFi. If you block it executing them, it cannot function. Because of this there's a 'watchdog timer' which resets the whole device if a task doesn't complete in time, and that's what you're seeing.

    @allObjects above has shown you how to do what you need - the lack of a delay function in Espruino is very much intentional - because it encourages behaviour that causes problems for many of the devices Espruino runs on.

  • Hi,
    You should be aware of:
    this dedicated page about Arduino+Differences
    and/or more MCU like functions as:
    shiftOut
    Waveform.startOutput

    Those are not necesseraly the answer to your precise question. But If you have very short waits then they will be the beginning of an answer.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Sync delay like Arduino delay function built-in

Posted by Avatar for user97622 @user97622

Actions