Addressable Icicles (tutorial)

In this tutorial, I’ll be making addressable icicles using KnowShine data return lights mounted to custom PCBs. I designed the PCBs to either plug in RJ9 modular (phone) connectors or to solder the wires directly to the board. Simply crimping RJ9 connectors to the wires is faster and easier. But because I’m designing these to be out in the wind, rain and snow, I am going to solder the wires directly to the board.

I built my icicles with 5cm horizontal spacing. If you have a large roof line to cover, you might want to go with 10 or 15cm spacing between strands. To do alternate spacing, just solder a short wire between the data and data return pins on the drops you want to skip. NotEnoughLights used this method to cover 30m of roof-line at 5cm spacing. Yes, that is 600 strands! Check out his video.

You could make all of your strands equal length like NotEnoughLights did. But I’m going to vary strand lengths from 8 to 13 pixels to make it look more like icicles. Because the lights will all be going in the same direction and not serpentine, you can find many 1D effects that will look great on your icicles. But because we’re WLED enthusiasts, we will configure this to take advantage of the fantastic 2D features of WLED. The jagged bottom edge will add a few more steps to do this. I’ll show you how to do this with both gap files and led maps (you would only need to do one method). Let’s start building!

I mounted the lights to a 3/4" x 1.5" frame to make it easier to install and to help protect from the weather. I soldered 90deg pin headers to both ends of the PCBs. Be sure to solder them on the bottom sides of the boards (the side with the footprints of the RJ9 connectors) so your PCBs will be flush on the frame.

Now it is time to start attaching strands. You are going to want a repeating pattern when you get to the mapping/gapping part. My pattern repeats every 10 strands. I chose 10 because the PCBs have 5 drops each so I end up with just two different style sections to keep track of. Keep the start-end of your pattern within a pixel or two of each other. The pattern I used was 13, 12, 11, 9, 8, 9, 10, 11, 12, 13. You might want to do a pattern with more 2 pixel steps to make it look more random.

Strip and solder the tops of the strand to the PCB. Trim any excess wire sticking out of the top. Be careful not to bridge contacts when soldering. On the bottom of the strand, strip the data and data return lines, solder them together, then cover with a heat shrink tube. Then I hot-glued brass beads to the bottoms for weight to help keep the strands hanging straight.

I soldered a 3-pin header to a male JST connector so I could plug in and test each individual section before final assembly. Once everything was tested, I mounted the sections to the frame using M2.5 screws. The PCBs have copper fills top and bottom and will carry quite a bit of current. But the connectors between sections are only going to carry 3A. So plan on doing a power injection at least every 600 lights. Use silicone or liquid electrical tape to protect any exposed contacts.

WLED Configuration
There are two ways to deal with the missing pixels in our matrix, ledmaps or gap files. Ledmaps are extremely powerful and allow us to map very complex shapes and structures. But because we are simply dealing with missing pixels, there is an even easier way to handle it, using a gap file.

Gap File
A gap file is a JSON formatted array that has either a 1 (pixel present), 0 (pixel present but don’t light), or -1 (pixel not present) for every position in our matrix with the first position being the top left pixel and the last position being the bottom right pixel, regardless of the physical layout of your lights. An easy way to create the file is to use Excel to generate a CSV file. I started by adding column and row headers that will need to be deleted before the file is saved to CSV. Then for columns 1-10, I populated a 1 everywhere there was a pixel and -1 everywhere a pixel was missing. After columns 1-10 are filled, copy those cells and paste for the remainder of your matrix. You want each line to end with a comma in the CSV, so enter a space in the first cell after your matrix. Save your file as a CSV. It is important that the JSON file is ANSI encoded and not UTF-8 encoded. Open your CSV in a text editor like Notepad++. Add an opening square bracket “[” at the start of the file, and a “]” at the end of the file. If you missed the step about entering a space after your last column above, add an ending comma at the end of each line. Save the file with a .json extension.

In the WLED LED Preferences page, set the number of pixels to at least the number you would have if you had no missing pixels, not the actual number of pixels. In the 2D Configuration page, set the dimensions w = the number of strands and h = the max length of your strands, orientation to vertical, and serpentine is unchecked. If you are using the standard (AirCookie) version of WLED, upload your gap using the control at the bottom of the 2D Configuration page. If you are using the MoonModules fork, the gap file will still work, but you will need to upload it using the /edit page, saving it as 2d-gaps.json.

Ledmap Option
Ledmaps have been around for much longer than gap files, and more people are familiar with it. As I said, I think it is overkill in this situation. But I’ll show you how to do it. In Excel, populate the cells corresponding to missing pixels in columns 1 through 10 (or however many your pattern repeat is) with -1. Then copy and paste columns 1 through 10 to the rest of the columns in your matrix. Then starting at “0” for your first pixel, hold CTRL as you drag the handle on the bottom right corner of the first cell to the bottom of your matrix or to the -1. This will increment the numbers, 0-12 in my example. Then continue that sequence at the top of the next column and CTRL drag to increment the remainder of that column. Be careful when doing this. If you make a mistake, you will have to redo the rest of the grid from that point forward to fix it. Once all of the cells corresponding to your matrix are populated with either a -1 or the pixel number, add a space character to the first cell in the column after that. Save as a CSV and open the CSV in a text editor.

Open a new text document, call it something like “icicles_ledmap.json”, enter the following JSON attributes, then copy and paste the values from your CSV file.

"n": "icicles",
"width": 35,
"height": 13,
"physical": true,
   ... paste values from CSV here ...

Be sure all of your map rows end with a comma. Save your file and upload using the /edit page. Change the file name to “ledmap.json” before you click the “Upload” button.

Once your gap or ledmap has been uploaded, reboot WLED. Go to segments and be sure it matches the dimensions of your matrix. You’ll need an effect that moves horizontally, like Scrolling Text, to verify that your mapping is correct. If the text is legible and moving straight horizontally, you’re good. If it doesn’t work, check that your json file is properly formatted and ANSI encoded. An IDE and some editors like Notepad++ can help identify JSON formatting errors. The JSON library that WLED uses is picky.

Note on PCBs
I used rigid PCBs in this build. It is surprisingly quick and inexpensive to get them from JLCPCB. It cost me about $1-2 per meter depending on quantity. But I really wanted to do this using flex PCBs. They build LED strips by making 50cm long flex PCBs and soldering them end to end. The problem with flex PCB is that it is significantly more expensive than rigid in the quantities that a hobbyist would be ordering ($3 - 8 per meter). I was talking to the owner of KnowShine about this and he said they could get us much better prices by ordering large quantities. And they manufacture LED strips in their factory so they are set up to convert the 50cm flex PCBs into 5M strips. I’m very excited about this, as it would make it even easier to make long stretches of icicles. I will give an update once I know for sure. If they don’t make them, I’ll provide the gerber file so you can order them.


Nice work. Now add a lil hot glue to waterproof the solder connections :wink:

Here is another idea. You could put the pcb strip in this and I wowuld think it would shield the rain enough to keep things dry.

Perfect solution!
Could you show “gap file” is a JSON formatted? ledmap.json works for me, but doesn’t work with “gap file”. I’m making a mistake somewhere. It doesn’t load at all.

I like the liquid electrical tape because it dries much faster than silicone (and I’m impatient).

It would fit in 1/2" trim. But with 1" trim, you could fit the strip and still have enough room to clip and screw it to the fascia board from inside the channel.

Here’s my gap file with places where you’re likely to make a mistake:

  • a comma at the end of each row
  • no trailing comma on the last row
  • file ANSI encoded

If you upload using the control built into AC 2D Configuration page, it automatically renames the file “2d-gaps.json” but if you manually upload it using the /edit page, you must rename it yourself.

1 Like

Thanks for the tip. It turns out that the file contains only what is in square brackets? I added “{” “}”.

Correct, just the array in the square brackets.

Is it correct to bracket like this?

No. That is not valid JSON. When you have curly brackets, you’re saying you have a dictionary and it would expect attribute names and values. Lose the curly brackets and it will work.

Thanks for the tip.

Does anybody know of a supplier in the UK?
We seem to lag behind when it comes to decorating our houses with festive lights


Supplier of what? If you’re talking about seed pixels with built in data return, then as far as I know, there are only three suppliers. They are all based in China. NotEnoughLights and I collaborated with KnowShine to bring these to market. A few months later Ray Wu and another supplier were also offering lightly different versions.

Artacus, I managed to set up my matrix. I made a gap-file. Before your post above, I could not find a clear explanation anywhere on how to make a gap-file correctly. Thank you very much for this.

Tell me, what kind of 4-pin connector do you use on your PCB? I searched on Aliexpress but couldn’t find it.

I’ll be looking forward to your link to the gerber-file of your PCB!

Glad you got your gap file working.

The 4-pin connectors are just standard 2.54 pitch 90deg male and female headers. Male headers come in lengths of 40 that you break into the size you want. Female headers you can get here.

I’d hold off on getting them though. That PCB was designed for curtains where you typically need 2 data pins. The 4th pin is to carry data to the second half of your curtain. But with icicles, you might need 8 data pins. So I went with just a standard 3 pin configuration. And if we can get a flex tape, the whole strip would be continuous and you’d just put a 3 pin JST-SM or waterproof connector on the end.

I just need a connector for such a curtain. It is a pity that the connector does not have a “key” to prevent incorrect connection.

I don’t understand why you write about “8” pins?

How many data pins do you think NotEnoughLights used in his 30M 600 drop display? Probably 10 or more. I’m saying that since a large icicle display could require any number of data lines. I’m not going to try to accommodate that on the PCB, you’ll have to run separate wires.

It’s clear! I haven’t seen this 600 dot display.

Cool info , While i still do not have Icicles yet just a small correction related to the gap file when you listed " with the first position being the top left pixel and the last position being the bottom right pixel, regardless of the physical layout of your lights " When i tested the physical layout does matter when using gap file which i am sure was the intended behavior ( does not matter with ledmaps) .
I have tested that as you see below and if the 2D page setup was altered then the effects did not work . I am testing on a new build so might be something to consider physical


For those asking where you can get the PCBs, I posted the Gerber files in the Modular Matrix thread.

1 Like