• Hi
    Love the Espruino. Having loads of fun seeing what it can do. However have issue that is confusing me. Can somone help.

    I wrote the following code...

    var list = [
          {"b":0,"g":0,"r":0,"s":0},
          {"b":0,"g":0,"r":1,"s":45},
          {"b":0,"g":1,"r":0,"s":90},
          {"b":0,"g":1,"r":1,"s":135},
          {"b":1,"g":0,"r":0,"s":180},
          {"b":1,"g":0,"r":1,"s":120},
          {"b":1,"g":1,"r":0,"s":90},
          {"b":1,"g":1,"r":1,"s":60}
        ];
    var MIN_SERVO = 0.63;
    var MAX_SERVO = 2.34;
    var ONE_DEG = (MAX_SERVO - MIN_SERVO) / 180;
    var ZERO_DEG = MIN_SERVO;
    var step = 0;
    
    function posServo(deg) {
      return E.clip(MIN_SERVO + (ONE_DEG * deg), MIN_SERVO, MAX_SERVO);
    }
    
    var servoPos = posServo(0);
    
    function stopTimer() {
      if (timer) {
        clearInterval(timer);
        timer = undefined;
      }
    }
    
    function nextLights() {
      digitalWrite(LED1, list[step].r);
      digitalWrite(LED2, list[step].g);
      digitalWrite(LED3, list[step].b);
      servoPos = posServo(list[step].s);
      step = (step +1) % list.length;
    }
    
    var timer = setInterval(nextLights, 500);
    
    setWatch(function() {
      stopTimer();
      nextLights();
    }, BTN1, {"repeat":true,"edge":"rising","debounce­":10});
    
    var sp = setInterval("digitalPulse(C5,1,servoPos)­", 20);
    

    This works fine, my lights blink, my servo moves...
    When I save() and reset the code does not start! However if I press the button it does get to the setWatch function and the device works from there.
    If I do a dump() however there are some confusing changes to the code.

    var list = [
          {"b":0,"g":0,"r":0,"s":0},
          {"b":0,"g":0,"r":1,"s":45},
          {"b":0,"g":1,"r":0,"s":90},
          {"b":0,"g":1,"r":1,"s":135},
          {"b":1,"g":0,"r":0,"s":180},
          {"b":1,"g":0,"r":1,"s":120},
          {"b":1,"g":1,"r":0,"s":90},
          {"b":1,"g":1,"r":1,"s":60}
        ];
    var MIN_SERVO = 0.63;
    var MAX_SERVO = 2.34;
    var ONE_DEG = 0.0095;
    var ZERO_DEG = MIN_SERVO;
    var step = 5;
    function posServo(deg) {
      return E.clip(MIN_SERVO + (ONE_DEG * deg), MIN_SERVO, MAX_SERVO);
    }
    var servoPos = 2.34;
    function stopTimer() {
      if (timer) {
        clearInterval(timer);
        timer = undefined;
      }
    }
    function nextLights() {
      digitalWrite(LED1, list[step].r);
      digitalWrite(LED2, list[step].g);
      digitalWrite(LED3, list[step].b);
      servoPos = posServo(list[step].s);
      step = (step +1) % list.length;
    }
    var timervar sp = 2;
    setInterval("digitalPulse(C5,1,servoPos)­", 19.99950408935546875);
    setWatch(function () {
      stopTimer();
      nextLights();
    }, "B12", { repeat:true, edge:'rising' });
    digitalWrite(A15,1);
    digitalWrite(C5,0);
    

    var step is set to 5, somtimes 7... never 0;
    var servoPos = 2.34. However if I run from console I get the following:

    posServo(0)
    =0.63
    

    also the line

    var timer = setInterval(nextLights, 500);
    

    is re-written as:

    var timervar sp = 2;
    setInterval("digitalPulse(C5,1,servoPos)­", 19.99950408935546875);
    

    and the var timer is not set and timervar is introduced. This is a mix of

    var timer = setInterval(nextLights, 500);
    

    and

    var sp = setInterval("digitalPulse(C5,1,servoPos)­", 20);
    

    Finally the setWatch parameters are missing the "debounce":10

    I updated to 1v67.. Read some entries in the forum and downgraded to 1v66 but it still does not work.

    When I received Espruino I updated straight away and did not see and evidence of this. that was about a week ago. however in my excitement I did not note which version it upgraded to.

    Currently it works from ram not from flash. If I reset() in the console(), press the reset button, disconnect battery and re-connect or load() in the console it does NOT run.

    It tried minification on and off. It still does not work...

    Can you please help...

    Stuart

  • Sorry about the mess but the formatting seems to be messed up. If yo uneed separate copies of the files I can provide.

    Stuart

  • The issue with the code not displaying is that you need a newline before and after each section of code that you paste in...

    I think the main issue you're hitting here is that when you send code to Espruino from the right-hand pane, it's executed immediately. That means if you say:

    var foo = myFunction();
    

    Then foo will forever be set to the result of myFunction() - it won't be executed each time you start. Espruino has always worked like this - it's nothing new. When you type dump(), Espruino tries to reconstruct the code that you wrote based on its current state (by adding setWatch, setInterval, digitalWrite, etc) - and sometimes it doesn't get it exactly correct.

    It's most noticeable for setInterval/setWatch which return integers - so Espruino has no way of knowing that the number 2 assigned to sp came from setInterval, and not just you writing 1+1.

    To get around this, it's best to put code that you want to start into a function called onInit(), which will automatically get called when Espruino starts up:

    var list = [
          {"b":0,"g":0,"r":0,"s":0},
          {"b":0,"g":0,"r":1,"s":45},
          {"b":0,"g":1,"r":0,"s":90},
          {"b":0,"g":1,"r":1,"s":135},
          {"b":1,"g":0,"r":0,"s":180},
          {"b":1,"g":0,"r":1,"s":120},
          {"b":1,"g":1,"r":0,"s":90},
          {"b":1,"g":1,"r":1,"s":60}
        ];
    var MIN_SERVO = 0.63;
    var MAX_SERVO = 2.34;
    var ONE_DEG = (MAX_SERVO - MIN_SERVO) / 180;
    var ZERO_DEG = MIN_SERVO;
    
    function posServo(deg) {
      return E.clip(MIN_SERVO + (ONE_DEG * deg), MIN_SERVO, MAX_SERVO);
    }
    function stopTimer() {
      if (timer) {
        clearInterval(timer);
        timer = undefined;
      }
    }
    function nextLights() {
      digitalWrite(LED1, list[step].r);
      digitalWrite(LED2, list[step].g);
      digitalWrite(LED3, list[step].b);
      servoPos = posServo(list[step].s);
      step = (step +1) % list.length;
    }
    
    var step, servoPos, timer, sp;
    
    function onInit() {
      // just in case other intervals were already running when we typed 'save()'
      clearInterval();clearWatch();
      // now init
      step = 0;
      servoPos = posServo(0);
      timer = setInterval(nextLights, 500);
    
      setWatch(function() {
        stopTimer();
        nextLights();
      }, BTN1, {"repeat":true,"edge":"rising","debounce­":10});
      sp = setInterval("digitalPulse(C5,1,servoPos)­", 20);
    }
    
    // Explicitly call onInit, so it starts working (this time) even before you save:
    onInit();
    

    Having said that, there seem to be other issues:

    • There's a bug in Espruino where it doesn't seem to like dumping a value if it is undefined. Hence why you get var timervar sp = 2; instead of what you should see, which is var timer = undefined; var sp = 2;
    • Given timer is undefined, it looks like the button has already been pressed (and so stopTimer() was called) by the time you save() - which would explain why nothing happened in your case. I just tried your exact code here and it works fine.
    • The missing debounce is a bug too - i'll try and get that fixed for 1v68.
  • Just wanted to add that while Espruino has a hard time turning its internal state back into text, it doesn't mean that save() suffers from the same problems as it saves the internal interpreter state.

    I think that in your case, using your existing code and just saving before you press BTN1 would solve your problems. At least it worked for me :)

  • Thanks for the reply.
    The formatting went away when I returned to the forum later. Seemed to sort itself out!

    Thanks for the reformatted code I will give it a try. I can see the logic now so it makes sense. Coming from a Java background you may see where my confusion stems from.

    My process was to upload the code, then press the button, then save(), then do the dump().

    Am I right is saying that the current value of the var's is wirtten to flash with the source when a save() is run and dump inlines the values with the source.
    A load(), reset... then reads the state, including the saved values, back to ram.
    You would normally expect a reset to ZERO all state and start running the source from the top. It's a bit mind blowing especially if the app has many states.

    So onInit() is run on reset, reset() and power-up. Is it run on load() as well.

    I do think the coding examples need to show this feature of the language.

  • Seemed to sort itself out!

    Not quite. I did it :)

    My process was to upload the code, then press the button, then save()

    Yes, so it saved the state of the board after you'd pressed the button :)

    Am I right is saying that the current value of the vars is written to flash...

    Yes, that's basically right - except reset() resets everything - it doesn't load your code at all.

    So:

    • save() : save the current contents of RAM into flash
    • power on/hard reset/load() : load image from flash into RAM, run onInit()
    • reset() : reset everything to 'factory fresh'

    It's a bit different to a compiled language, but it makes sense as there isn't space for it to store both the original state and the new state at once.

    There is some at the bottom of the Quick Start:

    The save() command saves the current state of the pins and on-chip peripherals, as well as all your functions, variables, watches and timers. The commands that you typed in previously won't be executed again though. If you want to execute some code when Espruino starts (for example you may need to initialise some external bit of hardware like an LCD), create a function called onInit.

    and it's touched on slightly in Troubleshooting. It's hard to know where people will look for it though! It seems most people (like me) don't read much of the documentation until they actually have a problem!

  • OK - Thanks for sorting it out.

    This is really useful if when the code does a save() all state is saved, it means that after a power down and reboot the state is restored.

    I assume the local variables in onInit() are not saved, just the globals.

    Thanks for the response. Very encouraging.

    All I need now is for Espruino to run bare metal on a RaspberryPi...... Put it on my wish list!

  • Everything is saved that you'd expect if you took a 'snapshot' of memory... So:

    function foo(a) {
      setTimeout(function() {
        console.log(a);
      }, 1000);
    }
    
    foo(42);
    save();
    

    will print '42' the next time around, even if it's not global.

    The one 'gotcha' is that save() is executed when the interpreter is idle, so:

    function foo() {
      console.log("Hello");
      save();
      console.log("World");
    }
    

    Will print 'Hello', then 'World', then it will save the state.

    It's probably not a nightmare to run Espruino bare-metal on the Pi, but the second you want USB/Ethernet/Video/Sound/etc it's going to turn into an enormous amount of work :)

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

Confusing changes to code made by save() - dump()

Posted by Avatar for Stuart.d.d @Stuart.d.d

Actions