Ambilight clone using WS2812B LEDs -- build log - Page 1
Forum section: electronics / projects

author: tom66
author_rank: Super Contributor
timestamp: June 18, 2014, 06:02:47 pm
content: OutlineMy project of the month will complement my new TV. Philips TVs have "Ambilight" - a somewhat over-done but nice feature if used on certain films. Essentially Ambilight follows the picture content with a series of LEDs around the TV's frame. This lights up the wall behind the TV. It's only commercially available for Philips TVs - and they never made decent plasmas. It will be going with my Pioneer Kuro...Size and quantity of LEDsInitial calculations: The TV screen area is about 45 inches wide and 24 inches tall (16:9 ratio, 50" panel.) I want to surround the whole frame, top, bottom, left and right, although I only will cover the active picture area as the Kuro has a relatively thin bezel. I will be going with a density of 60 LEDs/m and using WS2812B RGB LEDs (these LEDs are serial-addressed LEDs, which means that each pixel can be independently controlled.)A quick calculation shows I need to cover 3.5 meters, so I will buy 4 meters of 60xLED/m strip (from Seeedstudio, about $67, or ~£44.)This will be a total of 210 individual point sources of light.Power requirementsA rough initial estimate of current consumption from the sparse documentation on these LEDs says 60mA/LED for full white, so the total load at full white x 210 will be 12.6 amps, or 63 watts on 5V rail.Time to get some LEDs... I bought a small "sample" bunch of 10 WS2812B (eBay #121347733196), and connected them in series using 0.1" headers. I then used some example code for a TM4C123GH6PM launchpad (Tiva launchpad) to give it a quick spin... They work great, although I broke one LED whilst soldering. 9 LEDs at full white initially used 385mA, or about 43mA/LED at 5V supply. However the white had a fairly noticeable blue tint, so I played with running the blue LED at about 75% that of the red and green LEDs. This worked quite well for a neutral white point, and reduced the full white current to 35mA/LED plus made the LEDs run cooler. Even at this low current, the LEDs are very bright - almost too bright to look at for any long period of time - and more than bright enough for an Ambilight effect.This change in power consumption means I need to supply 5V at 7.35A now, or 36 watts. One of the other things I noticed is that the LEDs would work just fine on about 3.75V with no change in brightness except at full white, where I had to increase the supply to about 4.25V to avoid a yellow tint. I could possibly control the power supply so that we constantly track the LED display status and try to operate at the minimum supply voltage. Not only would this reduce heating in the LEDs, improving their longevity, it would also improve the energy efficiency. Running at 4.25V even continuously chops off another 5 watts.Full load will be rare (most of the time I imagine sitting somewhere between 5 and 15W of load, which would be 50~150% total intensity on across three colours per LED) but I need it to be able to run continuously just in case.LED quiescent current is about 800uA at 5V, so 0.84W in dark scenes with all 210 running. The power supply needs to be able to cope with a rapid load shift from 0.84W to ~30W in one single frame (60Hz maximum, it will have less than 1/10th a frame or about 1.6ms to cope with this swing, including any voltage tracking.) That should be an interesting challenge. Since each LED "free-runs" at about 450Hz +/-50Hz, I can rely on running ripple current being relatively low. They will not begin PWM cycles at the same time.Logic levelsThe WS2812B are rated for 3.5V at 5V supply. I found that at 5.2V DC, the strip would receive commands incorrectly (garbage instead of correct colours, or not updating) from a 3.3V MCU. Therefore logic level translation will be necessary, especially if the strip voltage is to rapidly modulate. I will use a logic buffer IC.

author: tom66
author_rank: Super Contributor
timestamp: June 18, 2014, 06:35:03 pm
content: ControllerI will design the controller PCB to accept a DC input of 11~14V. From that it needs to supply the 3.5~4.3V @ 7.5A for the LEDs. It will also have the video processing logic on it. The video processing logic will require +/-5V and 3.3V analog supplies at about 40mA each. The microcontroller needs about 80mA at 3.3V. I will also use a Noritake VFD for debugging and test -- though it might make it into the final product. It will require 5V at 300mA. I've no case in mind - I'll probably just get a bit of acrylic laser cut and mount it on that below the TV. I figure the maximum DC current will be about 3.5A at 11V in, I'll probably power it from a 12V brick.FPGAs are still new to me, and HDMI is a bit of a beast of a protocol plus will usually require an expensive PCB to use. I will be using VGA for the video input. This is fairly simple to understand, can be captured using a simple microcontroller, and my media PC, the source of almost all content displayed has a VGA port. For future use, I will want to add support for games consoles and OTA TV, so I will build a second revision with a HDMI port - or perhaps some plug in module for the current board. Alternatively I could also invest in a HDCP stripper and capture the HDMI video straight out of my AVR.Maximum video input will be 1920x1080p at 60Hz which is a pixel clock of 165 MHz although the typical input will be 24Hz cinema video. I will be sampling at up to 2 MHz on this signal using sample and hold buffers to capture small area averages. I figure one possible way would be to capture a random scattering of pixels underneath each LED area. I could also do the capture deterministically on specific known pixels, making sure to get sufficient averages for each LED pixel. To simplify processing, I could compute only every 2nd LED, with the LED in between the two representing some kind of average, though if I can I'd like to avoid this. All video data to be captured on each VGA HSYNC. By counting HSYNC and VSYNC, it will be very easy to know what line we are on, and VGA is fairly clean for pixel timings, so we can probably get down to the resolution of about 5 pixels. I don't need pixel perfection. Interlaced video doesn't need to be supported.I'll put an EDID EEPROM on the board for the PC to ID the widget - I'll copy the data my Kuro reports in a hope that this will keep the timings identical for both.I'll also give the board an audio input so it can work in a solo manner with just an audio source and play patterns related to the music.I use XBMC for my media PC. It's set up to change the display refresh rate to match the content. This is one easy way to detect if the content changes - with this I can set up a routine to look for 21:9 or 16:9 content and adjust the LED behaviour respectively (21:9 would dim the top and bottom LEDs.)Data wise, I want each of the 210 LEDs to be able to accept an independent intensity level in R, G and B. Internally I will be using 12-bit data (the reason will become clear later.) The frame rate needs to be at least 60Hz, but ideally would be much higher- about 240Hz. From measurement of the current test board, it takes 277us to write 9 LEDs, so a reasonable estimate will be 6.46ms for 210 LEDs, excluding calculation time. I will therefore split the LED branches into two halves of 105 LEDs so the write time is shortened to about 3.2ms.Memory wise, about 6 bytes are required per pixel (because 12-bit data), plus the SPI data generation requires another 9 bytes per pixel. Total memory ~3150 bytes - no problem for a TM4C123GH6PM with 32K of SRAM. With up to 10 subframes though, I might end up using another ~16.5K (I will need to buffer all 10 subframes per real video frame.)Gamma Correction, Dithering, SubframesThe WS2812B LEDs only use 8-bit PWM, but that has poor low level detail. Plus, I need to gamma correct it by applying a CIE luminance curve. This reduces the effective video bits to about 6 bits, which is pretty poor. In particular on dark shades you can see an obvious stair-stepping effect and colour resolution is poor at low levels.One solution is to use dithering - flicker the LED quickly between the two closest levels. This technique is also used by plasma displays, and when done correctly is essentially unnoticeable. Initially, I tried dithering with a PRNG - but the results were poor. The flicker is obvious. I then tried using dithering with a deterministic pattern - I made a few bit shift patterns which maximised available flicker frequency. This works surprisingly well - the human eye is good at integrating very short brightness events. I use 16 periods per frame for a prototype but in the real version I will switch to 4 periods per frame (for 60Hz) and 10 periods per frame (for 24Hz Cinema.) The increased effective bit depth for cinema viewing is nice and the dither rate will be about 240Hz so should be completely unnoticeable. The 12-bit gamma corrected data (from 8-bit linear source video) allows for up to 16 dither frames although that would be difficult to implement, so the dithering will be spread across different real frames, and spatially translated amongst each LED - so the LED dither pattern is constantly moving around making it even harder to perceive.

author: tom66
author_rank: Super Contributor
timestamp: August 23, 2014, 04:09:30 pm
content: OK, got a bit sidetracked, but I'm moving forward now on this project.Some changes:PowerI've changed the LED power supply to two 3.5~5V @ 3.9A outputs. Two outputs chosen to simplify the power design. I chose an integrated IC, TPS56628, which is a 6A device. The full white current is 3.9A and the average current will be around 1/3rd to 2/3rds this. The supply needs to handle a load transient from 0A to 3.9A (with output slewing from 3.5 to 5V) at 30Hz. To help with this, I have added some additional bulk capacitance on the output. Two channels are run independently, allowing each 105 LED channel to have a different supply voltage. This helps reduce power dissipation further, because there is more flexibility over the LED control.The power supply for the logic is +3V3(DIG), +5V(DIG), +5V(ANA) and -5V(ANA). The negative 5V analog is derived from a chargepump and 7905 on the main 5V converter. The positive 5V analog is derived via straight 7805 from the 12V input. The 5V converter supplies up to 1 amp at 5VDC (expected 550mA max) and is implemented by a TPS54331. The 3.3V is linear regulated from the 5V digital rail.Power budget:+5VDIG 550mA+3V3DIG 150mA-5VANA 50mA+5VANA 65mAMCU changeI've changed to an STM32F407 because of additional memory requirements, faster clock speed, and a faster ADC. The faster ADC has enabled me to ditch the sample and hold circuit entirely; it can sample at 2MHz over 3 independent channels and I use the ADC's internal S&H buffer. The only input requirement is a buffer amplifier.I've added a VGA passthrough output for debugging only. I will probably not need it but I had the board space.YPbPr supportI've added YPbPr support in the form of a 3.5mm connector, as I would also like to connect this to an older Xbox 360 console. However, I have decided the V2 digital model will be HDMI only. This is more of a proof of concept. There is also a YPbPr passthrough connector available.I've sent the board off to Seeed Studio along with an order for some LEDs. I'll see how it goes and will update. Will release design files when all tested and complete.It's a 2 layer board, 99 mm x 95 mm with 7/7 track/gap. Double sided load but only a few passives on the bottom.

author: Prime73
author_rank: Regular Contributor
timestamp: August 23, 2014, 05:29:49 pm
content: I've done it using lpd 8806 leds and arduino board. really simple setup. Why complicate things with a custom controller, etc?www.youtube.com/embed/yFfqt2IE9TwQuote from: tom66 on June 18, 2014, 06:02:47 pm

author: tom66
author_rank: Super Contributor
timestamp: August 23, 2014, 05:48:45 pm
content: Because I can. It's an engineering challenge; yes, I could have built the board with only a USB port, but that would be no fun. Designing a moderately high power DC-DC converter is a challenge, as is putting it all together in an integrated system with a lot of analog processing. Version 2 will use a HDMI port which will enable any HD source (not just a PC) to work with it, this is a proof of concept for a future project, which may be done as a 3rd / 4th year project at my university. That will require a bit more R&D to implement...That Ambilight effect is pretty cool, too - how many LEDs did you use?

author: Prime73
author_rank: Regular Contributor
timestamp: August 23, 2014, 08:42:54 pm
content: Quote from: tom66 on August 23, 2014, 05:48:45 pmfair enoughHow do you plan to go around a broadcast flag (DRM thing) on HDMI? as far as I remember you can't capture video from most HDMI sourcesI've used 110 LEDs evenly spaced on all four sides of the tv (it's a 50" screen).

author: tom66
author_rank: Super Contributor
timestamp: August 23, 2014, 09:09:22 pm
content: All of my sources can have HDCP turned off. For example, the Xbox One and PS4 both allow HDCP to be turned off if Blu-Ray/Netflix are not played. My PC has a DVI port, with no HDCP support. HDCP is horrible - we have to do tons of testing on it at work - so I am working to avoid it as much as possible.I'm going with about double as many LEDs as your set up. I should also have some improved colour graduation with the dithering algorithms; effective colour depth close to 10 bit but with gamma correction, should be at least 8 bit. I do plan to play a bit with some algorithms for filtering LED speed (not decided on whether to rapidly change the LEDs or slowly change them) and also build in a bias light function to improve low light image contrast. Kuro plasmas do have very good contrast ratios, but the apparent contrast can be massively improved with bias lighting.

author: hamster_nz
author_rank: Super Contributor
timestamp: August 24, 2014, 09:12:54 pm
content: Quote from: tom66 on August 23, 2014, 05:48:45 pmStrangely enough I worked on two aligned projects this weekend that are aligned with yours:1. Powering up my $10 strip of WS2318B LEDs from Seeed Studio using an FPGA -2. I finally got an image through my 720p HDMI input for an FPGA - (Well, actually DVI-D through a HDMI plug ). Yet to iron out a few bugs, but it is now working.http://forum.gadgetfactory.net/index.php?/topic/2023-hdmi-input/page-2DVI-D Ambilight clone here I come???

author: tom66
author_rank: Super Contributor
timestamp: August 24, 2014, 09:32:38 pm
content: Neat! I didn't know you could do HDMI in on a Papilio! I'm quite surprised you can send HDMI data over a 0.1" header... Personally, I was going to use a device like ADV7619 and work with the raw YUV/RGB/YPbPr data. But if I can shove the HDMI straight into an FPGA, it would be simpler. The ADV7619 even supports HDCP (heh, cheap HDCP stripper?!) but I probably won't need that.Would that board be able to support 1080p60? Or is that asking too much? (ADV7619 can do 1080p60.)From what I've seen, 60 or more LEDs/m is the best effect for an Ambilight. Ideally, I'd go for 144 LEDs/m, but that would blow my budget somewhat. And it would be very power hungry, unless I limited the brightness to be about the same as 60 LEDs/m (1/2 the brightness.) It is on the list of ideas for V2 though.

author: hamster_nz
author_rank: Super Contributor
timestamp: August 24, 2014, 11:24:07 pm
content: Quote from: tom66 on August 24, 2014, 09:32:38 pmNobody is more surprised that it works than me - esp since the termination resistors are on the wing board, not next to the FPGA.The interface is good for 720p @ 60Hz (75MHz pixel clock, 750MHz bit clock per channel), or at least that is what I am working with. The Spartan 6 serialisers top out at about 1Gb/s, so 1080p is completely out of the question.If you like, I have 8 spare PCBs & parts kicking round in a shoe box. If you have a Papilio Pro I can toast one for you, test it and drop it in the post. I 'forgot' to connect 3V3 to the I2C level converter (for the EDID channel), but you are more than welcome to have one to play with.

author: tom66
author_rank: Super Contributor
timestamp: August 24, 2014, 11:42:02 pm
content: I appreciate the offer. At the moment, I don't yet have a Papilio (pro or otherwise), so I wouldn't need the adapter. But I will keep you in mind if I get one in future for development of version 2, when I will probably end up buying an FPGA board of some sort.It looks like I need to use a HDMI deserialiser chip for now, as it's the simplest way to support 1080p and HDCP (a bonus.)

author: tom66
author_rank: Super Contributor
timestamp: September 13, 2014, 10:03:35 pm
content: Well, lots of progress this week.I received my LEDs, my PCBs, and finally put my TV on the wall with the LEDs attached.I have done some initial tests with a Tiva launchpad and used USB to drive the strip (USB to USART on the launchpad, then converting this data to LED data, very limited but works for a quick test.) The final version will be using VGA only.Just waiting on parts to build the rev1 PCB.

author: tom66
author_rank: Super Contributor
timestamp: September 13, 2014, 10:59:31 pm
content: Quick demo video (Avatar)

author: SL4P
author_rank: Super Contributor
timestamp: September 13, 2014, 11:04:28 pm
content: Quote from: hamster_nz on August 24, 2014, 11:24:07 pmYou must be using that 'copper-free', liquid cooled Munster cable, which offsets the losses & crosstalk in the dodgy wiring & termination.

author: miguelvp
author_rank: Super Contributor
timestamp: September 13, 2014, 11:11:09 pm
content: Quote from: tom66 on September 13, 2014, 10:59:31 pmNice

author: tom66
author_rank: Super Contributor
timestamp: September 18, 2014, 07:22:42 pm
content: Build progress. Fair part of power supply section done.Messed up a pin out for a regulator, but fixable by using SOT89 instead of SOT223. The SOT89 will run much hotter, but I figured only about 15C for the original, so 45C J-A for this one. It's only regulating the 3.3V logic rail, at about 150mA maximum (100mA typical.)The 5V section of the PSU works, I get 4.9V (20k + 3k9, 0.8V vref). I will adjust resistor values for 5V, I made a round-off error in my calculation for the resistor divider.

author: tom66
author_rank: Super Contributor
timestamp: September 24, 2014, 09:03:00 am
content: First LED buck converter tested and working. Output voltage modulation also working great.Small concern with the buck converter falling output voltage waveform (the output voltage target is dropped.) It seems to do a very long OFF-time, with the output voltage sagging quickly - I suspect it is dumping the capacitor energy into the lower FET, which is something that might lead to early device failure. I might have to add some slew limiting on the falling edge, which can be accomplished in software or hardware.It can slew from minimum to maximum in just 150us and max to min in 1.5ms, well beyond my target. Rising edge begins to enter current limit, may have to limit slew rate there too.Definitely slight audible "click" on falling edge, probably due to long off time.Output voltage variable from ~2V to ~6V. I will be using ~2.5V to ~5.5V.1: Close up of falling output voltage and lower FET "off-time" (500mA load)2: Falling output voltage (500mA load)3: Rising output voltage (500mA load)4: Rising output voltage under light load (V/us virtually unchanged) (zero load)

author: Prime73
author_rank: Regular Contributor
timestamp: September 24, 2014, 01:15:29 pm
content: How you plan adjusting LEDs responsiveness (speed) to colours? also some other parameters like saturation, interpolation, etc would be useful as well. If you're not aware there is an XBMC plugin that works with ambilight ( the one I've build as an example) you can take a look at its settings and maybe get some ideas.

author: tom66
author_rank: Super Contributor
timestamp: September 24, 2014, 01:35:05 pm
content: There's a VFD on the board, and I have a remote control inputall of it will be fully configurable.I looked at boblight and used that for the demo/test. Problem is it can't do large area averages without using too much CPU. So it looks a bit rubbish to be honest. It picks up on single pixels only and this causes problems for fast moving scenes.

author: Prime73
author_rank: Regular Contributor
timestamp: September 24, 2014, 01:43:30 pm
content: Quote from: tom66 on September 24, 2014, 01:35:05 pmVery coolCan't wait to see a fully working prototype. I'm definitely going to build one for myself.and yes boblight eats up cpu quite a bit. I have mine setup to average 32x32 pixels to get an acceptable performance/ colours

author: tom66
author_rank: Super Contributor
timestamp: September 24, 2014, 05:25:38 pm
content: The problem I found with boblight (at least on my PC) was that going above more than about 4 pixels per LED (for just 72 LEDs along the top) made video at high bit rates judder. I could watch youtube etc but not much more. This was a modified version though with Python spitting out data over UART, so maybe that was a factor....Anyhow; I made an error with the design. Ugh. (Another one?) Well, two in fact. One, I got the SCR pin out wrong. Easy to correct, and it is only a protection device for the LED strip for OVP shunting. Got that working and tested, it trips at about 6.5V per channel. But the bad one was the buffers for the LED data. Now I am SURE I checked this before I sent off the PCBs but clearly I missed the fact that I got the footprint completely wrong! As a result I have had to do an ugly bodge and will have to build an external level shifter. I will not make this mistake in V2! (HDMI version)Found the negative 5V regulator (Taiwan Semiconductor 79M05, i.e. bog standard 79xx) to oscillate at about 90kHz with a 1uF output ceramic capacitor. Increased that to 2.2uF and oscillation stopped. Datasheet says more than 0.33uF but does not mention ultra low esr ceramic stability.Otherwise, board progress is good.

author: tom66
author_rank: Super Contributor
timestamp: October 02, 2014, 10:43:04 pm
content: Ok, lots of problems with the STM32F4 design section and running out of chips has meant I've decided at least for now to do all the development on an STM32F4 dev board with jumper wires over to the main board. I don't expect this will be permanent but I've grown a little frustrated with blowing up so many chips (and I'm not sure why!) so this is a quick solution.Got output voltage variation working, from about 15% to 37% PWM the output voltage varies from 6V to 1.8V. I don't need much resolution so this is fine.Original PWM of 40kHz caused controller to occasionally oscillate and lock onto 40kHz frequency causing very poor efficiency. Fixed that by increasing PWM frequency and RC time constant.Pictures:- 40kHz output modulation glitch (occurs once board warms up)- switch node modulation- close up of switch node modulation- opamp volt mod node command (too much ripple due to too low RC value, error in calculation)- low output modulation- high output modulation

author: tom66
author_rank: Super Contributor
timestamp: October 18, 2014, 11:49:32 pm
content: Progress is progress. Getting the VGA sync working and the WS2812B code for STM32F4 is pretty much finished now, so that's good. Projects always take far longer than you expect...Quick note; for VGA debugging, I've been mirroring screens off my laptop. But my laptop LCD is 1280x800 and I want to test it at 1920x1080p. It's actually possible to do this on Linux (X.org.) The laptop LCD displays at native and the VGA output is a scaled version of the laptop display (obviously interpolated.) This gets rid of the annoying missing desktop too...Here's how to do it, command line xrandr trick:Code:xrandr --output VGA1 --same-as LVDS1 --scale 0.667x0.740 --pos 0x0(substitute LVDS1 for the laptop screen name, and VGA1 for DVI1 or HDMI1 if necessary.)I'm not sure if this is possible on Windows, it probably is, but I haven't looked into it.In theory X would also let you have one monitor at a different frequency - I would guess it drops both to the lowest common frequency or makes one drop frames. Not tried that yet.