How-to: Make a TV or PC monitor Ambilight

Have you ever wanted your TV or monitor to have lights behind them reflecting what is on the screen, like those fancy expensive Philips TVs? Apparently they are called Ambilights 🙂

Lighting up the wall behind the screen is a brilliant way to add more ambience and makes the watching movies/TV so much more immersive.

Ambilight TV

You can actually do it quite easily and cheaply with an Arduino and some LEDs from ebay. In total my lightning for my 24″ monitor cost around £10!

To be clear: this only works for monitors or TVs which are connected to a computer as a computer has to scan the image being displayed and tell the Arduino what to display.

There are ways to setup ‘Ambilight-ing’ for ANY screen being driven by an HDMI connection, this makes use of a Raspberry Pi to do the processing and tell the LEDs what to display. I may write a guide for this in future if there is demand???
But if you want to try it for yourself now, here are some links to some great guides already written…

I’ve gone ‘cordless’ so my living room TV is simply a large monitor for a small computer tucked under it, so this works great.

The LEDs

We are using WS2811 LEDs for this project. They only have three cables going through the string of LEDs, two for power, and one for data. WS2812s should also work fine. When I was planning this project I thought I was buying WS2801 LEDs as I’d only seen these used in the guides online, then the WS2811s showed up and I had to work out how to use them. I would actually recommend the WS2811s now since they have fewer wires which makes it marginally simpler, and they are much cheaper – I found the WS2811s for about £2.20 per meter compared to over £5 per meter for the WS2801s.

WS2801 vs WS2811

If you do have WS2801s they can be used for this project but they have two data lines so the wiring and code will need tweaked a little to use those but I’m not going to cover that here. You can find a guide for that option at https://learn.adafruit.com/adalight-diy-ambient-tv-lighting/

 

The Hardware

  • Arduino  – any kind will do but I’m using a Nano since it is tiny, and I
    got a cheap one from ebay. Since the Arduino schematic is open source you
    can get cheap ‘unofficial’ versions of them which work just as well as the real thing. I got mine here, I ordered a pack of 5 so that I had a couple for the TV and monitor Ambilight and some extra for other projects (like a 4x4x4 RGB LED cube!).Arduino Nano

    Since they are not ‘real’ Arduinos you’ll need to install some extra drivers to make sure they are recognised properly on your system. The links to the drivers are detailed in the ebay listing but I’ve noted the links here for convenience in case you go for the same ones as I did: Win7 driversWin10 drivers, Linux drivers
  • LEDs – WS2811s. I got a few 1m strips from here. I found they were cheaper than strings of LEDs and they stick more easily on the back of the TV, instead of hot gluing every light on individually the strips tend to have a sticky backing to stick to the back of your screen. Just measure the circumference of your screen to work out how many strips you’ll need. The strips you buy can be trimmed to size. But some strips can only be cut in between every three LEDs while some can be cut between each LED, then reconnected with flexible wire to go round the corners. WS2811sYou’ll want a set that has 30 LEDs per meter, and of size 5050 (means it’s 50mm x 50mm across each LED) you can also get 3528s which are a bit smaller and give out a bit less light.
    You can use either 12v or 5v LEDs, doesn’t make much difference but make sure you get a power supply (below) which outputs the correct voltage. Also make sure you don’t get ones which are only addressable in sets of three LEDs like I did with my first set i.e. you send a command to turn the first LED red and lights 1-3 go red, you send a command to turn the second LED blue and lights 4-6 go blue. You want INDIVIDUALLY addressable LEDs. It’s actually quite hard to tell from looking at pictures whether a string of LEDs is individually addressable or addressable only in sets of three. All strips addressable in threes only have one controller chip (the black microchip about the same size as the LEDs) per three LEDs, but some of the individually addressable LEDs also only have one chip per three LEDS and some individually addressable LEDs have a chip per LED. So look for an ebay listing which explicitly states that they are individually addressable.
  • Barrel Connectors – the Arduino can’t provide enough Barrel connectorscurrent for the string of LEDs so we need to power them externally. I got mine from here.
  • DC Power Supply with a 5.5mm barrel connector to match the voltage of your LEDs. The output current will also need to be sufficient. We’ll cover that below. This seller has a selection of DC supplies.5v DC power supply Note: Almost all of the connectors and power supplies come with the barrel center being positive and the outside being negative (to avoid accidentally electrocuting yourself when you pick it up) but it is something to be aware of when ordering, just make sure you get a barrel connector which matches the polarity of your power supply. To be honest I didn’t notice whether mine even said which polarity it was on the ebay listing for either the barrel connector or power supply and I completely forgot that it was a possibility to get them the other way round until after the project was finished!
  • You’re also going to need a soldering iron and solder for this project. And a glue gun will come in handy but isn’t strictly necessary as you can use some electrical tape instead if you don’t have a glue gun. Also some heat shrink tubing for covering where some wires will be soldered together, again electrical tape can also be used.

 

The LED current draw

Each RGB LED* is actually 3 individual LEDs (one green, one red, one blue), each individual LED draws about 20mA when fully lit. That means each RGB LED has a draw of 60mA when fully lit.

RGB LEDSo to work out how much current your full Ambilight will draw, and hence what specification of power supply you’ll need, simply multiply 60mA by the number of LEDs you expect to have mounted around your TV or monitor. Each to work out since each meter of strip has 30 LEDs on it. So my monitor has a circumference of 1.8m, so I’ll be using 30 x 1.6=48 LEDs = 2.8 A

So if I use a 3A supply that will provide sufficient current. It’s good to note that your LEDs will only draw the current they need, so it’s safe if your power supply can provide more current, just as long as it isn’t too low.

Some useful power draw numbers*:

  • 50 light string = 3A
  • 30 light string = 1.8A
  • 25 light string = 1.5A

* These numbers are for 5050 (50mm x 50mm) LEDs, other sizes will vary on how much power they suck up. You should look up the datasheet online to find out the current draw.

 

The Software

We’ll be using the Arduino software to load code onto the Arduino Nano which will drive the LEDs. Then we’ll run some java code in Processing to take measurements of the area around the edge of the screen and output this to the Arduino over the USB port.

Download the Arduino software from here: https://www.arduino.cc/en/Main/Software

Let’s load some libraries into the Arduino software which we’ll need later. Both of these libraries can be used for addressable LEDs with only one data line, like the WS2811s. The same libraries will be needed if you’re using WS2801s too, you can find a guide for setting these up at https://learn.adafruit.com/adalight-diy-ambient-tv-lighting/

  1. Get the FastLED library from here: https://github.com/FastLED/FastLED
    Download the project as a zip file, rename the file to FastLED.zip, then import to Arduino through ‘Sketch’->’Include Library’.
  2. Get the Adafruit Neopixel library from here: https://github.com/adafruit/Adafruit_NeoPixel
    Download the project as a zip file, rename to Adafruit_NeoPixel.zip, then import to Arduino through ‘Sketch’->’Include Library’

 

Now, also go and download Processing 2.2.1 from here: https://processing.org/download/?processing

Make sure you have downloaded v2.2.1 (toward the bottom of the page) and not a more recent version or the code will not work. More recent version have changed the way Processing handles the size() function and it will no longer accept varibales as options, only constants, this will break our code.

The Circuit

Before we start, note that these strips have a specific direction in which the power and signal must flow, indicated by arrows. Make sure you connect everything in the correct direction.

If you haven’t already, you’ll need to work out exactly how many LEDs you’re going to need for your TV/monitor. Simply measure the circumference of the TV about an inch in from the edges and then work out how long an LED strip you’ll need.

You’ll need take some care when thinking about how you’re going to position the LEDs. We’ll be cutting to size Copper Padsshortly and we can only cut between the copper pads which on some strips are only every three LEDs. So make sure you have taken this into account when thinking about your arrangement.

Also bear in mind that you’ll have ‘corner’ LEDs, it doesn’t really matter  whether these are on your ‘top/bottom’ strips or your ‘left/right’ strips but worth noting so that you can think about where the strips need cut later.

You also need to decide where on the screen the strip will start and end as this will influence the setup code further down. I’ve started mine at the middle of the bottom row to allow the cables to run down behind the TV/monitor stand without being visible.

This is the kind of arrangement you need to create:

ambilightDon’t cut anything right now, just connect the strips together using the connectors which should come attached to each end of your strip. If you have no connectors, then simply solder some wire between the matching lines on the strip using the copper connector pads at the end.

 

The Arduino, LEDs and power

This is tricky to explain so a picture will probably be most useful…

Circuit Wiring

  • The barrel connector +’ve needs to be connected to the 12v/5v lead on the LED string.
  • The barrel connector -‘ve needs to be connected to both the GND lead on the LED string and a GND pin (doesn’t matter which one) on the Arduino.
  • The data line (labelled ‘Din’ on my LEDs – the middle one) should be connected to whatever pin on the Arduino you’re going to use to send lighting instructions. I’m using pin 6 (labelled D6 on the Arduino).
    Just make sure you are using one of the Ardunio pins which supports SPI since this is how the LED data lines is controlled – use any of pins 3, 5, 6, 9, 10, 11.

I wired mine up as described above but later in the project after I had cut my LED strips and wired them up to go on the back of the monitor, I had a couple of the connectors from the end of the LED strips which had been trimmed off. I decided to rewire the Arduino/power arrangement and into one of the LED strip connectors to allow easy disconnection from the strip, that’s what you see in the picture above.

Note: If you’re connecting a lot of strips, and you don’t have a single power supply which can supply enough current for the whole strip, you can re-inject more power between strips further down the line. Probably not necessary for a short Ambilight project though.

For info: The Arduino can run off a separate 12v or 5v supply through the VIN/pin 30 (for 12v) input or +5V / pin 27 (for 5V) so you could run the Arduino directly off the barrel connector and it’s power supply. You’ll not be able to use for the Ambilight project since if you do this, it effectively takes the USB input out of the loop and we can’t then get data in from the computer but it is good to know for future standalone Arduino projects.

 

Test the Circuit

Connect the Arduino and load up the Arduino software. Make sure it is recognised by the software, if not then make sure you have the correct drivers loaded if you bought a knock off Arduino like I did.

Load the ColorPalette example sketch from the FastLED library, File -> Examples -> FastLED -> ColorPalette. Or you can use the ‘strandtest’ example from the Adafruit library.

For whatever example you choose, edit the code to make sure that it has the correct pin selected to match where you’ve connected your LED Data lead. If using the ‘strandtest’ sketch then you’ll also need to amend a couple of variables in line 16 [mine was: Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_RGB + NEO_KHZ400); ]

Send the sketch to your Arduino – your LEDs should light up and run through a test routine repeatedly. If this doesn’t work then make sure your cabling is correct and the correct pin is selected in the sketch. I had a problem where only a dim red was showing from the LEDs, this was because I was using a 5v supply for a 12v set of LEDs! Swapped over the supply and all was good!

 

The Ambilight Software Configuration

Sorry – there are not too many pictures in this section, it’s mostly just a detailed description of how to set up your Ambilight software.

I got a lot of help for this part from this Make Use Of guide. In fact, below I’ll link to one of their reader’s utilities created for configuring the code to reflect the exact placement of the LEDs. Thanks guys if you’re reading this!

Arduino Setup

Download the Arduino code from the Ambilight.ino file in my github project. Edit lines 37-41(-ish) to reflect the number of LEDs you have and the Arduino pin you’re connecting them to.

You’ll also need to check the speed of your serial port which the Arduino is connected to (note that the Arduino has a USB to serial adapter built in so the computer actually thinks it’s communicating with a serial device). Go to Device Manager –> find the Arduino (usually listed in the ‘Ports’ section –> double click it –>  go to the Port Settings tab -> check the Bits Per Second setting. Either update the Arduino code to reflect what is already set here, or change the Bits Per Second value to match the code – I changed the Bits Per Second value to match the code.

You then need to edit line 81(-ish), to find the exact values you need first open the FastLED example sketch ‘RGBCalibrate’ and follow the instructions in there. For the strip I purchased, it’s using chipset WS2812B and colour order of “BRG”. So my code is: FastLED.addLeds<WS2811, LED_PIN, BRG>(leds, NUM_LEDS);

Now click the arrow button to load it onto the Arduino. After it’s loaded on, the Arduino listens on the serial port for instructions coming from the Processing code we’re about to set up, then lights up the LEDs to reflect what Processing tells it.

Processing Setup

Now we need to set up the Processing code. This was actually produced by the awesome people at Adafruit and you can download the original code from them if you want here. But I’d recommend that you use my code from my github project (Adalight.pde) as I’ve added extra commenting to make it a bit more friendly, and also made a few more amendments which we’ll discuss below. Download, save in a file called ‘Adalight.pde’ (or whatever you want) and save that file in a folder of the same name (this is important for Processing to work with it).

Note that the Adafruit project also has a Processing file called Colorswirl which you can download and run to make your LEDs run with a swirly colour pattern. Looks good! Just remember to edit the number of LEDs and the serial port if needed (more on this below).

Also, note that if you’re troubleshooting any problems later, the Adafruit guide has a good Troubleshooting page.

…configure the Arduino connection

You may need to change line 187(-ish) if the Arduino is not the only serial device connected to your computer. Change to Serial.list()[1] if the current value doesn’t work for you. There is also some commented out code I added, which you can uncomment and run to help find your connected devices and find the right one. My Arduino was the only connected serial device so the default was fine for me.

Also check the last value in that line matches the same speed we had in the Arduino code.

…setup the LEDs

We also need to edit lines 109(-ish) and 136(-ish) which tell Processing how our LEDs are configured. This can be done ‘by hand’ and the correct values worked out using the instructions in the code but a reader of Make Use Of created an online tool to do it for us: http://www.rankinfamily.com/JSledMatrix.html

Update (16/10/16): Unfortunately this link no longer seems to be working. Luckily I saved an offline version of the site before it disappeared and have put a copy on my website here: https://www.mc-guinness.co.uk/ledconfig/
If you are the original owner, I will gladly remove this if you have any problems with me hosting it. Please just leave a comment below or email me. 

When working out how many in each row and column, the corner LEDs are counted twice – on both the horizontal and vertical axes.

Note that as we noted above, you’ll need take some care when thinking about how you’re going to position the LEDs. We’ll be cutting to size shortly and some strips can only be cut between every three LEDs, along the copper pads you can see on the strip. So make sure you have taken this into account when creating your LED configuration code.

You also need to decide where on the screen the strip will start and end, and factor that in too. I’ve started mine at the middle of the bottom row to allow the cables to run down behind the TV/monitor stand without being visible.

…dealing with ‘letterboxed’ video

There is also a potential problem when it comes to watching some movies or TV shows which are ‘letterboxed’ with black bars running across the top and bottom of the screen. In this instance, the LEDs would show nothing as they would be trying to reflect the black colour.  This can be fixed by adding adjusting the sampling region which the LEDs reflect. Again, a reader of Make Use Of adjusted the Processing code to enable us to tweak both the horizontal and vertical sampling region (see this forum post).

I have already added these changes to the Processing code you downloaded earlier so no need to try to integrate it yourself. If you want to tweak the sample region edit the last two values in line 109(-ish) to reflect the % of the screen you want to use, 95% of the horizontal and 85% of the vertical in my case: {0,18,11, 95, 85}. This seems to be sufficient to still make the LEDs work with letterboxed video. And the 95% horizontal just seemed to give a slightly better colour on the LEDs for my liking, I may change back to the default 100% later.

…turning off the Processing on-screen output

When you run the code a small image representing the LEDs appears on your screen. This is handy for the playing with the code and setting up the lights but a bit annoying when you’re actually running in everyday use. You can stop this picture appearing by commenting out (with ‘//’) lines 454-459(-ish).

I thought commenting the lines mentioned above would work to disable the preview image. I was wrong. You need to do what it says in this forum post i.e.

  1. Add this line to the top of the sketch: import processing.pdf.*;
  2. Find this line (around line 232 or so): size(totalWidth * pixelSize, maxHeight * pixelSize, JAVA2D);
    Change it to (for Windows): size(totalWidth * pixelSize, maxHeight * pixelSize, PDF, "NUL");
  3. Scroll up and find this line, around line 138-ish: port = new Serial(this, Serial.list()[0], 115200);
    Move it to under the newly amended ‘size’ line.

The sketch also prints the output frame rate as it is running. You can disable this too by commenting out line 462(-ish): println(frameRate);

Cutting The Strip

You can now start cutting your strips to fit. As noted above, you’ll see 3 copper connectors every 1 or 3 LEDs, the strips can be cut at this point and these connectors reconnected with a length of wire.

Wiring strip

Carefully measure and cut the strips you’ll need to go round your TV. At the corners, cut the strip at one of these connection points and re-connect with spare wire. Cover any bare connections with electrical tape or hot glue in case you electrocute someone (or yourself) later – although there is a very slim chance of this since the body’s resistance is so high and there is such a low voltage running through the circuit.

Go ahead and peel off the backing paper and stick the LEDs to your TV! Connect up the Arduino and power then run your Processing code!

 

The extra bonus stuff!

This stuff is not required since you have your LEDs working already but there are a few more things you can do to make the experience a bit more seamless…

Automate the LED startup

It’s annoying to have to manually start the Processing sketch every time you start your computer so why don’t we automate it?

Luckily Processing accepts command line arguments and can run sketches directly from there. That way we can create a .bat file with the startup command to run on boot which will start the LEDs when the computer starts.

You can find more details of the Processing command line options here: http://www.dsfcode.com/using-processing-via-the-command-line/ . Or from inside your Processing installation folder open a command prompt and run ‘ processing-java --help ‘

First create a folder called ‘output’ in the same directory as the Adalight.pde file. This is needed by the Processing command line commands. Next, create a LED_Start.bat  file in your computer’s startup folder and add this command to it (obviously change the paths to match your file locations):

<Path to your Processing installation>\processing-java.exe --run --force --sketch=<path to your Adalight.pde file>\Adalight.pde --output=<path to your Adalight.pde file>\output

While this will start your lights when your computer boots it will also create an annoying command prompt window which will remain on your desktop. To avoid this, you can follow my other guide on running command line programs silently, then you can run it without any command prompt window.

 

But what happens if you want to stop the lights?!

Easy, you can run another batch file which will kill the Processing tasks and after 60 seconds the lights will turn off (this length of time is set in the Arduino sketch and turns off the LEDs when no instructions are received for X seconds – you can change it yourself).

My batch file for killing the Processing tasks is in the github repo but just be aware that there is a very slight chance that it may also accidentally kill other processes if they match the wildcards. Also note that the file is setup to kill tasks based on naming the Processing code file Adalight.pde, if you have not used that name then you’ll need to edit the batch file to match yours.

 

Power your LEDs directly from your computer!

If you’re reading this then you are probably the type of person who builds their own computer, if not then read on anyway as anyone can follow this.

Molex WiringYour computer PSU outputs both 12v and 5v to power a number of components inside. It can also provide up to around 11 amps through these connections. You’ll need to make sure your power supply doesn’t get overloaded, remember that your power supply will be rated in the wattage it can supply and your computer components will use a chunk of that already. You know the  current draw from your LEDs since we worked it out up above and using P = IV, you can work out how much more power the LEDs will suck from your computer PSU.

Conveniently for us, the molex connector for a non-SATA hard drive or CD/DVD drive has all the power delivery we need. The molex connector has a 12v, 5v, and two GND pins.Molex Adapter

Even modern computers which mainly use SATA drives should still have a couple of these older style molex connectors. We can chop off this connector or, better yet, use a molex adapter/splitter cable to wire in some DC adapters to allow us to plug in the LED circuit we created above. I had a molex adapter lying around which used to be used to power some case fans.

You’ll want to keep the ‘male’ end and cut off the rest of the adapter but leave plenty of wiring attached to allow us to wire in the DC adapters like so…

Molex wired to DC adapters

Then connect to the molex connection inside your computer (please turn the computer off and unplug it first!) and connect the Arduino to a USB cable as before and you’re all set.

You can even get an adapter which can plug into the USB header pins on your motherboard which will give you a USB socket inside your case, that way all the cabling to the Arduino/power can remain inside the case.

Internal USB

You will need to find a route out of your case for the LED wiring and also almost definitely need to extend the wiring between the Arduino/power and the start of the LEDs but I feel like this is quite a neat solution to connecting everything up.



Useful links:

21 Comments

    1. Thanks fabio – I'll look into ambibox. Processing is fine for my desktop machine since it's brand new but the machine that the TV is connected to is a bit older and just running the lights takes 15% of the CPU.

      I'll update this post if I find a better solution.

    2. Just tried Ambibox. Works well. Lower CPU and higher frame rate. But there is about a quarter of a second lag between what is on the screen and the light changing. Haven't been able to get rid of it so far with changing settings but will keep tweaking. Shouldn't be related to my PC performance as I'm running on a new i7-6700 with a 980ti.

      Looks like a really good tool as it's easier to configure and has lots of plugins but I'll need to go back to Processing if I can't fix it.

      Also heard good things about Pismatik (the up to date fork not the original) so might try that too.

  1. hy I made my desktop ambilight just as you described hier ,but i have a prob and i dont know how to do it right as i run a rgb test sequence its like in mirror blue is up and green is down. i can send you a photo about my config and settings in the pocessing code i just cant get itt right! maybe you could help me out.
    Thanks anyway.:)

  2. Hi.

    I'd like to thank you for your tuto. I was struggling with the ws2812B and Arduino code. Yours works perfectly. And It was all I needed.
    Thank you again.

    P.S: I'd like to translate in french your work, may I ?

  3. I am getting an error of course with my luck.

    c = pxls[offs[o]];
    ArrayIndexOutOfBoundsException: 2079362

    Anyone know how to fix this?

        1. How far did you get? Did you manage to test the LEDs with the RGBCalibrate code? Did that work ok?
          I've never seen them just show white from the Processing code not sure what that could be.
          You could try one of the other programs (e.g. Ambibox or Prismatic). They work really well and will work with the LEDs as long as you have got the Arduino code loaded onto the Arduino. In fact, I've moved to using Ambibox on my TV as it has a better refresh rate and works on lower end hardware. Sticking with Processing on the PC monitor as the specs are easily good enough to run it.

          1. Yes, I did manage to test the LEDs. I got it to work in processing but does not work in full screen. So I tried Ambibox for full screen and it just used half the lights.

  4. The only thing I can think of is that you may not have correctly defined the number of LEDs in the Arduino code?
    Or Ambibox can be a bit fiddly to set up and you need to do the config wizrd thing to define the number of LEDs, how many on each side etc. Make sure you've done that correctly.

    1. Mine worked since perfectly… but now the LED's turn red after like 5 minutes. Maybe it's my cheap Arduino or leds.

  5. Thank you for the tutorial. I'm waiting for my led strips to arrive. WS2812 s weren't available locally. So, I had to order it from aliexpress.

  6. I'd love to see a Raspberry Pi version of this. I'd like to adapt to my 120" screen that runs off my bluray players.

  7. I've finally finished this project and yours is the first code I've gotten to work, probably because the instructions are so clear. Thank you for posting this and taking the time to explain so well! Now with the backlight I just have to clear out all the cords I've been stashing behind my monitor.

Leave a Reply

(email optional)