Something is wrong - PICO

Posted on
  • When I send my code to the PICO by calling save() in the WebIDE, everything appears to work. I then unplug the USB cable, then when I either plug the USB cable back in or connect a power source/battery, it is obvious that the PIC is not running the code I just sent it. In some cases it seems to run a previous version that I sent to it via this method, in other cases it just seems to do nothing.

    No errors are reported via the WebIDE console, everything appears to be working, but it clearly is not. This happens on 2 different PICO's and both with the previous and latest firmware. Also tried on both Windows and OSX, same results.

    Seriously WTF is going on here, what am I missing? So frustrating...

    As an example, this is how simple the code is that I'm testing it with right now.

    function blah(){
      setTimeout(function(){
        digitalWrite(LED1, 1);
        setTimeout(function(){
          digitalWrite(LED2, 1);
          setTimeout(function(){
            digitalWrite(LED1, 0);
            digitalWrite(LED2, 0);
          }, 1000);
        }, 1000);
      }, 1000);
    }
    
    blah();
    
  • Is there a way I can just reset it to factory state, like by flashing a custom firmware or some such thing? Both PICO's were working fine up to a couple of days ago, when I noticed this and initially thought my code must be broken, so I simplified it down the example above to eliminate that.

    Clearly there's something fundamentally wrong with the code flashing process and/or the way the WebIDE is sending code to the PICO...

  • Well dang, I hang my head in shame for not checking the troubleshooting guide first.

    This answered my problem;
    http://www.espruino.com/Troubleshooting
    "If you want to execute certain commands at power-on, add one or more event handlers for the init event on E:"

    E.on('init', function() {
      // ...
    });
    

    "This will then be loaded every time Espruino starts up. If you create a function called onInit, that will be executed too:"

    function onInit() {
     // ...
    }
    

    So what is misleading is that if you click the "Send to Espruino" button in the WebIDE and DON'T have your startup code inside OnInit(), it runs fine, but if you DO then it doesn't run until you call save(). I'm sure there's an explanation to this somewhere.

  • Still doesn't explain why previous code I have sent to the PICO's without being inside OnInit were running okay at startup. Obviously I have to look more into how Espruino works.

  • Glad you got it sorted - ish :)

    When you type save() - it saves the current state of the interpreter to flash, which means if you have queued timeouts (like in your code) then those get executed.

    What I guess happens is you upload and the code actually starts running right then. You then type save() but it's actually halfway through running.

    So what you're left with is maybe only the last 2 timeouts, rather than all the timeouts as you'd expected?

    Also, would you have fiddled with the IDE and clicked Save On Send at some point in the past? This actually does what I think you're expecting - it saves your code as it was, and executes all your code on startup. It then runs onInit().

    However, if you then turn Save on Send off and upload, you're left with 2 copies of your code - what you uploaded previously and what you subsequently upload. You can run E.setBootCode() to get rid of that previous copy - but it's probably safer just to re-flash your Espruino to make sure everything is exactly as it should be.

    Also - just tried:

    function onInit(){
      setTimeout(function(){
        digitalWrite(LED1, 1);
        setTimeout(function(){
          digitalWrite(LED2, 1);
          setTimeout(function(){
            digitalWrite(LED1, 0);
            digitalWrite(LED2, 0);
          }, 1000);
        }, 1000);
      }, 1000);
    }
    

    here and it works great.

  • Cheers Gordon - good explanation, does make it clearer.

    Being a n00b is fun ;-)

  • Espruino Original/Pico/Puck lesson learned:

    LESSON 1

    DO NOT have directly or indirectly immediate_executed / upload_executed dynamic code in your application - especially timers - such as:

    // directly immediate_executed:
    // ... some code
    setTimeout(function(){ ...
      }, 100);
    // ... some more code
    

    or

    // directly immediate_executed:
    // ... some code
    function myFunction() {
      ...
    }
    setTimeout(myFunction, 100);
    // ... some more code
    

    or

    // indirectly immediate_executed:
    // ... some code
    function myFunction() {
      ...
    }
    function myOtherFunction() {
      setTimeout(function(){ ...
        }, 100);
      setTimeout(myFunction, 100);
    // ... some more code
    myOtherFunction();
    // ... and some more code...
    

    All of the above examples will get timers going already while uploading which most likely get you into troubles, especially when you

    • have save on upload enabled in IDE settings
    • have save() as last statement in your code - which y0u should not have anyway
    • type save() in the console after upload

    Best case is that the code works in development mode, but if you then save(), disconnect from IDE and just power it for running stand-alone, it most likely will not work as expected.

    Reason why you should NOT have immediate_executed / upload_executed dynamic code in your application is that execution of this code may interfere already with the upload (has been experienced), interfere with the save() as explained in this conversation, ...and in general because you cannot reliably control the sequence in which things happen.

    Remedy is - first - to put everything(XX) into functions, and - second - to call the functions as needed and in correct sequence in the onInit() { ... } function (or register them in correct sequence with E.on("init", myFunction);. This way it is guaranteed that invocation will happen on power cycle / power up initialization.

    DO THIS:

    // ... some code
    function myFunction() {
      ...
    }
    function myOtherFunction() {
      setTimeout(function(){ ...
        }, 100);
      setTimeout(myFunction, 100);
    // ... some more code
    function onInit() {
      myOtherFunction();
    }
    // ... and NO MORE code...
    

    (XX)everything is best practice and means also initializations, because some initializations are dynamic as well (as experienced with things such as require("module").connect(...); - because you cannot control what the particular .connect() actually does). Setting pin modes and settings of certain communication instances, such as Serial1, SPI1, I2C1, etc, you can have in directly or indirectly immediate_executed / upload_executed code - because @Gordon took care of saving state on save() and re-instating that state before (user) initializations (onInit() and E.on("init", ...)...@Gordon is such a nice and helpful guy to make live for us easy,... or lazy, but when you want to be lazy, you have to know how and what you do - lazy).

    Note that with above example nothing application-wise happens on or after upload when Web IDE save on upload is disabled. There is no need to enable it (and unnecessarily wear down you FLASH). Just enter onInit() in the Web IDE's console to get your code started 'exactly' as it happens on power cycle / power up. If you are - smart - lazy and do not forget to delete an extra line before save(), add - for development convenience - onInit(); as extra and last line to your code. But as said: remove it before you save your code (Personally, I prefer using onInit() over multiple E.on("init",...) because it enables the lazy development mode...).

    But for the sake of defensive, deterministic, and robust coding, it is best (practice) to put these things into functions too and invoke them the same - sequence controlled way - as the other functions with dynamic code.

    For background details, take a look at the two times 2 cents posts #8 and #18 of conversation about simple explanation how to save code that espruino run on start?.

  • @allObjects - wow thanks for taking the time to spell that out, really appreciate your insights here. After reading and experimenting more I was starting to "feel" the right way to do things was as you have just explained, so your explanations help cement this in confidence, cheers.

    Yeah I was beginning to see just how much @Gordon has done to abstract all the "messy" stuff away and make it easy for us to get our code on-chip and running, I agree this does come at the cost of allowing n00bs to do n00b things! Understanding how to do it properly however, removes the frustration entirely and brings back the fun, thanks guys, happy to understand some basics now and have my code working as expected.

    Good forum too - code blocks work well.

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

Something is wrong - PICO

Posted by Avatar for noofny @noofny

Actions