Promiscuous Ambient Light
I love shiny. So a television ambient light was an obvious project to spend some time (probably more than I should) and dollars (not many actually).
There are many choices depending on your hardware and budget, but I had some restrictions:
- It should work with any HDMI input. I have been a Kodi+Raspberry pi user for years, but recently I have moved to a Roku device as it was the only reasonable option to have a local media player plus the stream applications that I usually use all centralized (Netflix, Prime, AppleTV+, Youtube). So far I am happy with it, but knowing me it is just a matter of time to start using a different rig, so I wanted something that could work with any HDMI output (hence the promiscuous name)
- It should be cheap. Let´s be honest, I don´t need any of these.
So I searched the web for options, (There are some very good tutorials over there like the one in Muffin´s lab) and the most appealing was to use a Raspberry pi to capture the images to be displayed in the screen, process them, and interact with a strip of leds.
- Pros: works with (almost) any HDMI output and it is cheap
- Cons: nothing beyond that it requires fiddling with wires and some raspberry kung-fu
Supplies
This is the list of supplies. The prices are approximate and based in the components that I bought.
As part of the fun was to select the different components, I will include more accurate information and the links to the stores along the different steps.
- A TV. You probably have one already, its main function in the project is to serve as a surface where to stick the leds.
- A Raspberry Pi. Between $5 and $70, depending on the model.
- An HDMI splitter. $20 (you can probably do better than this)
- A USB HDMI video capture card. $12
- An individually addressable RGB led strip. $15
- A power source with enough wattage. $15
- A JST connector with the same number of pins that your led strip uses (and the opposite gender). $2
- A couple of short HDMI cables (apart from the one that your TV already has)
- Electric cable, and some other random stuff that you probably have around.
- Iron solder (probably) and some basic tools.
How Everything Fits Together
The basic idea is to get the HDMI signal coming from a media center (in my case a Roku device) and feed it at the same time to the TV (you still want to keep watching your series) and the Raspberry for processing. You can do that easily with a HDMI splitter, a device that takes one HDMI input and generates two or more identical HDMI outputs.
To get the HDMI signal into the Raspberry we need a HDMI to USB capture card. These devices work surprisingly well for the low cost that they have, they connect to the USB and create in your computer a video capture device that can be used by different software.
The Raspberry has to process the image, and determine what are the relevant colors to send to the led strip, this is done through a very nice software called Hyperion that can do all that for you.
Obviously, the led strip has to be connected to the Raspberry, that is done using of the pins in its GPIO interface.
Finally, you need to power all this. The important part is to have an idea of how much power the leds could draw so you can select a power supply with the right watts.
Capture the Signal
One of the fun things of DIY projects is that you learn things. In my case, one of the things I learned is that there is something called High-bandwidth Digital Content Protection (HDCP) that is used to prevent copying HDMI audio and video as it travels through the connections.
From a practical point of view and for what we want to do, this means that all the devices that the HDMI signal crosses have to be HDCP compliant. In my case, I learned that the hard way when after connecting this splitter, I got a message about it in my TV. I had a small panic attack that drove me to buy a compatible replacement as soon as possible and ended up with this one, significantly more expensive, and with some features I do not need (four outputs instead of two), but hey...
In any case, when you buy yours, make sure that it is HDCP compatible and it provides one input to two simultaneous outputs (there are some splitters that let you decide to what output do you want to send the signal to).
Using the USB capture card shouldn't be a trouble. Just make sure that it works. The easiest way is to stick it into a USB port of the raspberry, open a SSH session and use the command v4l2-ctl to list the capture devices in the system:
$ v4l2-ctl --list-devices
If you get an output that includes a USB device you are probably good to go. If you want to test the card in any other system (Windows, Linux, OSX), take a look at OBS, the Open Broadcaster Software.
Nothing much else here, just connect the output of the media center to the input of the HDMI splitter and then one output of the splitter to your TV set and the other to the USB HDMI capture card.
Gimme the Power
One of the most interesting parts of the project was to figure out how to give power to all the components in the simplest possible way. The easiest would be to use independent power sources for the Raspberry and the led strip, but I wanted to keep the number of cables and components to the minimum possible, so I decided to make it a little more interesting.
I have to say that I use to have nightmares where some of my electronic devices catch fire, so I tend to be very careful when playing with volts and amps. In any case, feel free to use the 'legal' power supplies for your components.
The most important part to take into account about powering this project is to be aware that the leds may require a significant amount of power that goes beyond the power source that you use to charge your cell phone.
I have selected a led strip of type ws2812b, one of the reasons is that this strip works at 5V, same as the Raspberry, which will be useful later. Each led of this strip, when at maximum intensity needs around 50mA. As I said, let's play safe and assume that it is 60mA. With the density of the strip that I have bought (3 leds each 10cm) and the dimensions of my TV (55 inches), I am counting a total of 110 leds. Some complicated calculations says that my led strip could draw 6600mA (that is 6.6A) when at maximum power.
The Raspberry that I am using is an old Model B rev 2 that I had accumulating dust. According to the vendor specifications, the recommended PSU for this little boy is 1.8A. So, to properly power the project under the most demanding circumstances, the PSU should be able to provide at least 8.4A at 5V.
There is an overwhelming variety of PSUs in the market, but I decided to keep things simple (again), and selected this one. The model with 5V and 8A. I know it is under the theoretical maximum, but I had oversized the maximum led consumption and it is also very unlikely that the Pi will get to the maximum. Actually, afterwards, I did some tests of normal use that gave a maximum draw of 3A.
Now, one small detail regarding the power supply. This PSU comes with a standard 5mm cylindrical connector, then, how can I connect it to the led strip that has one of this fun 3 pint JST connector and to the Micro USB of the Raspberry Pi?
This is what I did (later I realized that I shouldn't, but it was fun).
I assume that you are aware that any operation that you do involving power sources has to be done with the power source disconnected, but just in case, always make sure of that when you cut or touch non isolated wires.
I removed (cut) the connector of the power supply and used a very fancy fast-wire-connector that I was dying to try to get two pairs of cables (one for each device I wanted to power). Usually, the red wire is the positive and the white is the negative, but it doesn't hurt to test it with a voltimeter.
For the Pi I used the micro USB connector of an old phone charger and connected it to one of the pairs (Positive+Ground) that came from my fancy connector, you only need to be careful with the polarity of the cables in the micro USB connector, so before cutting it, make sure to note down which one is positive and which one is ground.
For the led strip, I attached the other pair to the respective Vcc and Gnd pins of a female JST connector that will be connected to the connector in the led strip.
Double check every connection. Make sure that no ground wire touches any positive one. Check it again and then connect the micro USB to the Raspberry, the JST to the leds and the PSU to the wall.
If you get smoke there is something wrong. If your Raspberry power led lights up you did pretty good (your led strip may or may not light the leds, that depends on the strip that you have bought, we will check that one later)
The Software
This is about software, but before that let's have some context about the platform where the software runs, the Raspberry Pi.
I used an old Raspberry that was gathering dust in a drawer. It is a model B probably from 2012, and its computing power is significantly lower than modern models. The most demanding activity that the Pi is going to do is to process the images coming from the HDMI capture card. The Pi has to do this very quickly to be able to match the led lights with what is seen in the screen. There are some parameters that can be adjusted to make everything run smoothly, basically, the frames to analyze per second, and the resolution of the frames. As my Pi is not HAL9000, I have chosen low values for this parameters, but I am quite happy with the results.
The software chosen to do the image processing and control the led strip is Hyperion. As we want to make it run in a Raspberry Pi, we will need also to install an operating system for the Pi (unless you have one already working).
I found out that there is a nice Raspberry distribution ready to use called Hyperbian, it contains a Raspbian lite, the Hyperion software already installed, and a web server for configuration, so you don't need to bother with any other application.
This is what you should do:
- Download the Hyperbian image from the Hyperion web site
- Uncompress it, you will get a .img file that you need to burn into the Raspberry SD card. To burn it, you obviously will need a SD card reader and some software (depending on your OS) to burn the image to the card. The Raspberry Pi site has very detailed instructions to do this.
Before booting the Pi, think that you will have to configure Hyperion using a web browser, that means that the Pi has to be connected to a network. If you have a wired network, you only need to connect the Pi using the Ethernet port and find out the IP that the DCHP server has given to it to access it using the web browser. Most likely your DHCP server runs in your home router which has an interface to check the allocation of addresses. But if that is not the case, you can always connect the Pi to a monitor and see the assigned IP address in the boot messages.
If you want to connect using wireless (remember, that this is only necessary for the initial configuration of the Hyperion system), you'll need to do some more configuration. First, find out if your Pi has integrated wireless, if not (like mine), you'll need to use a USB adapter. I used an old Realtek adaptor that was in the same drawer than the Pi. To make it work on boot you need to modify a couple of files in the image that you have just burned into the SD. If the SD is still inside the card reader, the computer will have mounted a filesystem called 'boot'. Go to it and do the following:
- Create an empty file named ssh
- Create a file named wpa_supplicant.conf with the following content:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
country=EN
update_config=1
network={
ssid="name_of_your_wifi_LAN"
psk="password_of_your_wifi_LAN"
}
Remember to put the actual name and password of your WiFi network. Just in case, there are more detailed instructions here.
If everything goes good, you should be able to access the Hyperion interface using a browser from any computer in your WiFi network with: http://IP_of_your_Pi:8090 (I don't need to tell it, but you must replace IP_of_your_Pi for the actual IP address of your Pi, for instance http://IP_of_your_Pi:8090
The Shiny
I wonder who doesn't like leds, with a more than reasonable price, and a little ingenuity you can transform a boring space in an Onlyfans studio.
The led strip selected is of type ws2812b. In this model, the leds are addressable individually, which means that we can select which leds will be switched on, and with what color. Which is an obvious requirement for the ambient light system. Also, this strip only needs a data line to specify the colors and leds to light, which is very convenient.
Each led in the strip has a small integrated circuit that, among other things, interacts with the data line to light the three components (Red, Green and Blue) of the color that we want to obtain. You can cut the strip to the length that you need for your project (as long as you cut by the indicated places) and you can stick together multiple strips as long as you respect the continuity of the three wires (Voltage, Data, Ground).
Another parameter that you may need to decide when buying your strip is its density (# of leds by unit of measure), the bigger the density, the nicer the effects that you can obtain, but keep in mind that the power requirements will also increase.
In my case I bought a strip with low density (30 leds per meter) that is sold in a roll of 5 meters for 13 dollars. There is another parameter to take into consideration when buying led strips which is the IP (Ingress Protection) rating that defines the degree of protection that the strip has against water. This is important if you are going to do an outdoor project, but as I am assuming that your TV is not waterproof the lowest IP (IP30) is more than enough.
Now you need to determine how many leds do you need, in my case, I needed 110 leds to create a complete rectangle in the back of the TV. 120cm in the horizontals (up and down) with 36 leds each, and 63cm for the verticals (left and right) with 19 leds each. A total of almost 3.7 meters of shiny.
The led strip has an adhesive, that in my case worked pretty good, but you can always reinforce it with tape on strategic places (just be careful of not covering any led). Some people cuts the strip in the four segments that are needed to create the rectangle and then solder them or use L-shape led-strip connectors. I just bent the bugger.
The most important thing is where to set your led #0, that is the one closest to the start of the strip (usually where the connector is), you probably want it close to the raspberry and the power source. In my case it was the lower right corner as you look at the TV from the front.
In a previous step we connected the power and ground cables from the PSU to a three pin connector, so we still need to figure out what to do with the remaining cable in the connector, the one in the middle. This is the line that the Raspberry will use to send the signals to configure the colors and intensity of the leds. To do it, it uses something called Pulse Width Modulation (PWM) that in the Raspberry is associated to GPIO 18, which for whatever reason is pin #12 in the board, or the sixth pin counting from the top in the right row of pins if you keep the GPIO on the right (HDMI on the left) and look at the Pi from the top.
The complete pinout of the Raspberry is here.
Once identified, you need to connect the GPIO 18 to the three pin connector that will go later into the connector at the end of the led strip. You can just use a cable to do the connection, but it is recommended to add a small resistor (100 Ohm) to protect the Pi in the case that something goes wrong with the led strip. The most complicated thing is how to do the actual connection between the GPIO pin and the resistor/cable. You can solder it, or can use any other type of connector. I used part of an EDG connector that I had in the toolbox (that useful Diogenes syndrome).
When you use an external PSU to power a load (in this case the led strip) that is also connected to the Raspberry you must make sure that both, Raspberry and load, have a common ground. In this case, the external source is also the source that we are using to power the Raspberry, so most likely is not necessary to provide a common ground, but as I am a coward, and just in case, I did it anyway. It is as easy as connecting any of the GND PINs of the GPIO to the common ground. Luckily, one of the pin besides GPIO 18 is a Ground PIN so I can use the same double EDG connector for both wires.
At this point everything is ready to connect and start the configuration of the leds. Go to the Hyperion interface using http://IP_of_your_Pi:8090 and do the following:
In Configuration->Led Hardware, select the controller type ws281x and the RGB byte order as GRB. Also, input the total number of leds that your project uses (in my case it was 110)
Then go to the Led Layout tab and configure how many leds are in the top, bottom, left and right rows, and move the input position towards the start of your led strip. Remember that for this we are looking at the TV from the front.
Finally, in Configuration->Capturing Hardware, go to the USB capture section and configure the device as USB video. Here is where you can fiddle with the device resolution and frames per second. The higher the resolution and the numbers of FPS, the more accuracy that you will get when translating the colors, but the more computer power that you will need.
Tidying Up
With everything working it was the moment of make some modifications to give it a more permanent status, basically I replaced the fancy cable connectors for something more industrial, soldered the resistor to the cable going into the GPIO 18 and covered with some heat shrink tube, and used a pair of male/female cylindrical connectors for the PSU and the rest of the components (yes, the same one I cut some steps ago.)
Finally, I velcro attached all the components to the back of the TV set.