Newbie question regarding loops

Posted on
  • Hi,

    I apologise in advance for this simple question.

    I have just taken delivery of two strings of 50 WS2811 led's.

    I can get all the sample code working and I have managed to extend the patterns of blinking but now I would like to try stepping patterns, ie light the first two led's and then step forwards lighting one led at a time and turning off the first led so that only two leds are lit at any one time.

    Here is the code that I am playing with -

    SPI2.setup({baud:3200000, mosi:B15});
    
    var rgb = new Uint8ClampedArray(50*3);
    
    
    function step(pos) {
      if (pos > 0) {
      rgb[pos-1] = 0;
      }
      rgb[pos ] = 0; 
      rgb[pos+1] = 0;
      rgb[pos+2] = 255;
      rgb[pos+3] = 0; 
      rgb[pos+4] = 0;
      rgb[pos+5] = 255;
    }
    
    function doStep() {
      for (var i=0;i<rgb.length-3;i+=3) {
        step(i);
        setTimeout(SPI2.send4bit(rgb, 0b0001, 0b0011), 5000);
      }
    }
    

    I know its ugly but I am just playing at the moment.

    When I execute this the first two leds light and I get the following error -

    Uncaught Error: Function or String not supplied:
     at line 4 col 56
    

    Any pointers would be gratefully appreciated.

  • First argument to setTimeout has to be a function or a string.

    function:
    setTimeout(function {SPI2.send4bit(rgb, 0b0001, 0b0011);}, 5000);
    or string:
    setTimeout("SPI2.send4bit(rgb, 0b0001, 0b0011);", 5000);
    or a function defined elsewhere
    function flip(){SPI2.send4bit(rgb, 0b0001, 0b0011);}
    setTimeout(flip, 5000);

    There's another problem there though.... you'll stack up 50 timeouts, which will then all run at once in 5 seconds. That setTimeout() should be outside the loop.

  • @DrAzzy
    I understand the parameters of setTimeout now, but if I place it outside of the loop surely I will only ever light the last two lights ?

    The timeout is needed to delay the step otherwise the pattern will complete in a flash, if you will forgive the pun !

    Thanks

  • Aaah so you want it to happen after each call to step. (I also misread a bit what your code was doing there)

    That won't work, because setTimeout() doesn't block. It stores the function and remembers to execute it in 5 seconds, and then the rest of the code continues executing (ie, it acts like setTimeout does in normal javascript). So you'd end up with the loop running almost instantly, and then all timeouts fire off in rapid succession 5 seconds later.

    You want to use setInterval() instead, and put both functions into the interval (while storing the current animation index in a global variable or object property).

  • @DrAzzy
    That's sorted it !!

    Thanks for pointing me in the right direction.

  • No problemo

  • Okay maybe not the most exciting pattern but here is what I ended up with -

    SPI2.setup({baud:3200000, mosi:B15});  // setup SPI port
    
    var pos = 0;        // select start point
    var direction = 1;  // set direction of travel, 1 forwards and -1 backwards
    var width = 4;      // set width of pattern
    var length = 50;    // set length of led string
    
    var rgb = new Uint8ClampedArray(length*3);  // setup array for leds
    
    function step() {
      if (pos > width && direction == 1 ) {        // if we have lit the pattern width and are travelling forwards
        rgb[(pos-(width*3))] = 0;                    // then blank the first led in the pattern
        rgb[(pos-(width*3)+1)] = 0;
        rgb[(pos-(width*3)+2)] = 0;
      }
      if (pos < rgb.length && direction == -1 ) {  // if we haven't reached the end of the string and travelling backwards
        rgb[(pos+(width*3))] = 0;                    // then blank the last led in the pattern
        rgb[(pos+(width*3)+1)] = 0;
        rgb[(pos+(width*3)+2)] = 0;
      }
      rgb[pos ] = 255;                             // set the next led in the pattern to red
      rgb[pos+1] = 0;
      rgb[pos+2] = 0;
    }
    
    function doStep() {
      step();                                      // set next step in the pattern
      pos+=(3*direction);                          // step to the next position
      if (pos >= rgb.length) {                     // if we have gone passed the last led
        direction = -1;                              // reverse the direction
      }
      if (pos < 0) {                               // if we have gone passed the first led
        direction = 1;                               // reverse the direction
      }
    }
    
    function send() {
      SPI2.send4bit(rgb, 0b0001, 0b0011);          // send the data to the led string
    }
    
    setInterval(function() {
      doStep();
      send();
     }, 18);
    
    
  • @ukflyer And now stick it on the bumper;-)

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

Newbie question regarding loops

Posted by Avatar for ukflyer @ukflyer

Actions