If I want to use an Atmolight this is a problem. Lights behind the TV that change color require a cable to the computer. They also require a power supply and, apparently, quite an extensive and expensive list of parts. My other problem is that the IR remote receiver plugged into my computer is just above the floor, and the receiver keeps getting covered by the rug.
My solution is an Atmolight clone controlled by Bluetooth. It draws power for the chip from USB (so can be powered by the USB sockets on the TV) with a separate supply to power the LEDs. When done it will relay IR commands from its built-in IR receiver to the computer via Bluetooth. Atmolight was a DIY version of the orginal Philips Ambilight, so as this is a Bluetooth version I have therefore christened it "Bambilight" and take childish pleasure in trampling over not one but two trademarks.
Parts
- 1 x Teensy 2.0. I love this board, it's simple to use, well documented and cheap for what it does.
- 1 x BTM-400 Bluetooth module, with breakout board. Optional - the board and code can also communicate over USB
- 2 x ULN2803 octal Darlington array in DIL package
- 5m roll of SMD RGB LEDs.
- 1 x Infrared photo-detector.
- Some PCB Sockets and pins.
- A 12V power supply and matching PCB mountable socket. You probably want 2.1mm, which seems to be the standard for 12V power
- Copper PCB for etching, the final board is about 70mm x 40mm
Design
I designed the board in Eagle, which took me a long time to get to grips with - I'm still not 100% satisfied with it, but you can download the board, Eagle schematic and source code from this link. My first etch had holes that were too small, which was fixed with a re-edit in Photoshop. This gave me the chance to add some text, and a measurement bar - my second print effort failed after etching and drilling the board because the ****ing printer had been set to scale the image by not enough to be obvious, but just enough to be useless.I ended up printing to plain paper, verifying the size then photocopying onto transparency acetate. The image is at 600dpi and the text is flipped horizontally - put it this way up on your lightbox with the photosensitive copper board on top and it will etch the right way round. Something I learned after my first print effort.
Build
The Bluetooth chip is an SMD board and is optionally supplied with a breakout board. This had pins wired horizontally, which is really annoying, so I unsoldered and replaced with pins that point down from the board. I then drilled the board - I can't imagine doing this without a 0.7mm bit, a Dremel and a Dremel drill press as lining these up by hand would be impossible. The bit will self-align to the stripped hole in the middle of each solder pad, so it's not as daunting as it first appears. The Jellybaby is for sizing, I didn't have any coins.Once drilled I ran three wires on the top of the board as indicated by the red lines on the photo - here's the top view. Then started soldering the components, cheap bits first. Watch the orientation of the darlington arrays. Another lesson I learned shortly after switching the board design to using a 12V strip of leds is that it's much easier to solder a socket than to try then fail to desolder your expensive IC.
Here's the board with the Teensy and Bluetooth boards in place. The yellow linking wire on top saved me some hairy routing below - it connects Teensy pin B0 with the RESET pin on the Bluetooth module. I ate the Jellybaby.
LEDs and install
The LED strips are really easy to work with, each group of 3 is wired in series to run off 12V, so you can cut the strips after every 3 LEDs as needed. Solder wire terminated with a 4-pin header to each section, making sure to order the pins R, G, B and 12v. Then plug these into the headers on the board, with 12V towards the edge of the board. (I have double headers, a legacy of my first design. You don't need them). Then plug the board USB into a USB socket on your TV - any will do, it's only for 5V supply - and the 12V supply into the 2.1mm DC socket you can see poking out of the top-left of the board. Assuming you've programmed the Teensy you can then tuck this out of sight behind the TV.Software
Here's the code I uploaded to the Teensy (note this can be done before or after the chip is in place - progamming a Teensy is that easy). There are 12 LED channels plus IR and bluetooth control so I'm using just about every I/O pin on the board, and controlling the LED brightness by bit-bashing the PWM. This isn't pretty but it works.#include "IRremote.h" #define BLUETOOTH #define NUMCHANNELS 4 #define NUMLEDS (NUMCHANNELS*3) #define MODE_LEDON 0 #define MODE_LEDOFF 1 #define MODE_SLEEP 2 #define BUFLEN 32 #define IRTX 10 // C7 wired but not used #define IRRX 11 // D6 #define BTKEY 9 // C6 #define BTRESET 0 // B0 #define OUTPUTLOW0 15 // Set to input, wired to low byte pins[NUMLEDS] = { 19, 20, 21, // 1st clockwise from USB F4 F1 F0 18, 17, 16, // 2nd clockwise from USB F5 F6 F7 4, 5, 6, // 3rd clockwise from USB B7 D0 D1 3, 2, 1, // 4th clockwise from USB B3 B2 B1 }; byte rgb[NUMLEDS]; byte gamma[256]; float gammapower = 2.0; // LED brightness based on gamma = 2.0 byte count = 0, i = 0, buflength = 0; byte ledmode = MODE_LEDON; boolean debug = false; byte buf[BUFLEN]; decode_results results; IRrecv irrecv(IRRX); void dopwm(); void setrgb(byte *, byte); void readcommand(int); #ifdef BLUETOOTH void btcmd(HardwareSerial bt, char*msg); HardwareSerial bt = HardwareSerial(); #endif //------------------------------------------------------------------------------------ void setup() { for (int i=0;i<256;i++) { gamma[i] = (byte)(pow(i/255.0, gammapower) * 255 + 0.5); } Serial.begin(38400); for (int i=0;i<NUMLEDS;i++) { if (pins[i] < 255) { pinMode(pins[i], OUTPUT); digitalWrite(pins[i], HIGH); } } pinMode(OUTPUTLOW0, INPUT); pinMode(IRRX, INPUT); pinMode(BTKEY, OUTPUT); pinMode(BTRESET, OUTPUT); irrecv.enableIRIn(); irrecv.blink13(true); #ifdef BLUETOOTH // Reset BT device digitalWrite(BTRESET, LOW); delay(500); digitalWrite(BTRESET, HIGH); delay(500); digitalWrite(BTKEY, HIGH); delay(500); // Initialize, set name bt.begin(38400); bt.flush(); btcmd(bt, "AT+INIT"); btcmd(bt, "AT+NAME=Bambilight"); btcmd(bt, "AT+PSWD=0000"); // Enter BT slave mode digitalWrite(BTKEY, LOW); #endif // Initialize all LEDs to off for (int i=0;i<NUMLEDS;i++) { buf[i] = 0; } setrgb(buf, NUMLEDS); } void loop() { while (Serial.available()) { readcommand(Serial.read()); } #ifdef BLUETOOTH while (bt.available()) { readcommand(bt.read()); } #endif if (irrecv.decode(&results)) { // Not currently used, need to patch boblightd first irrecv.resume(); } dopwm(); } // Read command from "buf", which could be set from BT or USB serial void readcommand(int v) { if (i != 0 || v == 255) { buf[i] = v; if (buflength !=0 && (i == buflength || i == BUFLEN-1)) { if (buf[3] == 15 || buf[3] == 12 || buf[3] == 9 || buf[3] == 3) { // SETRGB setrgb(buf + 4, buf[3]); } i = 0; } else { if (i == 3 && v < 16) { // SETRGB buflength = v + 3; } i++; } } if (debug) { Serial.print("read "); Serial.print(v); Serial.print(" @"); Serial.println((int)i); } } // Set the RGB value for the LEDS - b is array of "numleds" values // from 0 (off) to 255 (full). void setrgb(byte* b, byte numleds) { int i; for (i=0;i<numleds;i++) { rgb[i] = gamma[b[i]]; } for (i=numleds;i<NUMLEDS;i++) { rgb[i] = 0; } } // PWM the led bits. for each x=rgb[i], pin is on from 0..x and off from x+1..255 // count is unsigned byte so wraps at 255. Called in busy loop so nothing complex. void dopwm() { for (int i=0;i<NUMLEDS;i++) { if (pins[i] < 255) { byte val = rgb[i]; if (ledmode == MODE_LEDON && count == 0 && val != 0) { digitalWrite(pins[i], HIGH); } else if (ledmode != MODE_LEDON || (count == val + 1)) { digitalWrite(pins[i], LOW); } } } count++; } #ifdef BLUETOOTH void btcmd(HardwareSerial bt, char *msg) { if (debug) { Serial.print("Sending '"); Serial.print(msg); Serial.println("'"); } bt.print(msg); bt.write(13); bt.write(10); int v, j = 0; while ((v=bt.read()) != 10) { if (v >= 0) { buf[j++] = (byte)v; } } buf[j] = 0; delay(100); // I found I needed this to work reliably. } #endifOr click here to download with a Makefile (which works on OS X and should work on Linux too). "make upload" to upload via the normal Teensy Uploader.
The LEDs are controlled using the Atmolight protocol, which is spoken by Boblight: install this on your Linux box, connect to the Bluetooth chip using
bluez-simple-agent
and rfcomm bind
as described here, then setup the following in /etc/boblight.conf
[global] interface 127.0.0.1 port 19333 [device] name bambilight output /dev/rfcomm0 channels 12 type atmo interval 40000 rate 9600 delayafteropen 1000000 [color] name red rgb FF0000 [color] name green rgb 00FF00 [color] name blue rgb 0000FF [light] name top color red bambilight 1 color green bambilight 2 color blue bambilight 3 hscan 0 100 vscan 0 50 [light] name right color red bambilight 4 color green bambilight 5 color blue bambilight 6 hscan 50 100 vscan 0 100 [light] name bottom color red bambilight 7 color green bambilight 8 color blue bambilight 9 hscan 0 100 vscan 50 100 [light] name left color red bambilight 10 color green bambilight 11 color blue bambilight 12 hscan 0 50 vscan 0 100
XBMC
Nothing to it. Install the XBMC Boblight addon, run boblightd, XBMC will automatically find it and, er, Bob's your uncle.Notes
- Unlike here we're configuring the bluetooth chip directly. Just trying to run the commands in sequence failed, the chip seems to need time to respond. I've catered for this by adding delays - 500ms during reset, 500ms after, then 100ms after each command. This works, it may be more conservative than necessary.
- The Bambilight can be controlled via Bluetooth or via USB - if no bluetooth is required, drop that chip from the circuit and don't #define BLUETOOTH in the source code.
- There is an occasional brief flicker from the LEDs, say one every 5-10 minutes for a few ms of a second. No doubt this is down to my cheap bit-banging approach, but it's barely noticable and (for me) not a problem.
- The IR receiver is wired in and should work in theory (I'm having trouble with the RC-6 protocol used by my remote, the others seem to work) but boblightd needs to be patched to relay the response from the device to the Linux IR subsystem. Patching boblightd looks relatively simple, but I don't know how Linux talks to the IR system, particularly as it changed recently. So this part of the project on hold.
- For my own record, this build required: 3 attempts to build UV LED-based PCB etcher, 4 main PCB boards (1 backwards, 1 misscaled, 1 running LEDs off 5V and final one), 2 Teensys (blew first one up desoldering from board 3), 4 Darlingtons (blew two up on board 3), 12 LEDs & resistors (discarded for SMD roll after board 3).
awesome!
ReplyDelete**hi, i'm French so sorry for ma bad english ;s
ReplyDeleteI'm looking for ambilight for poor people XD, and i was interresting by your work. If I understand all in your test you have 5M of led ? oO near than 1 metter by side of the TV ? For this coast ?
Can you send me an email i have some questions to give for you if you can spend some time for me :)**cheers from France ! my mail:
mistralbreton@yahoo.fr
Next time you decide to run cables behind a wall, consider installing an adequate-sized plastic conduit instead, since that will allow you to add and remove cables as needs and technology change.
ReplyDeletei know this post is years old, but do you think a bluefruit would work in this usecase?
ReplyDeletehttps://www.adafruit.com/products/2829