How to build an ambient light using C#, Arduino & NeoPixel

Estimated Reading Time: 4 minutes

Ambient Lighting is really nice – and supposed to be healthy for your eyes as well!

(By Stephan Legachev (Own work) [CC 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

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

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 image 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..

<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"/>

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.

Enjoy your ready to use Ambient Lighting!


Leave a Reply

Your email address will not be published. Required fields are marked *