Creating a Block in Blockly

Posted on
  • Hi,

    I'm just trying to create my first block in Blockly for Espurino.
    I'm running the Chrome extension offline and editing the file "blockly_espruino.js".
    I made one function of the form "Blockly.Language.espruino_newFunction = {}" and one of the form "Blockly.JavaScript.espruino_newFunction­ = function() {}".
    But how do I actually see my new block? Is there a setting or something I'm missing? If anyone could list the steps to create a new block, I would really appreciate it.

    Thanks,
    Rehman

  • Hi Rehman,

    Great! To see the block, you need to add it to the toolbox, which is in EspruinoWebIDE/blockly/blockly.html. It should be pretty obvious how to add your own by looking at what's already there...

  • Thanks Gordon, that worked :)

    I have two more questions though:

    1. How do I see the JavaScript that the Blockly Code produces? I thought that toggling to the JavaScript view would update the code, but it does not.

    2. Is there a delay() or sleep() function? I just want to move a servo, wait a second (for it to move), then move it again. I thought setTimeout() would work, but it does not. This line of code works:
      setTimeout("analogWrite(C6, 2.0 / 50.0, {freq:20});",4000);
      But if I put this line after it, the code no longer works (properly):
      setTimeout("analogWrite(C6, 1.0 / 50.0, {freq:20});",4000);
      I tried playing with clearTimeout() to no avail.

    Thanks,
    Rehman

  • Great!

    To see the code, you might just be able to open the 'inspect element' window and go to the console - when you send to Espruino it should dump the code out there... You could always click in the left-hand pane and use up-arrow to check the history to see what was sent to Espruino...

    Your issue with the timeouts is that they're both run at basically the same time. If you do a timeout of 4000 for the first, and then 8000 for the second, it should work as you expect?

  • Thanks Gordon. The up-arrow trick works well to see the code sent by Blockly. I'm not sure how to open the 'inspect element' window.

    You're also right about the two calls happening at the same time. I read up on setTimeout() and see that it actually forks a new process that is executed at the specified time. But it is non-blocking. Is there a way to block? I tried writing a sleep() function, but that's not working either (see below). I also read that there's a way to get setTimeout() to work the way I want, but I can't get it to work.

    Thanks,
    Rehman

    function sleep(milliseconds) {
      var start =  getTime();
      var i = 0;
      for (i = 0; i < 1e7; i++) {
        if ( ( getTime() - start) > milliseconds){
          break;
        }
      }
    }
    
  • Blocking is really bad idea in Espruino, so it's intentionally made really difficult! Espruino isn't pre-emptive so a long loop like that stop all other timers/watches from executing.

    Is there any reason you can't do the following:

    setTimeout(function() {
      analogWrite(C6, 2.0 / 50.0, {freq:20});
      setTimeout(function() {
        analogWrite(C6, 1.0 / 50.0, {freq:20});
      },4000);
    },4000);
    

    That will execute the first timeout, and will then start the second one once the first has completed...

  • Hmm, nested setTimeout() functions. That works too. But unfortunately it doesn't solve my problem :(
    I'm actually trying to write easy Blockly Blocks to teach kids to program. So I want simple blocks like "Move Left", "Move Center", etc. I should be able to stack a bunch of these blocks in sequence, click run, and watch the servo go through the motions with a small delay between each.
    I'm not sure how to write the blocks to achieve the nested functionality in your last post. But if nothing else, maybe I can write them such that the timeout value is larger for each block added. It's not a perfect solution because I think it will require an init() block at the top of each program.

    Thanks again,
    Rehman

  • Well, you can easily do that, but you have to stack blocks inside of each other:

     after 1000ms do {
       set servo pos
       after 1000ms do {
         set servo pos
         after 1000ms do {
           set servo pos
        }
      }
    }
    

    I'm not sure that's actually such a hard thing to explain to children? It's harder for normal software developers because we're used to having things run linearly.

    Failing that, there might be a way to modify blockly - but that's a question to ask the developers of that...

  • Thanks Gordon :)

  • This works, not that I think doing this is a good idea in most circumstances.

    function delay(t) {
      var et=getTime()+t/1000;
      while (getTime() < et) {
    	et=et;
      }
    }
    
  • Thanks guys. I tried following your advice to not use blocking code, but ran into another problem. I can't change that value of variables inside the function prototype. For example, this code works:

    setTimeout(function () {analogWrite(B14, 1.6 / 50.0, {freq:20});},1000);
    
    setTimeout(function () {analogWrite(B14, 1.55 / 50.0, {freq:20});},2000);
    
    setTimeout(function () {analogWrite(B14, 1.5 / 50.0, {freq:20});},3000);
    
    setTimeout(function () {analogWrite(B14, 1.45 / 50.0, {freq:20});},4000);
    

    But this code does not:

    var pos = 1.6;
    var posInc = 0.05;
    
    setTimeout(function () {analogWrite(B14, pos / 50.0, {freq:20});},1000);
    pos -= posInc;
    setTimeout(function () {analogWrite(B14, pos / 50.0, {freq:20});},2000);
    pos -= posInc;
    setTimeout(function () {analogWrite(B14, pos / 50.0, {freq:20});},3000);
    pos -= posInc;
    setTimeout(function () {analogWrite(B14, pos / 50.0, {freq:20});},4000);
    

    The result is that it moves to position 1.45 at time 1000. So I guess it has already run "pos -= posInc;" three times before it first calls the analogWrite() function.

    Please help,
    Rehman

  • You need to put the pos-=posInc; inside the timeout.

    Right now, that is being run between the setting of the timeouts. So all three timeouts get set, and pos gets incremented three times. Then, a second later, the timeouts start firing, with pos at it's final value for all of the timeouts, because it got incremented way back when the timeouts were set.

  • Ah, that works well. Thanks DrAzzy.
    Another quick questions is: how do you change the default Blockly code that appears when you launch the Chrome extension? The JavaScript seems to remember the last code I wrote, but the Blockly code is always the default. Where can I edit this default Blockly code?

    Thanks.

  • The code's right at the top of blockly_espruino.js (and the actual data is at the bottom of blockly.html).

    You could probably fix it by adding to the code in js/core/code.js (halfway down). Although you may need to wait until 'windowloaded' gets called (see js/core/editorBlockly.js).

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

Creating a Block in Blockly

Posted by Avatar for rsm @rsm

Actions