Archive for February, 2012

Ambilight clone – Software

This is part 2 of this post

I have decided to write this up as a seperate post, due to length.

 

There are 2 pieces of software required to get an Ambilight working; The program to run on the arduino and Boblight.

Arduino

The code that runs on the Arduino was found here: https://github.com/michaelficarra/ambilight/blob/master/ambilight.ino

It can be run pretty much as-is, with one minor modification. To run with more than 32 LEDs, or faster than 30fps, the line

#define serialRate 38400

should be changed to

#define serialRate 115200

Here are the instructions on how to set up the required library (assuming you have the Arduino environment already installed)


$ SKETCHBOOK_PATH=$(grep ^sketchbook.path ~/.arduino/preferences.txt | cut -d = -f 2)
$ mkdir -p "$SKETCHBOOK_PATH/libraries"
$ cd /tmp
$ git clone git://github.com/arduino/Arduino.git arduino
$ mv arduino/libraries/SPI "$SKETCHBOOK_PATH/libraries"
$ rm -rf arduino
$ cd "$SKETCHBOOK_PATH/libraries"
$ git clone git://github.com/adafruit/WS2801-Library.git WS2801

This should install the SPI and WS2801 libraries required for the arduino code to run.

 

Boblight

The boblight project page can be found here: http://code.google.com/p/boblight/

And the instructions for installation are as follows (taken from the Compiling guide on google code)


$ sudo apt-get install libx11-dev libgl1-mesa-dev libxrender-dev libxext-dev portaudio19-dev libavcodec-dev libavformat-dev libswscale-dev libavdevice-dev
$ cd ~
$ svn checkout http://boblight.googlecode.com/svn/trunk/ boblight-read-only
$ cd boblight-read-only
$ ./configure
$ make
$ sudo make install

This should be all the software that is required to get an ambilight clone functioning. Boblight is made up of two components; The boblightd server which communicates with the Arduino and boblight clients which actually provide the colour data.

Boblightd requires a config file at /etc/boblight.conf and I have uploaded mine here

[global]
interface 127.0.0.1
port 19333

This defines which IP address and port boblightd listens on for clients.

[device]
name arduino
output /dev/ttyUSB0
channels 196
type momo
interval 16600
rate 115200
prefix 55 AA 55 AA 55 AA 55 AA
allowsync yes
#arduino bootloader runs when opening the serial port for the first time
#delay transmission one second after opening so we don't send shit to the bootloader
delayafteropen 1000000

  • name is a unique name for this boblight device
  • output is the where the Arduino connection can be found
  • channels is the number of LEDs * number of colours. In my case this is 64 * 3
  • type is the protocol used to communicate colour data, and should be left as ‘momo’
  • interval is how often updates are sent to the Arduino (in uS). 16600 is ~60 fps
  • rate is the number of bits per second to send over the link to the Arduino. This must match the #define serialRate set in the arduino code.
  • prefix is a string of bits sent between each frame of data
  • allowsync enables real-time updating of the colour data. This means a quicker response time of the LEDs but will also lead to the LEDs being out of sync if the data rate to the Arduino isn’t high enough

Next, the colours of the LEDs are defined:
[color]
name red
rgb FF0000
adjust 1.0
blacklevel 0.01

‘name’ and ‘rgb’ are fairly self-explanatory. ‘adjust’ is a value between 0.0 and 1.0 which allows the intensity of each colour to be calibrated. ‘blacklevel’ is the minimum brightness to be displayed on this channel; if the incoming colour is darker than this then display this brightness.

[light]
name light00
color red arduino 1
color green arduino 2
color blue arduino 3
vscan 94 100
hscan 94 100

This defines which area of the screen is assigned to which LED. The name is a unique name for each LED. The three colour lines define which colours the LED can display, which device the LED is attached to and the order of each colour component in the chain.

vscan and hscan define which area of the screen to average for that LED. 100% for the vscan is the bottom of the screen, and 100% for hscan is the right of the screen. In this case, the LED is matching the bottom right corner of the screen.

 

Testing it out

At this point, it should be possible to test out the ambilight system! The first test is displaying constant colours, using the boblight-constant client, which takes one argument. This is a hex string representing the RGB colour value to display.

First, start the boblight server

$ boblightd &

Then try each of these commands in turn (ctrl+c to quit)

$ boblight-constant FF0000

$ boblight-constant 00FF00

$ boblight-constant 0000FF

If you run these commands in order the LED strip should turn red, then blue, then green. Lastly

$ boblight-constant FFFFFF

should be pure white. If all of these work, it is time to test the screen-following client. This is called boblight-x11. A test command line is:
$ DISPLAY=:0.0 boblight-x11 -i v1 -o value=1.5 -o speed=100

If you’ve done everything correctly (and the planets are aligned just right), the LED lights should be following the edges of the screen. You can play with the config options to see what looks best for you (speed controls how long the averaging window the client uses is, value is a brightness multiplier, and adding -o saturation=x makes the colours more vivid).

I use VDPAU with MythTV and found that I needed to start it up with the environment variable VDPAU_NVIDIA_NO_OVERLAY=1 set. This makes boblight work with MythTV but sadly causes quite a bit of tearing. If anyone knows of a solution to this problem, I would be very grateful.

A little more control

This basic system works well when just watching TV, but I felt that there were a few improvements to be made. For instance, when you pause the TV and the screen goes blank, you lose the lights. Often you pause the TV because you want to get up and do something so leaving you in the dark isn’t ideal. To get around this problem, I wrote some software which allowed me to control which boblight client was running by echoing values to a file. This allowed central process management to keep track of which client is running and make it easy for various applications to interact with it.

The source for this system can be found here and it is compiled with the command

$ gcc boblight_notify.c -o boblight_notify

To run it, move the executable to a directory that allows the current user to create new files then run the executable. For example:

$ mkdir ~/boblight_manager

$ mv boblight_notify ~/boblight_manager

$ cd boblight_manager

$ DISPLAY=:0.0 ./boblight_notify &

To test that this is working, open a new terminal and run

$ echo 95 > ~/boblight_manager/tv

This should start screen-follow mode, with the speed set to 95. The other commands that should work with your current setup are:

$ echo [hex RGB colour] >~/boblight_manager/static

$ echo 1 > ~/boblight_manager/lock Forces the lights to stay in the current mode

$ echo 0 > ~/boblight_manager/lock Allows the lights to change mode again

$ echo off > ~/boblight_manager/off Kills all clients currently running

$ echo [text] > ~/boblight_manager/warn Makes the lights flash brightly 5 times while displaying text on the screen with notify-send (this seems to be buggy right now – I’ll try to fix it)

The other commands supported in the source file work with a client that I wrote, which I hope to be able to release the source for shortly.

I have used this control system with MythTV’s system events, so that whenever playback is started, stopped, paused or unpaused the appropriate command is executed to either start tv mode, or display a static white colour. I have also developed a web interface to allow control of the lights remotely. This requires a working apache+PHP install, and the source can be found here

Ambilight Clone

Ambilight “ generates light effects around the TV that correspond to the video content”. It was developed by Phillips around 2002. Simply put, the system takes the colours at the edge of the TV screen, and re-projects the colours on the wall behind.

Ambilight-3

 (not my TV/picture)

Previously I had found that watching television in a dark room could cause some eye strain due to the contrast between the bright television and the almost black wall behind it. My first solution to this was to place a desk lamp behind the TV, pointing at the wall behind it. This improved the eye strain, but wasn’t always best suited to the content being displayed on the TV. First, it was at a constant brightness. While the TV may have been displaying a very dark scene the back lighting would drown out the image. Secondly, it was a fixed warm-white colour, which didn’t really match what was playing unless the program was set outside in the daytime with good weather .

As a solution to this, I decided to build an Ambilight clone. This allows the back-lighting to match the content displayed on the TV in both colour and brightness, reducing eye strain and improving immersion (at least, that is what I hoped). As the majority of the content I play on the TV comes from my MythTV frontend and intercepting and decoding a HDMI signal is non-trivial, I decided to look for a method that would allow me to grab the framebuffer from the frontend and send data from that to the LED lights.

 

Hardware

The hardware requirements for the system I built are relatively modest. Due to the ease of setup/lack of wiring required, I decided to use a WS2801-based LED strip, which allows the colour of each RGB LED in the strip to be independently set using only two wires from an arduino. The strips I went with were these:

 

(available from here in the US)

I ordered two strips (2m, 64 RGB LED clusters), which came with enough connectors to join them together and to wire up to the Arduino / power without any soldering required. 2m is about the perfect length to cover the sides and top of  a 42″ TV, and 64 RGB LEDs is starting to approach the limit for how quickly you can pipe data to the Arduino @ 60 fps. These strips can be cut every 10cm or so to allow for smaller dimensions, although this requires some soldering ability, a sharp knife and some extra wiring and/or connectors.

I used an Arduino I had lying around to drive the LEDs. It was an ATmega328p-based  Duemilanove . An Arduino like this would be the ‘modern’ equivalent.

The LED strips I used required about 1.8A/m @ 5V (so 3.6A total). I ordered this power supply to power the LED strips (the Arduino pulls power from the USB connection).

 

Putting it together

  1. Attaching the strips to the TV. I found that for my size of TV (42″), 2m of LED strips almost exactly fills 3 sides of the screen (I didn’t place any LEDs along the bottom because they would be hidden by the stand). Luckily, the strips are flexible enough that I could bend them through 90° so that each strip covers one side and half of the top of the screen. Make note of the direction of the arrows on the strip, and place the start of the arrow closest to where the Arduino will be placed. The strips do have a sticky backing, but I decided not to use this and use sellotape instead, to allow for easier repositioning of the strips if required.

  2. Connecting the strips to the Arduino. As the power for the strips is coming from a different source than the power to the Arduino, I connected the ground (black) wire from the 4-pin connector on the strip to the ground on the Arduino to tie the two together. I attached the red lead from the cable to pin 2 of the Arduino, and the green lead to pin 4. I did not connect the +5v (blue) wire to anything.

  3. Power to the strip. This is done via the 2-pin connector. You can safely power 2m of strips without having to re-inject power at the start of the second strip, but it may be necessary to investigate more power wiring for longer strips.

  4. Connect the Arduino to the MythTV frontend via USB.

The total cost of these components was somewhere in the region of £120 (not including delivery). I did by some crimps/longer wiring in anticipation of having to splice strips together and make my own cables, but a couple of spare connectors were provided in the box which were all I needed to connect everything together.

A word of warningthe PSU I chose doesn’t guard the live mains power connections particularly well. While it shouldn’t be possible to give yourself an electric shock without a small amount of fiddling/poking (there is a plastic cover over the mains wire connection), it would be advisable to find an alternative housing for the project if there is any chance of pets/children getting anywhere near it. Any suggestions for a project housing which would require minimal/no cutting or drilling would be appreciated.

Software

Written up here

The finished product

I have an early video of my Ambilight clone, just after it was initially set up. At this stage there was a bug in the setup which meant there was a lag in updating the RGB lights. I also hadn’t finished implementing all of the modes in my boblight client, and the saturation / brightness were set higher than I have them today. Another thing to note is that cameras do not cope well with the dynamic range required of them to take video of bright LEDs in a dark room; the lighting is more subtle in-person.