• #blockly #graphicalprogramming #visualprogramming

    First of all, Espruino is event driven, in other words, it does not kill time by nested loops of doing nothing - like the way time is killed in the Arduino code loop - but by setting a timer and linking it to a piece of code that will be run when the timer times out (In Arduino, you can of course use events too - interrupts based on a timing out event of a timer, but it is way more complicated than in Espruino... that's why many of us Espruini - or Espruine, to be politically correct and complete - are so thrilled with Espruino!).

    Espruino's main difference to the typical setup of a code loop is that it work only when there is something to do triggered by all sorts of events, such as a timing out timer, a status change of a watched pin, an input available, or some other under the hood created software events. Between the actvities, Espruino can go into very very deep, deep sleepto make a large battery outlive you - litteraly (of course, battery with 'no' self-dicharge).

    In your code(s) above, after serting up the timer (javascript: setTimout(...)), it goes to the next statment, which invokes makeSound() rightAway (again)... and you will be able to confirm thia fact when closely lookinf at the description of Espruino-blockly-wait.

    The right-away invoking of itself will make Espruino end up with out of memory / stack-overflow, because makeMusic calls itself within itself / while it is still executing. You can fix this issue easily: move the makeSound into the do of wait. This way it does most closely what you described in your first blockly post: check after 5 seconds C7 and C8, and if one is on, get the sound going again and checking again after 5 seconds, and so forth, or switch sound of and wait for the next C6 to fall and get music going.

    *I 'despise' this wait term,... it even trips me! - A better working wording would be: **time this code block *, similar to setting an egg / kitchen timer to get reminded to check and take the eggs off the fire after set time... Just as you don't let yourself be held up until the timer rings from moving on doing other work, so does Espruino.

    By now you noticed: there is no loop in the programmatic sense of 'while' or 'for' or 'repeat-until' (even though an interval may look like a loop as in the first blockly post, it is not. It is more like a timing with repetition or continuous timing. And since ou get a handle back on the setup var intervallTimer = setTimeout(myFunction,intervalTime);, you can use this handle to clear the interval and with that the repetition: clearInterval(intervalTimer);. Btw, same applies for the timout: var timoutTimer = setTimeout(myFunction,timoutTime);, so that when some event else than the timeout makes the timeout obsolete, the timeout can be cleared and prevented from happening: clearTimeout(timoutTimer);.

    Above blockly code has still an issue afer fixing: while the sound goes on - and the 5 seconds are passing to switch it off and eventually on again, C6 can go low again... and trigger another run of makeSound. Such constructs create nice, upredictable, and difficult to detect application behavior... Therefore, you make the watching a single shot, and after switching the sound off (or not switching it on because neither C7 nor C8 are on), you set the watching again.

    The javascript code for that would look like this (otice the debounce AND repeat options which blockly does not support and in Espruino Javascript default to no-debounce and false, respectively, and therefore blockly's default option settings are unknown to me. - @Gordon, do I miss something here?):

    pinMode(C6,"input_pullup");
    pinMode(C7,"input_pulldown");
    pinMode(A8,"input_pulldown");
    pinMode(C9,"output");
    analogWrite(C9,0);
    var makeSound = function() {
      if (digitalRead(C7) || digitalRead(A8) {
        analogWrite(C9,0.5);
        digitalWrite(LED1,1);
      } else {
        analogWrite(C9,0);
        digitalWrite(LED1,0);
        setWatch(C6, makeSound, { edge:falling,  debounce:100 });
      }
    };
    onInit() {
      setWatch(C6, makeSound, { edge:falling,  debounce:100 });
    }
    

    Instead of coding setWatch(); in two places, you could just invoke makeSound(); in onInit() instead and it would work too (with a potential issue that sould could go on right away if C7 or A8 are on to begin with, even thoug C6 never did fall...)

    The blockly code looks like as attached screenshot.

    I'm sure you did also some initializing....

    Btw, with given code uploaded, you can type save() in the console (left pane of the Web IDE), which saves your uploaded code in Espruino. Anytime when you re-power your Espruino (Pico), the onInit() runs and Espruino does again what you expect - witout having to upload the code again (In my example, I switch also the LED1 to give a visual feedback).

    What I miss in blockly too - aside of the watch options - is the ability to set a variable to a function, which then would allow to make the execution sequence very clear: first the initializations, then the (makeSound) function assigned to a variable, and lastly the onInit() with the initial setWatch().

    PS: You may hear the re-switching-on as a hick-up. To avoid that, you would keep the on or off state in a global variable and execute the switching on only when not on (yet), and - of course - swtich of only when not switched off (yet). As a human listener, you may not hear nor notice the hickup because Espruino is so fast, but another Espruino potentially 'listening' to your signals will notice. Therefore you want to fully control what is happending. You find the solution in the second blockly attachement.


    2 Attachments

    • NoWaitNoLoop.png
    • FullyCotnrolled.png
About

Avatar for allObjects @allObjects started