Addressable RGB LED Art Project

Posted on
  • Hey guys,

    basically im a young electronics engineer who has a passion for arty farty things and this is a project ive been brewing for sometime.

    Overview:
    The actual end product is probaby best described as this; Its an A3 sized sheet of clear/slightly misted plastic that has a grid of RGB LED's laid behind it, which are controlled by the Espruino.

    I then produce black and white artwork onto sheets of clear acetate (causing it be black and clear artwork). This artwork is then overlaid/pinned to the item described previously. What this hopes to achieve is that it provides me with a piece of black and white artwork (sorta comic style) in which I am able to control the flow of colour within the 'white or clear' areas.

    Think like what doctors pin their x-rays to, except it looks like your bones are taking a funky acid trip :)

    Problem:
    Currently not having any issues with the physical build, but I am having issues with the coding and general understanding of the control of the LEDs. I have little coding experience, i get what a unit array is and a for loop, and the need to define, then call a function etc.. but nothing beyond very basic work.

    I was hoping someone could help me dissect the code from the RGB LED tutorial on here (this is the tutorial:http://www.espruino.com/Individually+Add­ressable+LEDs)


    var rgb = new Uint8Array(25*3);
    
    function getPattern() {
      for (var i=0;i<rgb.length;i+=3) {
         rgb[i  ] = i*10; 
         rgb[i+1] = i*10;
         rgb[i+2] = i*10;
      }
    }
    

    So;
    for (var i=0;i<rgb.length;i+=3)
    That is the three conditions within the for loop correct? first being; var i is set to 0, the loop ends when i =25? - as thats how many rows are in my array (ie LEDs), and on each loop 3 is added to the var i?

    rgb[i ] = i*10;
    rgb[i+1] = i*10;
    rgb[i+2] = i*10;

    What is this doing? I assume its setting a value of 10 to the first RGB LED, so [10,10,10]? then the next LED would be set to [20,20,20] once the loop is completed?

    Basically, id like help understanding how I am controlling the lights with relation to this Unit8Array

  • Yes, your intuition is good. The first three bytes control respectively Red, Green and Blue for the first led, the second three do the same for the second, and so on.
    I'm also developing some stuff by controlling leds, something that could be best defined as a software defined lamp; Depending on what you actually want to achieve, you could be better off using the graphics library (useful if you need to draw a line or something like that);
    I suggest you attempt to do something on the espruino command prompt, I love it because it allows for very rapid prototyping and gets you going quick.
    I include the file I'm working on; Probably not all of this is working, and some comments are in italian, but you could draw some inspiration as I use a few different ways of accessing the led array.
    Bye
    Luca


    1 Attachment

  • A software lamp?
    Surprisingly I am also currently designing a RGB LED lamp (like an actual physical lamp - if a software lamp is not physical?); although only intending to use about 5 LED's in the strip.

    I don't know what the graphical library is but I will look into it :) and command prompt is not a bad idea, although I have found the web IDE pretty decent. I just had it all plugged up at once and just reset() when i want to try something else.

    I went and spoke to a coder in my department and tbh that was a good way of gwtting more info about the uint8array and i think I get it now :)

    I also had a look at your code, so now im assuming a software lamp is literally drawing on a computer screen (based off your use of x,y co-ordinates it must be some sort of display).

  • I am currently now trying to do a little mini project to get my brain into the right gear before I work on my overall project.

    so a Knightrider loop (classic and imaginative i know);

    What im thinking, is instead of a Uint8Array I could use simply a variable. So for say 5 LED's;
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,]
    Then within the loop i'd need;

    • something that increments by 3 each time (so I can move from Red LED to Red LED each time)
    • Then using the above which goes 0,3,6,9,12 I can tell it to modify the position within my 5 LED variable.
    • I'd then also need something to reset the previous so? modify i-3 to 0.
    • SPI2.send4bit.....
    • Delay

    So what im doing is creating a blanket 5 LED strip of 'off' LED's in a variable, then each time the loop goes round using the 0,3,6,9,12 I can modify the value of the Red LED within that variable and resend the entire thing.

    im sure that's rather inelegant but I can come up with more creative ways later ;)

  • Well yes it's an actual lamp, but with code that decides the color of every pixel. So it's actually a very low res display, but with big, luminous pixels. The base model will be 5x5. The idea is to allow people to load software on it using bluetooth, so with a phone app some sorts.
    Bye

  • Not sure if this helps, but the array rgb is 75 elements - 25 LEDs, each of which need R, G and B... So it's like R0,G0,B0,R1,G1,B1,R2,B2,G2,etc

    When you do for (var i=0;i<rgb.length;i+=3) you're saying:

    • Start i off at 0
    • Stop the loop when i is bigger than 75
    • Each time around the loop, make i 3 bigger (R, G and B)

    As you're controlling a grid of LEDs you might want to do something like this (assuming you have 5 LEDs down by 6 LEDs across):

    var rgb = new Uint8Array(5*6*3);
    
    function getPattern() {
      var x,y,i = 0;
      for (y=0;y<5;y++) {
        for (x=0;x<6;x++) {
         rgb[i++] = x*10;  
         rgb[i++] = y*10;
         rgb[i++] = 0;
      }
    }
    

    That's a bit different, but the principle is the same. What happens is it loops over all the LEDs, but assumes they're in a grid, so you get X and Y coordinates. There's no +3 because we now call i++ (which adds 1 to i) 3 times each iteration.

    @Loop's suggestion of using the graphics library is good though. There's another simple example for the RGB123 module, which is a pre-made grid of LEDs.

    The two methods (Array vs Graphics Lib) are good at different things. Basically:

    Array: Useful where you want to change the state of all LEDs at once - and specifically if you want to make the value of lights dependent on some mathematical function (like maybe a sine wave).

    Graphics Lib: Where you want to draw bitmaps, rectangles, lines, and text. You can still access pixels individually, but it's not as fast.

  • @Robet, the Knightrider thing sounds like a good place to start...

    Personally, I'd keep using Uint8Array - It uses less memory and it's faster, but otherwise it's just like a normal array.

    And instead of a delay, you'll want to use setInterval to call your code maybe 5 times a second (200ms)...

    Let us know if you need any pointers... The only thing to note is depending on your LEDs (WS2811 or WS2812) red, green and blue are in different order - but if it's not right it's easy enough to experiment :)

  • Thanks Gordon :)

    I like the idea of the grid Uint8Array, that indeed will be very handy, over the weekend me and a buddy managed to get our heads around it, I hadn't known the ws2811 is a different order to the ws2812, thanks for the tip :) luckily our experiments were more just about the control and not entirely worried about colour at that point.

    I think the Uint8Array is something good to stick to, i'll try the graphics lib, but I will mostly be looking to use mathematical functions. Thank you for the tip.

    Created some fancy knightrider effects after we got the standard version going. Have now ordered a nice amount of surface mount LED's, so hopefully should have the grid to play test in a week or so :)

    Thanks for the input guys and i'll keep the progress updated.

  • Hey guys,

    The project has made some real progress today, my SMD LED's arrived (although soldering 8 in series was a little horrible, dont think il be making them the same way after this prototype :P ).

    I currently have 8 in a chain, so thats the first line of my grid, for the Uint8Array that is in the format (8,5,3) do I simply need to continue the chain? as in will the first LED of the second row be chained from the end of the first row?

    Dont want to chain them and find out it wants a different setup :P I'm assuming it will be fine, but rather not make the mistake :D

    Also; Gordon,
    little confused as to what is occuring within the FOR loops/brackets in what you linked me. Its still simply increasing the values of X and Y? in order to move to the next LED.

  • Gordon's example is for a 5x6 array (30 LEDs) so he makes a uint8array 90 bytes long (30 LEDs 3 bytes per LED). The outer loop loops over each of the 5 rows, and the inner loop goes over each LED within those rows, setting the three colors in it. X and Y are the coordinates of the LED it's addressing.

    If you only have 8 in a single row, you'd create a 24 byte long uint8array (3 bytes per LED), and you'd want to adjust the two loops appropriately (ie, change the tests to y<1 and x <8 )

  • What @DrAzzy said,

    will the first LED of the second row be chained from the end of the first row?

    Yes, that's what the code above assumes you'll be doing. If you do something else you'll need to change the code.

    Just to add that it'd be a good idea to chain the signal but to connect the power and ground together all down the edges of the lights - otherwise you might find that when they're all on the power draw is so high that the ones right at the end will be more dim than those at the start.

  • Hey guys,

    i've been having a little tinker and play with some code, but im not sure im thinking in the right dimensions.

    The intended use of the LED grid will involve individual LEDs doing various patterns dependant on the artwork that is overlaid on to the board, so I think I need to be attempting to control the LEDs in a much more individual fashion rather than by row or by column.

    Is it possible to access the array in a more coordinate based style? such as being able to do something like;

    (2,2)
    rgb [i] = 255;
    rgb [i++] = 255;
    rgb [i++] = 255;

    So this in a grid of say 4x4, would select the LED thats the third across and third down (assuming that 0,0 would be top corner?) and set it to white.

    I also have a question, having looked at the code ive currently been working with, it seems that say I wanted to update 1 LED from green to blue, I am not simply selecting that 1 LED, sending it data and then it changes. But what happens is; I update the array by adjusting 3 values within the entire array so for a 4x4 this would be adjusting 3 values in a 48 byte array, I then send out the entire array and every LED is adjusted to the new values (except that in this case only 3 have changed- so only 1 LED changes).

    Im thinking that this is due to the way the LED chain operates right? And therefore not something I can change, unless I individually connect each LED to its own data pin? Will this affect the speed of the data being written if say I am adjusting the first and last LED in a 50 LED chain at the same time? would the first change noticably quicker?

    I apologise if these seem like really basic questions, I tend to learn by doing and find that books often dont really help with such individual projects; although i have a java book in the post as we speak :) combined with some internet tutorials.

  • Yep, you're right - you can only send data to all the LEDs in a chain, not just one. The data gets sent pretty quickly though, so you won't notice any difference in when the lights come on or go off.

    It's about 20,000 LEDs/sec - so if you were updating 50 LEDs they would update in 1/400 sec, which you'd never notice.

    The code before will let you change every LED individually (not just row or column), but in a similar way to the lights, you'd have to figure out what colour every LED should be at the same time.

    If you actually just want to change individual colours, you could re-write the code as:

    var rgb = new Uint8Array(5*6*3);
    function setPixel(x,y,r,g,b) {
      var i = (x+y*6)*3;
       rgb[i++] = r;  
       rgb[i++] = g;
       rgb[i] = b;
      SPI2.send4bit(rgb, 0b0001, 0b0011); // update the display
    }
    // ...
    setPixel(2,2, 255,255,255); /* the colour */
    

    OR, you could do what @Loop suggested earlier, and use the Graphics class, which already provides functions like setPixel and clear:

    var g = Graphics.createArrayBuffer(6,5,24);
    g.setColor(255,255,255);
    g.setPixel(2,2);
    SPI2.send4bit(g.buffer, 0b0001, 0b0011); // update the display
    
  • Haha! yeh I had a feeling the data would be too quick to notice. Which is a good thing :)
    The graphics class i will definitely look into then.

    Thank you for the tips guys and Gordon :) I really appreciate it.
    I have built a prototype out of cardboard (its a total bodge but I simply needed a working version), I will post pictures once the first non-cardboard prototype is done!

  • I will post pictures once the first non-cardboard prototype is done!

    Thanks! I'd love to see what it's like :)

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

Addressable RGB LED Art Project

Posted by Avatar for Robet @Robet

Actions