• I got a several 4x4 neopixel-compatible modules:

    and would like to string several of them horizontally to create a 16x4 matrix. Can the Graphics library work with this configuration?

    I know in the RGB123 example you can create an array buffer x*y but wondering if it will work with arbitrary rows and columns since in regard to the wirings of arbitrary modules.

    Thanks!

    *edit: I need to do 12X4 instead of 16X4

  • So I did a manual remapping from the Graphics.buffer to the way my modules are chained:

    /*
    Graphics.buffer (not zigzag):
    00 01 02 03 04 05 06 07 08 09 10 11
    12 13 14 15 16 17 18 19 20 21 22 23 
    24 25 26 27 28 29 30 31 32 33 34 35
    36 37 38 39 40 41 42 43 44 45 46 47
    
    My module chained, three 4x4 modules horizontally:
    
    00 01 02 03  16 17 18 19  32 33 34 35
    07 06 05 04  23 22 21 20  39 38 37 36
    08 09 10 11  24 25 26 27  40 41 42 43
    15 14 13 12  31 30 29 28  47 46 45 44
    
    */
    

    And use this code, with a util function to copy the triplets of RGB per index:

    //
    var neopixel = require("neopixel");
    
    var leds = Graphics.createArrayBuffer(12,4,24,{zigzag:false}); 
    
    
    
    var getTriplet = function(array,index){
     
     index*=3;
      var result =[array[index],array[index+1],array[index+2]];
      return result;
    };
    
    
    leds.flip = function() { 
      var rawBuffer = [];
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,0));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,1));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,2));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,3));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,15));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,14));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,13));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,12));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,24));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,25));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,26));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,27));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,39));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,38));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,37));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,36));
      //
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,4));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,5));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,6));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,7));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,19));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,18));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,17));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,16));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,28));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,29));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,30));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,31));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,43));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,42));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,41));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,40));
      //
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,8));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,9));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,10));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,11));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,23));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,22));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,21));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,20));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,32));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,33));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,34));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,35));
      
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,47));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,46));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,45));
      rawBuffer.push.apply(rawBuffer,getTriplet(leds.buffer,44));
     
      neopixel.write(B15, rawBuffer); 
    };
    

    The above does the trick, but all of the array operations slowed down the performance quite a bit... :(

    Anybody know any tips on the best way for this kinds of operation?

  • Well, there is a solution in Espruino to handle multiple NxN+NxN plates

    // connected to a 4x4 neopixel plate (x,y)=(0-3,0-3)
    //var leds = Graphics.createArrayBuffer(4,4,24); 
    
    // connect to four noepixel plates (x,y)=(0-4,0-15)
    var npp = Graphics.createArrayBuffer(4,16,24);
    
    // horizontal (x,y)= (0-15,0-4)
    npp.setRotation(1,false);
    
    
  • Thanks MaBe for the comment.

    I modified the H count:

    Graphics.createArrayBuffer(4,12,24);
    
    

    but doesn't work for my 3 plates horizontal with this led array sequence:

    00 01 02 03  16 17 18 19  32 33 34 35
    07 06 05 04  23 22 21 20  39 38 37 36
    08 09 10 11  24 25 26 27  40 41 42 43
    15 14 13 12  31 30 29 28  47 46 45 44
    
  • Check for option zigzag in createArrayBuffer()

  • I see - I think that could work, but I'd have to reassemble my module differently:

    00 01 02 03  16 17 18 19  32 33 34 35
    07 06 05 04  23 22 21 20  39 38 37 36
    08 09 10 11  24 25 26 27  40 41 42 43
    15 14 13 12  31 30 29 28  47 46 45 44
    
    //TO
    
    00 01 02 03  
    07 06 05 04  
    08 09 10 11  
    15 14 13 12  
    
    16 17 18 19
    23 22 21 20
    24 25 26 27
    31 30 29 28
    
    ...
    
    

    However, being rotated, I don't think doing

    leds.drawString("123")
    

    will draw expectedly something like

    /*
    \\\\\\\\\\\\\\\\\
    \\\ 123       \\\
    \\\\\\\\\\\\\\\\\
    */
    
    

    but instead will create a rotated version of

    /////////
    // 123 //
    //     //
    //     //
    //     //
    //     //
    //     //
    /////////
    

    Would work for fillRect or lines I think, but I need to draw text...

    Thanks again!

  • Yes, you'd have to reassemble your module, but the Graphics.setRotation command will let you rotate the graphics object so that you can draw in the orientation you want to.

    That'd definitely be the fastest/easiest.

    If you're totally set on remapping using your method, I'd suggest using the Graphics lib, but to remap the flat image to the 3 panels.

    var leds = Graphics.createArrayBuffer(12,4,24);
    
    
    // flip...
    var img = {width:12,height:4,bpp:24,buffer:leds.buffer};
    var ledbuffer = new Uint8Array(12*4*3);
    var dst = Graphics.createArrayBuffer(4,4,24,{zigzag:true});
    var panelSize = 4*4*3;
    dst.drawImage(img,0,0);
    ledbuffer.set(new Uint8Array(dst.buffer),0);
    dst.drawImage(img,-4,0);
    ledbuffer.set(new Uint8Array(dst.buffer),panelSize);
    dst.drawImage(img,-8,0);
    ledbuffer.set(new Uint8Array(dst.buffer),panelSize*2);
    neopixel.write(B15,ledbuffer);
    

    Not tested, but something like that should work fine.

    It's a bit fiddly, but would be way nicer/more efficient if you were working with much bigger panels.

  • That does it! Thanks @Gordon! You're the best :)!

  • like to share scrollString.js, a sample code to draw and scroll strings on a 3 x 8 by 8 panel

    attached is the wiring and a scrolling sample movie


    2 Attachments

  • @MaBe neat! So in that case you're doing like you suggested above - placing them at 90 degrees to @n00b and using setRotation.

    I'd say if someone didn't already have panels set up, that's the easier way to do it :)

  • Using a remap function and a panelList allows you even a combination of panels like this:

    each p is a 8x8 panel like above

    //--------------------------------------------------
    // p1           : [[0],[0]]         x 0-7,  y 0-7
    //--------------------------------------------------
    // p1 + p2      : [[0],[56]]        x 0-15, y 0-7
    //--------------------------------------------------
    // p1 + p2 + p3 : [[0],[56],[112]]] x 0-23, y 0-7 
    //--------------------------------------------------
    // p1 + p2      : [[0,64],[56,120]] x 0-15, y 0-15
    // p3 + p4
    

    test_remap.js

    @Gordon is it possible to inject a remap function into Graphic lib?


    2 Attachments

    • 4x4np8x8_back.jpg
    • 4x4np8x8_front.jpg
  • is it possible to inject a remap function into Graphic lib?

    Not really - the act of calling JS for every pixel write would really slow things down. For example you can't just remap the coordinates of a rectangle, because it could bridge two panels.

    It's better to do what I did in the example above and just use Graphics itself to remap to each separate panel. It'll be much faster too.

  • To be honest, I was thinking about adding it to GRAPHICS as option and call it like this:

    Graphics.createArrayBuffer(16,16,24, {panelMap:[[0,64],[56,120]]})
    
  • Why not just make a module to handle it, rather than building it into Espruino? It sounds like that kind of thing could easily be done with Graphics and drawImage as I'd mentioned above...

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

WS2812B (neopixel) and Graphics lib: custom matrix configuration

Posted by Avatar for n00b @n00b

Actions