Skip to content
Synless edited this page Dec 28, 2021 · 11 revisions

Welcome to the SynLight wiki !

Presentation

Ambient lighting system for Windows

This program is written in C# using the MVVM architecture as part of my coding learning.

On the computer side, it processes screenshots and sends data to a NodeMCU microcontroller (ESP8266 based) via Wifi (UDP). The microcontroller then drive individually addressable RGB LEDs behind a screen, to match the color of the edges of the screenshot. A level shifter is highly advised to step up the 3.3V signal coming out of the microcontroller to a 5V signal for the LED strip. Not using one could lead to flickering colors or even the setup not working at all.

For this project, I used a NodeMCU microcontroller for its embedded WiFi module, receiving data via UDP on my local network. After experimenting with the Adafruit version of the Philips Ambilight, I decided to write my own piece of code to add several features :

  1. Support for 21:9 content on 16:9 screen, black bars management.
  2. Network data transfer, driver-less and wireless method.
  3. On the fly configuration, while running.
  4. Optimization and extra features.
  5. Can run totally in background.

Requirements

  • Having some experience with WS2812B (Neopixel) and the Arduino environment is highly recommended.
  • To run the program you need the .net Framework 4.5 or higher.
  • To modify the code, Microsoft Visual Studio 2017 or higher.

Arduino dependencies :

Note : I had problem uploading sketches to the nodeMCU with some USB 2.0 ports as well as having it to work properly. This has been solved by using USB 3.0. The whole hardware was meant to be powered by a single USB3.0 port, therefor the LEDs are dimmed on the Arduino side. Remove this software protection only if you are using a power supply or if the size of your setup is really small.


How it works :

On the PC side :

  • Taking a screenshot and store it as a Bitmap object.

Size Screen = new Size(PrimaryScreenWidth, PrimaryScreenHeight);

Graphics gfxScreenshot = Graphics.FromImage(bmpScreenshot);

gfxScreenshot.CopyFromScreen(0, 0, 0, 0, Screen);

It should be noted that the .Net API provides a method to get the OS front screen but no further, running a game in fullscreen mode will results in a black screenshot and switched-off LEDs. Grabbing the GPU video buffer directly may be added in the future. Other contents run fine without video stuttering, with every type of vertical synchronization.

2019/10 - UPDATE : It seams to be working on the latest revision of Windows 10.

  • Creating a new Bitmap from the main screenshot, with a size matching the number of LEDs in X and Y.

scaledBmpScreenshot = new Bitmap(bmpScreenshot, Width, Height);

  • Scanning through the scaledBmpScreenshot according to the first LED position and the direction of rotation, and fills the data with bytes corresponding to the red, green and blue value of every edge pixels.

  • Sending to the microcontroller using Socket.SendTo(dataAsByteArray,new IPEndPoint(IP,port));

On the NodeMCU side :

  • Connecting to a network

WiFi.begin(ssid, password);

  • Starting to listen to a defined port (this port matches the one the C# program is sending to)

UDP.begin(localPort);

  • Looping on reading the incoming UPD packets

UDP.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);

  • Scanning the packetBuffer array. The N-bytes is for red, the N+1 bytes is for green, and N+2 bytes is for blue of each LED.
Clone this wiki locally