Ambient Lighting is really nice – and supposed to be healthy for your eyes as well!
(By Stephan Legachev (Own work) [CC BY 3.0 (http://creativecommons.org/licenses/by/3.0)], via Wikimedia Commons)
E.g. Phillips sells it as Ambilight for their TVs and there’s also many KITS on the internet that help you implement ambient lighting for your TV.
Fortunately but in this case UN-fortunately I have a projector at home – watching all my favorite DVDs, movies & clips from an attached laptop. So how to do ambient lighting then?
Turns out it’s really easy..
Required Parts & Cost
- Adafruit NeoPixel RGB LED Strip – starts at ~18$ / meter for cheaper clones, with 3 PINS (5V+,DIN, GND)
- Arduino UNO / Genuino UNO – ~ 25$
- 370 Ohm Resistor (~1$)
- 100 µF Capacitor (~1$)
- 3-Pin Cable (~1$ / meter)
- DC Barrel Jack Adapter (~2 $)
Basic Wiring & Architecture
The PC is running our C# based ScreenRipper software – aka. the “SENDER”. It constantly takes screenshots every 500ms and analyzes the colors of the screen. It down-samples the colors on the edges of the screen, so the amount of pixels fits the amount of LEDs on the strip. Here’s a sample how the down-sampled version might look like for a website for instance…
Once the colors are analyzed, they’re being sent to the Arduino via it’s USB port – via the C# Serial Port.
On the Arduino Pin 6 is being used to communicate via PWM with the LED Strip.
Wiring up the LED Strip..
- 5V+ to the (+) of the power supply
- GND to the (-)/ground of the power supply as well as GND of Arduino
- DIN – “Data In” to PIN 6 of Arduino
- Include a 1000 µF Capacitor between (+) and (-) of the LED Strip
- Include a 500 Ohm Resistor on the DIN cable – as close to the LED Strip as possible
- I’ve used a DC Jack Barrel Adapter for the connection to the standard power supply
I seriously recommend reading the Adafruit NeoPixel Guide, which talks about why you need a capacity & resistor as well as other important tips for wiring up the NeoPixels or compatible devices.
Arduino Software with FIRMATA
Now the wiring is done, let’s start with the software for the Arduino.
After playing around for a while with hardcore Arduino code, Josh Holmes on my team pointed me at FIRMATA.
That’s a protocol to control all Arduino Pins via Serial Port from another device.
This is *absolutely* the right thing for this project.. Because of the screen ripping it requires a PC anyways, so I saved a lot of time on coding for Arduino, instead wrote all the logic on the PC and had it “remotely” use Arduino’s Pin 6 via Firmata. There’s a branch of FIRMATA, that already has support for the NeoPixel Library from Adafruit in.
Here’s the steps to get Firmata on the Arduino
- Download the latest Arduino Software
- Download the “NodePixel” project – the FIRMATA for NeoPixel
- Open “node_pixel_firmata.ino” in the subfolder “firmware/build/node_pixel_firmata/”
- Press the 2nd button (upload)
- Wait for the upload to finish… voila!
C# Sender
The Arduino is all wired, setup and plugged in to your PC’s serial port.
Next get the source code of the C# Sender Application from my Github Repo.
I’m using the SolidSoils Arduino Library from Github – which covers basic FIRMATA connectivity from within C#. On top of it I’ve implemented support for the NeoPixel LED Strip specific commands. This is through the class NeoPixelArduinoSession, that implements INeoPixelProtocol:
namespace Knom.AmbiLight.NeoPixelFirmata { public interface INeoPixelProtocol { void Init(IEnumerable<Strip> strips); void SetPixel(byte address, int color); void Show(); void SetColor(int color); } }
The ScreenRipper project then does the rest…
- ScreenshotColorScanner: Has a timer that constantly takes the screenshot. It then crops black borders and “pixelates” / down samples the colors. At the end an event is fired.
- ArduinoLcdColorWriter: Listens to the event and sends the colors via INeoPixelProtocol to the Arduino.
- DebugColorWriter: Creates the pixelated preview image shown above called “screen.png”– which can be helpful for debugging.
Now.. Compile & RUN the Knom.AmbiLight.ScreenRipper.exe.
A little Icon will show up in your taskbar tray.
Double clicking on it will toggle visibility of the preview bitmap – screen.png on your screen.
Also you can open Knom.AmbiLight.ScreenRipper.exe.config and fine-tune some of the settings being used..
<appSettings> <add key="debugImages" value="true"/> <add key="interval" value="500"/> <add key="xPixels" value="60"/> <add key="yPixels" value="45"/> <add key="scanPixelSteps" value="2"/> <add key="scanMinColorThreshold" value="25"/> <add key="scanMarginRatio" value ="0.2"/> <add key="comPort" value="auto"/> <add key="comBaudRate" value="9600"/> </appSettings>
Key | Description |
debugImages | Turn the screeen.png debug image on/off |
interval | The capturing interval for the screenshot in milliseconds. |
xPixels | How many LEDS/Pixels do you have on the X Axis (count!) |
yPixels | How my Pixels on the Y-Axis. The overall Pixels is X-Axis + Y-Axis * 2 E.g. in sample case a 150 LEDs strip |
scanPixelSteps | Make down sampling faster, by skipping every N pixels. Default is 2. |
scanMinColorThreshold | If the color has less than N as a value, it’s going to be left 0. This is to brighten up colors. |
scanMarginRatio | What’s the percentage of the screen that’s considered as the relevant margin for the color calculation. Default: 0.2 = 20% |
comPort | By default all Com Ports will be searched for. You can also set it to e.g. Com3 explicitly. Default: Auto |
comBaudRate | Only change this, if you also modified the FIRMATA. Default:9600 |