TV Ambilight USB Webcam Arduino/Raspberry Pi

by TheoShah04 in Circuits > LEDs

8988 Views, 45 Favorites, 0 Comments

TV Ambilight USB Webcam Arduino/Raspberry Pi

TV Ambilight Arduino/Raspberry Pi USB Webcam
TV Ambilight Showcase
2D061FBF-8B08-4492-8D15-C2A5D27247E7.jpeg
067F3414-45D4-4229-B7D9-9AD5F4E3055C.jpeg

In this instructable, I will show you (or bore you) on how to set up your own TV Ambilight using a USB Webcam, Arduino and a Raspberry Pi. Instead of using a HDMI Capture Card that not only takes up a HDMI port space on your TV (which i dont have availiable), and are incompatible with Smart TV's, USB Webcams are a cheap alternative.

It uses a combination of a Raspberry Pi, which is better at capturing live videos due to better processing speed, and a Arduino, better at controlling other hardware devices due to a better clock and a friendlier interface, meaning you will be able to improve your skills in both controlling platforms.

If you're starting with absolutely nothing, all the required components will cost between £60 - £90, but i will be genuingly suprised if you have survived through lockdown without a USB Webcam! And yes, i am aware Philips sell these kind of things for around £150 but whats the fun in buying that?

If you have any questions, i am more than happy to answer them as soon as possible and with as much clarity.

So if you're intrested in listening to me for more, start at Step 1. If you're already bored, i don't blame you.

Supplies

Hardware

Software

Raspberry Pi - Setting Up the SD Card

Screenshot 2021-09-04 130409.png
2021-09-10.png

Firstly, before you do anything with the Hyperbian image, because burning an image onto a SD card erases all data stored on that drive previously, if you only have one SD card, you will want to back up your SD data onto another device to be stored and can then be burnt back onto that SD card later without any data loss. However, if you have a new SD card or a SD card with unwanted data, you can skip this step:

To back up your data, you will need a micro SD card reader and plug it into a laptop or computer where it will be detected. Then to transfer the files, you will need to download and launch an imaging program, and if you're on Windows, launching Win32 Disk Imager will work fine and for free. If you are on Mac, there is this guide that covers backing up Raspberry Pi SD cards.

Once it's launched, you will first need to select the SD card, then select a folder to transfer the files to be stored, and then press the option 'Read' to start the transfer. Beforehand, i created a folder called "Transfer Files" on my laptop drive where the data would be written to. To restore the files, you will need to select the folder the files are stored and the drive you want to write it on, and then press 'Write' instead. By using an imaging program, it is able to preserve the data in a image state so that when restored, the file will work immedietely with the Raspberry Pi.

Raspberry Pi - Hyperbian

2021-09-02 (3).png
2021-09-02.png
2021-09-02 (1).png
Screenshot 2021-09-03 121046.png
A07F7C02-136C-4704-9453-B45734015964.jpeg

Ok, so now that you've got a free SD card, you will need to download the Hyperbian image from here and once the download is complete, you will need to extract all the files from the zip folder. Then, using the Disk Imager you may have used last step or another imaging program, you will need to burn the Hyperbian image you extracted onto the selected SD card plugged into your device using a Micro SD card reader.

Once the image has been burnt onto the card, insert the card into the Raspberry Pi you're going to use, then power up the Raspberry Pi and connect your keyboard and mouse, then by using a HDMI cable connected to a monitor, you will be displayed with the Hyperbian terminal asking for your login credentials. The default credentials are:

Login - pi

Password - raspberry

When typing in your password, it may not be displayed for security reasons but if you type in your password properly it should still work. Once you're logged in, you can connect to the internet by typing in the command:

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

And then adding this at the bottom with your own internet information: (If your on Pi 3B+ or 4, or if you want security, this page will better explain this)

network={
   ssid="testing"
   psk="testingPassword"
}

Once you're connected to your Wifi, these commands should then activate your Hyperbian Configuration Page:

sudo systemctl disable
sudo systemctl enable
sudo reboot

After rebooting, if you see "Hyperion Stasus - Running", then your page should be up and running (the web address is shown above in blue). It is also very helpful to turn on "Auto-Login on Reboot" so that you don't have to type in your username and password everytime you disconnect or reboot your Raspberry Pi. To do this, type:

sudo raspi-config

Then choose boot options, then enable desktop and console autologin, which will then prompt you to restart.

Arduino - Code

2021-09-03.png
2021-09-03 (1).png

For the Arduino to be able to control the LED strip, the Arduino needs code so that each individual pixel can be tuned in real time. Before you upload the code though, and if you did, you would have realised that the code utilises the "Fast LED" library that makes it much easier and quicker to control the LED's. To install the library, you will need to select Below is the Arduino Code that needs to be uploaded to the board using a Serial USB cable and the Arduino IDE:
(Bear in mind that some parts of the code will need to be altered to suit your own project but i will indicate where)

#include "FastLED.h"
#define NUM_LEDS 124 //Type in the number of LED's that you will use 
#define DATA_PIN 6 //Type in the PWM IO Pin of the Arduino the data pin is connected to 
#define COLOR_ORDER RGB
#define SerialRate 500000 //Baudrate: higher = faster refresh rate
CRGB leds[NUM_LEDS];

uint8_t prefix[] = {'A', 'd', 'a'}, hi, lo, chk, i; //Magic Word

void setup() {
        FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
        LEDS.showColor(CRGB(255, 0, 0)); //testing
        delay(500);
        LEDS.showColor(CRGB(0, 255, 0));
        delay(500);
        LEDS.showColor(CRGB(0, 0, 255));
        delay(500);
        LEDS.showColor(CRGB(0, 0, 0));
       
        Serial.begin(SerialRate);
        Serial.print("Ada\n"); // Send Magic Word string to host
}
 
void loop() {
  int switchPin = digitalRead(12);
  if (switchPin == 0){
    for(i = 0; i < sizeof prefix; ++i) {
    waitLoop: while (!Serial.available()) ;;
    if(prefix[i] == Serial.read()) continue;
    i = 0;
    goto waitLoop;
  }
 
  while (!Serial.available()) ;;
  hi=Serial.read();
  while (!Serial.available()) ;;
  lo=Serial.read();
  while (!Serial.available()) ;;
  chk=Serial.read();

  if (chk != (hi ^ lo ^ 0x55))
  {
    i=0;
    goto waitLoop;
  }

    memset(leds, 0, NUM_LEDS * sizeof(struct CRGB));
    for (uint8_t i = 0; i < NUM_LEDS; i++) {
      byte r, g, b;    
      while(!Serial.available());
      r = Serial.read();
      while(!Serial.available());
      g = Serial.read();
      while(!Serial.available());
      b = Serial.read();
      leds[i].r = r;
      leds[i].g = g;
      leds[i].b = b;
     }   
     FastLED.show(); //Update with new values 
  }
  
  else{
    LEDS.showColor(CRGB(0, 0, 0));        
    FastLED.show();
      }
}

Before uploading, make sure you are uploading to the right Arduino board and that you have selected the right COM port and the right Bootloader. For me, because i was using a Nano 'Clone', I had to select "Arduino Nano" and "ATMega328P (Old Bootloader)". Once the code has been uploaded, you can unplug the Serial Cable and plug it back into the Raspberry Pi so that they can communicate between each other.

Electronics and Wiring

D71726D4-3426-4F1A-8A3E-02E8146EF3AD.jpeg

Once you're done with the Hyperbian image and code, you will need to setup the USB Webcam as well all the wiring with the LED strip and Arduino.

As I said before, i'm pretty sure any webcam with a USB cable can be used as a video input stream and so the only thing you will need to do is to plug the USB connection into any of the USB ports on the Raspberry Pi. For the Arduino which will be controlling the LED strip, there is a picture of all the wiring needed. The data IO pin for the LED strip can change as long as it changes to another PWM IO Pin and the #define line for the DATA_PIN is changed as well. By plugging in the Serial USB cable into one of the Raspberry Pi USB ports, the Raspberry Pi will be able to communicate with the Arduino. To be able to control whether you want the LED's on or off without a IR Reciever, you can use a switch with 3 connections, one to 5V, one to ground, and one to a IO Pin on the Arduino that is correctly defined in the Arduino Code.

Usually a Raspberry Pi would need to be powered by a separate power supply through the Micro USB port but this can be annoying to use two power sockets and so instead power will be supplied by the main power supply and through the 5V pin on the Raspberry Pi with GND connected too. To power the Arduino, 5V is supplied into the board using the Vin pin, which itself also needs to be grounded.

Setting Up the LED Strip/Power

AmbilightTV Soldering Timelapse
E4B4F9C4-15CA-4969-858A-892D2546854E.jpeg
8073E621-015A-45E6-ACE0-3831A480A5E3.jpeg
C70F022F-E49D-43E8-A59D-C094B74D8FCA.jpeg

Although the LED strips require 5V and so theorectically the Arduino 5V output pin could power a small number of LED's but in this situation when we are using 124 LED's (worked out below), and when running, they will draw a maximum of 8.5 Amps of power and at 5V, 42.5 Watts of power will be running through the Raspberry Pi and Arduino which will quickly fry them up.

Instead of powering the LED's with the power from the Raspberry Pi and Arduino, you will instead want to use an external 5V power supply capable of withstanding a minimum of 8A output. Of course, if you use less LED's, less current will be needed to be drawn and so a weaker power supply can be used at a reduced price. The power supply i bought comes with an adapter for positive - negative wire outputs from the barrel jack the supply outputs. If no adapter comes with the power supply, they are pretty cheap to buy. Plug the power supply into a wall socket next to the TV.

As for the LED strip itself, you will want to buy specifically WS2812B LED strips as not only can they be programmed by Arduino and Raspberry Pi microcontrollers, but also that each LED can be assigned its own colour as some LED strips make it so that all LED's have to be one colour which is obviously not what we want.

To set up the LED's on the TV, I first measured how many LED's would fit on the dimensions of my TV, which in my case was 58 LED's on the top and 33 LED's on the sides, and because i want LED's on the top and both edges of my TV, that's a total of 124.

The next step is to work out how you want to turn your LED strip 90 degrees on the corners of your TV. There are many ways you can do this:

  1. Use L shaped connectors that can safely and easily connect strips together
  2. Bend them!
  3. Cut the strips with scissors and solder wires connections, which is what i ended up doing, shown in the video. (5V to 5V, GND to GND, Dout to Din)

Just as a warning, it is a pain to try and solder flying leads to the miniature brass areas you need to solder on so if you're new to soldering, i would recommend the other two options that are safer/easier. You can see my frustration in the video!

To attach the LED strip to the back of the TV, i just used some clear tape to stick them onto the edge so that they can be easily removed but you can use the back tape the strip comes with if you want a permenant installation.

For the rest of the electronics, i just hid them behind the TV and rested them on the platform that holds up the TV so that wires aren't visible when watching. For the USB webcam, I placed it on a coffee table in front of our TV so that it's easier to crop out the pixels of the wall around the TV in the captured frame later on. I also taped the USB Webcam in place to the table to make sure it doesn't shift around.

Configuration - Input

2021-09-11 (3).png
2021-09-03 (3).png
Screenshot 2021-09-10 221405.png

So once you're done with the Hardware, you will want to use a device connected to the internet and in your browser, type in your Raspberry Pi IP Adress followed by :8090

Example - http://192.168.79.372:8090

You can find your Raspberry Pi IP address in your terminal by typing in the command:

Hostname -I

Once you've typed in the web address, it should open a Configuration Hyperbian Page for your Raspberry Pi. On this desktop page, the first thing you will want to do is to enable USB webcam as a setting in the "Capturing Hardware" tab on the left. Once that's enabled, you will see your webcam in "Devices Discovered" and the next thing that you will want to do is to decrease the "Device Resolution" to the lowest setting possible, which was 340x240. By doing this, it takes a lot of stress off the Raspberry Pi and will prevent it from overheating and the lower resolution will not matter as the Hyperion software itself lowers the resolution of the image to generate colour averages of pixels to be displayed.

You will instead want to increase the FPS of the camera to get a smoother display. This is also where you will be able to crop the video stream edges, meaning that you will be able to get rid of the pixels of the wall/other surfaces around the TV that the USB camera is capturing. If you don't, the colour of the surrounding surfaces will interfere with the colour of the LED display. You can keep tweaking how much you're cropping out and then check the preview of the live video explained below. You will want the edges of the captured frame to be some centimeters off the edge of your TV Border.

To check that your USB Webcam is working, you can preview the captured image by pressing the monitor button in the top right and then pressing live video. It also shows what colour the LED's should be displaying.

Configuration - Output and Communication

2021-09-11 (5).png
2021-09-04 (2).png
2021-09-11.png

Once your done with the Input, now we need to focus on the Output LED in the LED instances tab. Select the "LED Layout" option followed by the "Classic Layout", which will give you the ability to type in how many LED's you have on each edge of your TV and will also helpfully tell you your max power usage depending on the number of LED's your using. Another important feature you will need to check is which of the LED's is the first LED (first LED on the start of the strip) and with the "Input Position" you will need to select where that first LED is.

If prime or secondary colours (RGB, Cyan, Magenta, Yellow) are not being displayed correctly when you test it later, (for example Red on the TV caused the LED's to go Green, and Cyan caused a Magenta LED cololur, and vice versa). To change this, on the "Image Processing" page, you can change what the LED's think the colours are in RGB to get the right display, shown in the image.

Once your done with the Input of the Raspberry Pi and Output of the Arduino, we now need to make it so that they can communicate. To do this, plug the Serial USB cable into one of the USB ports on the Raspberry Pi. Then, on the Hyperion page, if you stay on Output LED tab but instead on the "LED Layout" option, in the "LED Controller" select, change the controller type it to "adalight" under USB/Serial and it should detect the Arduino plugged into the Raspberry Pi. If you are using a Arduino Nano, it will display USB0 at the end, and ACM0 if a Uno, Due or Mega is being used. In addition on this page, you want to set "LED Hardware" to the number of LED's you are using. A very important thing you are going to want to do next is go to the Hyperion settings in the top right, and where it says "Setting Level", change it to the maximum setting, and on the LED Controller page, you should now see an option to select the Baudrate. Change this to whatever the Baudrate is in your Arduino Code, which in this case is 500,000, as the Raspberry Pi and Arduino will not be able to communicate if the baudrates are different.

Done!

5E3E1268-65ED-4DAC-ADC2-03EAB60BFBD6.jpeg
AE61F266-3E6E-4CF3-8E7F-17B9153E45C6.jpeg
E500A491-0EE2-4DD9-BEDC-5FB4840ED577.jpeg

Hopefully if you've done everything right, as soon as you save the settings and power the electronics with your power supply, the LED's should first display some testing colours and then accurately react to your TV display. If the colour display is off, you can alter the saturation or brightness settings in the Hyperbian Configuration Page until you're happy!

Because the image is captured by a USB Webcam, it means anything displayed on the screen is captured, meaning you can even play on your Xbox/PS while the LED's are on, creating a better immersive experience.

One thing to note is that this feature works better on TV's that are parallel to the back-wall, causing less light dispersion and less irregularities, but it doesn't matter too much shown in my TV where it is angled against a corner.

If you have any questions, i am more than happy to (try to) answer them, and if i've missed something completely or not in enough detail, feel free to mention it. If anyone does replicate it, i would be very intrested to see!