digitalPulse and setTimeout doesn't work

Posted on
  • Hi,

    I'm trying to write a simple LED animation for a 7-segment display. It will light up a segment, then another one, then another one, until all are lit up, then dim a segment, then dim another one, etc. The code is (supposed to be) very simple. For reference, I'm using an MDBT42Q module with a 32khz crystal added on P0 and P1 with 22pf caps. I don't think it should affect my code.

    var segs = [A, B, C, D, E, F]; // array of LED segments, each a variable for a pin
    
    for (int i=0; i<6; i++) {
        digitalWrite(segs[i], 1); // light up the first segment in segs[]
        digitalPulse(D30, 0, 100); // pulse unused pin for 100ms, this is just a simple delay
    }
    for (int x=5; x>=0; x--) {
        digitalWrite(segs[i], 0);
        digitalPulse(D30, 0, 100);
    }
    

    and well, the code works as if the digitalPulse()es aren't even there. Everything happens very quickly so the LEDs just light up and off in a fraction of a second. I honestly have no idea why this isn't working as the other digitalPulses in the rest my code work just fine. I have other LED animations that use digitalPulse() in my code and those animations have no problem.

    So I tried using setTimeout(). I believe it's like so, but I might be wrong:

      for (var i = 0; i<6; i++) {
        setTimeout('digitalWrite(segs[i], 0)', 100);
      }
      for (var x = 5; x>=0; x--) {
        setTimeout('digitalWrite(segs[x], 1)', 100);
      }
    

    this one doesn't work either. So I tried another method:

    digitalWrite(A, 1);
    digitalPulse(D3, 0, 100);
    digitalWrite(B, 1);
    digitalPlulse(D3, 0, 100);
    digitalWrite(C, 1);
    digitalPulse(D3, 0, 100);
    .
    .
    .
    

    And same results.
    This has been driving me absolutely bonkers for the past few hours so any help would be greatly appreciated!

  • Ahh - pretty sure you're hitting:

    http://www.espruino.com/Reference#l__glo­bal_digitalPulse

    ... It uses a hardware timer to produce accurate pulses, and returns immediately (before the pulse has finished). Use digitalPulse(A0,1,0) to wait until a previous pulse has finished.

    So it's doing the pulses, but it's queueing them up to happen at pretty much the same time, in the background. If you did:

    for (int i=0; i<6; i++) {
        digitalWrite(segs[i], 1); // light up the first segment in segs[]
        digitalPulse(D30, 0, 100); // pulse unused pin for 100ms, this is just a simple delay
        digitalPulse(D30, 0, 0);  <--- wait for the pulse to finish
    }
    

    It'd likely do what you're expecting, but it's far from ideal. What you were attempting with the timeout would have been best, but there were just somes issue with your code:

      for (var i = 0; i<6; i++) {
        setTimeout('digitalWrite(segs[i], 0)', 100);
      }
      for (var x = 5; x>=0; x--) {
        setTimeout('digitalWrite(segs[x], 1)', 100);
      }
    
    • It's queuing all 12 timeouts up to happen at the same time - 100ms from the time the code runs
    • When the timeout runs, it executes the string 'digitalWrite(segs[i], 0)' - but 'i' is just set to 6, because the FOR loop has already run.

    Instead something like this should work fine:

      for (var i = 0; i<6; i++) {
        setTimeout('digitalWrite(segs['+i+'], 0)', i*100);
      }
      for (var x = 5; x>=0; x--) {
        setTimeout('digitalWrite(segs['+x+'], 1)', 1200 - x*100);
      }
    

    Normally I wouldn't recommend setTimeout with a string (I'd usually pass in a function) but here it works quite well.

    Another slightly more efficient solution would be to just have a single function that runs over and over:

    var i=0;
    var myInterval = setInterval(function() {
      if (i<6) digitalWrite(segs[i], 0);
      else digitalWrite(segs[11-i], 1);
      i++;
      if (i>=12) i=0; // or you could clearInterval(myInterval); to stop it
    }, 100);
    
  • @Gordon Oh my goodness thank you so much! It works like a charm :)
    One question tho, what does "+" do before and after a variable? Since you wrote '+i+' and '+x+' when referencing to elements in the array segs[]. I've never seen that before in any language.

  • You're just executing a string of code, so you're just adding strings together to make one big bit of text (which happens to also be a JavaScript command) - it's like you'd have if you were working with Strings in any language:

    i=0;
    print('digitalWrite(segs[i], 0)') prints digitalWrite(segs[i], 0)
    print('digitalWrite(segs['+i+'], 0)') prints digitalWrite(segs[0], 0)
    
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

digitalPulse and setTimeout doesn't work

Posted by Avatar for BootySnorkeler @BootySnorkeler

Actions