I Sleep You 3000

Posted on
  • the current 'wait x seconds' for Espruino blockly doesn't always work as intended.

    for example, if a while(true) loop containing a wait x seconds block, for javascript, it doesn't really wait for the setTimeout function and will just immediately execute the next iteration.

    e.g. the attached image will be converted to:

    while (true) {
        setTimeout(function() {
            digitalWrite(LED, 0);
            setTimeout(function() {}, 1000*1);
        }, 1000*1);
    }
    

    Which is pretty confusing for the blockly user

    So I implement a sleep function as stated in https://stackoverflow.com/a/16624104/63226

    var sleep = function (miliseconds) {
       var currentTime = new Date().getTime();
    
       while (currentTime + miliseconds >= new Date().getTime()) {
       }
    }
    

    It works when I execute like sleep(1000) or sleep(2000), but for sleep(3000) the nodeMCU resets itself.

    Is there a max execution time that forced the nodeMCU to reset? if yes, then how to increase it?

    Thanks


    1 Attachment

    • Screenshot 2019-06-18 at 11.32.22 AM.png
  • Mon 2019.06.17

    @Unreality this experiment is creating a true Unreality! ;-)

    Did you catch the bold text just beneath that code snippet from the link provided?

    "Note: The above code is NOT recommended."

    Forcing the processor to block other requested scheduled tasks is a bad practice, as you have discovered. A forced break/exit is most likely by design as this article points out:

    https://cs.stackexchange.com/questions/9354/what-mechanisms-prevent-a-process-from-taking-over-the-processor-forever

    The datasheet for your particular processor may have an explanation also.

    The original snippet using setTimeout is the recommended way to go.

    re: 'Which is pretty confusing for the blockly user'

    What is the true purpose, an attempt to make Javascript instructions look pretty?

  • @Robin
    For kids to use blockly to program the microcontroller, so the javascript should exactly reflect what it intends, that is, to wait between loops' interations

  • Yes, while it looks sensible, what you did in fact does not makes sense in event based system like espruino. The while block is useful only for short code that finishes quickly and not with true condition and not with any wait inside.

    Your blocks would translate well to e.g. micropython. Yes it is confusing and your case perfectly shows how those blocks are hiding the true nature of event based javascript and Espruino. The first generated code is in fact complete nonsene, which is not your fault. Your fix is well meant but not really helping, check e.g. this explanation

    Maybe the block->code generation could be much smarter to create illusion that this works but it looks like currently it is not clever enough.

  • @fanoush
    This is how blockly implemented waitForSeconds in their additional layer of Javascript interpreter:

    https://blockly-demo.appspot.com/static/demos/interpreter/async-execution.html

    You can see that the 'waitForSeconds' work completely fine.

    There is way to make the blockly makes sense in execution, so I think Espruino could do something to support 'waitForSeconds' like that Javascript Interpreter layer, and thus would make kids far more easier to play with Espruino?

  • Oh, they have this sandboxed 70Kb minimized javascript interpreter written in javascript to allow this. Looks a bit heavy for Espruino.

  • The nodeMCU resets, because the ESP8266 has a watchdog, and the while loop prevents control returning to the underlying Espressif OS. But I'm pretty sure it would mess up USB and Bluetooth communications as well. Also, even a simple uart buffer - that uses HW uart & buffer - could overflow in a couple of seconds.

    Almost wrote that there could be a "main loop a'la arduino" thing in Espruino-Blockly, that emulates the expected behaviour. But the purist inside me thinks that kids mind should not contaminated be by seeing a blocking wait call on a microcontroller. Or actually in any code. Even if everybody seem to do that.
    Did you know that god kills a kitten when you use blocking wait in any code? :O

    Instead if the while(true) block, you can use the run code every X seconds block I guess.

  • why is it a poison for kids? some language supports the wait function, why limit event based javascript to the mind of a kid?
    it is all about the interpreter

    also with ES7 it can support async and await, is it really a poison?

  • there are times we need for loop and have wait for seconds within it

    kids do not know about multithread etc, why limit their mind and treat "wait/sleep" as abnormal

  • The poison part meant to be slight joke.
    In most languages a delay / wait literally waits at that point, and nothing else can happen simultaneously. This leads to locked-up UIs & CPUs sitting and waiting later. More and more languages include some form of async-await, or already have Future / Promise / Task to help avoid blocking code and callback hell.

    If you do that with async-await, it won't block the CPU, it 's just a state machine, that gives the illusion of "sync" code. While allowing the CPU can do whatever it wants. Execute other code, or go to sleep to save energy.

    Ok, that's really far from a kid just learning programming, and I have no experience teaching kids. So you are right, it should be as simple as possible.
    If someone has never seen programming, I guess the concept of a while loop is something new as well.
    Can you get to the same end result with run code every X seconds block?
    For example: can you easily blink 2 LEDs at different frequency? Have never played with Blockly & Espruino, but I think that would need two "timer" blocks, and pretty much done. It would be much difficult in a while loop.
    For interaction (UIs with buttons & leds, or some external chip) an event-driven approach feels better. Honestly, don't know which one would be more easier for kids to grasp. I started with Pascal & C in the school, for and while loops, etc. Those languages don't support async. But what if a kid can start with a language that has async support?

  • The blocks "After n seconds do" and "Every n seconds do" are suited for the task, like this:

    Every 2 seconds do
    ----After 1 seconds do
    --------print "LED 1 off"
    ----print "LED 2 on"
    

    And yes, it first prints "LED 1 on" and then "LED 1 off", and that makes complete sense. If you tell someone to switch the light out after 1 minute from now on, and then to switch the lights on immediately the exact same thing will happen: Lights on first, then lights off. So I'd say even kids can understand this.

    Now duplicate the block, multiply the numbers by 2.5 and update the text. The kids will see the real power of async programming. You could toggle one LED at 1 Hz and another one at 2.5 Hz. How would you do this with a while loop using waits?

    The wait block should be removed for Espruino as it doesn't do anything useful, Javascript being an async progamming language.

  • being an async progamming language.

    do you mean javascript ES7 which supports async / await changed the nature of language?

  • No, it's still async. In Espruino you can take the block "Wait BTN1 both edge do", that is basically the same as an await. And ofc the "sleep" functions implemented in ES7 are still async, if there's any function triggered while a "sleep" function is "active" that function will be executed.
    The give an example:
    -You have the LED "toggle" function, switching an LED on and off every 1 second, either with setInterval() or with a ES7 "sleep" function.
    -You have another "fancy" function to do some fancy stuff, taking 3 seconds.
    Whenever the "fancy" function is executed your LED will stay on (or off) for 3..4 seconds, because the "toggle" function is only executed after the "fancy" function has completed, because there's no multitasking and things run async.

  • Async-await does not make it sync. It only gives the "illusion" of synchronous execution.

    For example Typescript has / had a state machine that supports async/await without browser support. It's a state machine that gives an illusion of sync execution while the code actually executes async + on one thread. Now async is supported by most browsers, but I thought it's worth mentioning. So it's not block-the-browser sync & works (and did work) without browser support.

    For example unless you await some async function, it won't wait for you. This confuses developers often, at least confused some guys at work. Also, same effect as a trap: try-catch won't catch your async exception, if you don't await the async call. Confused guys at work...

    Check out this plunk for an example. Try to guess what happens without looking at the console :)

  • This is a different wording of the facts @AkosLukacs points out in post #7.

    The problem is that blockly does not think event driven. Javascript is a single threaded executed... and wait - by constantly checking time until time arrives - just cannot exist in such an environment, and - worse - in Espruino, it hogs the processor until 'snippet' is completed. Never ever implement something like in second code block of #1 post. Even the while loop hogs the processor... it comes from the outdated main loop concept (erroneous reestablished and 'hardened' in the public mind by Arduino - so retro), a concept that was introduced in machine control with digital logic a good 50 years ago... derived from / emulating the even much older electro mechanical 'Schrittschaltwerk' - automatic stepping mechanism. The automatic stepping mechanism is a list of unconditioned and conditioned steps that are executed one after the other over and over again. It is easy to understand but extremely limited...

    (If you are using ESP8266, your processor reboots constantly... because the Wifi stack on it has an interrupt cycle of a given number of micro seconds to take care of urgent communication work, and when it does not get the control of the processor, it resets itself. This means in other words that the javascript executed on an even can only take so much that it still fits into this interrupt cycle window... From the total processor time only a percentage is available to other code / application code / Espruino code, and this code has to finish within a given number of microseconds. The other percentage is used by the Wifi stack).

    What actually happens in the blockly code is the following:

    • create the while loop with true executing this code:
      • crate an entry in the 'time table' - so to speak - that after 1 second execute the following code:
        • turn the led off
        • create an entry in the time table hat after 1 second executed the following code:
          • nothing

    Creating the entry in the time table takes practically no time -returns immediately - to executed next statement, and now y0u understand that the code creates tons of execution deferred pieces of code... until it rans out of space in the time table... (paraphrased), and never ever even 'gets the time' to work on these scheduled blocks of code...

    SetInterval and SetTimeout is not a waiting kind of thing but a scheduling thing scheduling a piece of code to be executed at scheduled time (now plus delay), is executed immediately with control returning immediately.

    Try something like that in blockly:

    • create a boolean variable b that you set to true.
    • create a function f that includes the following:
      • wait (blockly's incorrect notion of schedule following code to be executed after wait time
      • turn the led on / off
      • if query the boolean variable b, and if true:
        • invoke 'yourself' - the function f
    • invoke the function f - to get it all started

    Invoking the function f you even can - should - do with a wait, because you want to let the upload finish - because it is also a Javascript snippet(s) execution.

    • create a boolean variable b that you set to true.
    • create a function f that includes the following:
      • wait (blockly's incorrect notion of schedule following code to be executed after given time)
      • turn the led on / off
      • if query the boolean variable b, and if true:
        • invoke 'yourself' - the function f
    • wait (blockly's incorrect notion of schedule following code to be executed after given time)
    • invoke the function f - to get it all started (after upload completed)

    The sequence you create this logic in blockly is to create the function first, and then the other code:

    • create a function f - a named block of code - that includes the following:

      • wait (blockly's incorrect notion of schedule following code to be executed after given time)
      • turn the led on / off
      • if query the boolean variable b, and if true:
        • invoke 'yourself' - the function f

    • create a boolean variable b that you set to true.

    • wait (blockly's incorrect notion of schedule following code to be executed after given time)

    • invoke the function f - to get it all started (after upload completed)

    I'm sure you have some other logic that controls boolean variable b and as well some variable code that determines whether the led should be turned on or off...

    @Gordon, I guess it is time to thing of something more Espruino / JS / Event driven and 'ban' the (inferior and in reality never used concept of) wait (by killing processor cycles by just looping around and checking time)... for examle: scheduleOnce and scheduleRepeated as an (right hand) expression returning the handle and with the look of the while/for loop or if/else to make clear the block structure. (Something on your already tall pile... may be there are takers in the forum...). I wanted to use blockly in its current from, but it got so cumbersome that learning JS and coding in a language in text from is what just works better.

  • Sun 2019.06.23

    Agree with your last sentence @allObjects re Blockly. I also like your idea of scheduleOnce() but would/will the resultant code and understanding be any better than setTimeout()?



    For @Unreality,

    'Is there a max execution time that forced the nodeMCU to reset?'

    Found a nice article explaining both the Hw and Sw resets for ESP8266

    https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/


    EDIT: Sun 2019.06.23
    I like the concept of Blockly, especially for children and individuals (
    yes, there are those that don't get ;-) us!)
    that just don't grasp the concept of programming. From what @Unreality #3 points out, there is a need to have an easier way of explaining in code what is actually going on for each of the 'blocks' involved. A fundamental issue is that the minds concept of 'wait' is much different that how a microprocessor functions, and how code is executed, especially when instructions are interpreted line by line. As both @allObjects and I discovered, using Blockly as a solution is a bit cumbersome, and for us, typing text is easier on the mind.

  • @allObject: The two blocks "After n seconds do" and "Every n seconds do" are already there. I'm not sure why you introduced scheduleOnce() and scheduleRepeated(), do you want them as js functions or blocky, and how would they differ from the existing js functions setTimeout/setInterval or the existing blocks?

  • Sun 2019.06.23

    @maze1980, I see that you are a recent member to the forums, forgive me if explaining this implies otherwise.

    While I'll defer to @allObjects for an author official explanation, and while his availability is rather limited, and a considerable amount of effort went into laying out that content, . . . IMO if you'll note, his last paragraph was addressed to Gordon, . . . 'for example' . . . and as a suggestion with content to enhance Espruino and not directly meant to change how the core Javascript is defined.



    In your explanation #13 my interpretation is that I believe that you believe the difference, but the explanation needs a bit of cleanup.

    Excellent article:

    https://johnresig.com/blog/how-javascript-timers-work/

    ref #13 ' if there's any function triggered while a "sleep" function is "active" that function will be executed.'

    ref #14 @AkosLukacs 'executes on one thread'

    From the article and the above post, the 'actual' code is 'queued', along with the event, and running in a single thread. So there isn't a guarantee the function will be executed immediately as in your explanation.

  • @maze1980, yes, I would like to have blocklies with these names. Of course, they will use setTimeout() and setInterval(), and furthermore, return the handle, so they can be canceled: cancel(handle)... another blockly... and the wait I would retire, because it conveys the wrong concept: Scheduling is not waiting... but I see your point that "After n seconds do" and "Every n seconds do" already do that... missed it. The only thing they are missing is to be able to store the handle... and there is no cancel to use the handle... Introducing the concept of scheduling makes cancel understandable...

  • I agree, it makes sense. Maybe it goes beyond what most users would build with Blocky, but as long as a handle and cancel block are not implemented nobody knows for sure.

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

I Sleep You 3000

Posted by Avatar for Unreality @Unreality

Actions