Skip to content

support@quartzcomponents.com

Free Shipping Over INR 500

Electronics Projects

DIY Real-Time Ambient Lighting System Using Arduino Nano

by RISHABH JANGID 05 May 2026 0 Comments

Transform your PC setup into an immersive experience with this DIY Real-Time Ambient Lighting System. By syncing your monitor’s colors with a WS2812B LED strip, the lighting extends beyond the display and reacts instantly to on-screen content. This version uses an Arduino Nano with an improved Adalight implementation for better synchronization, data validation, and stability.

Prismatik Software (PC side)

This system uses Prismatik as the core PC-side engine. It captures real-time screen colors, maps them to LED zones, and streams RGB data to the Arduino using the Adalight protocol.

The software divides your screen into multiple regions and assigns each region to a specific LED. It continuously sends:

  • Header → "Ada"
  • LED Count → 2 bytes
  • Checksum → validation byte
  • RGB Payload → Full LED frame data

Download Prismatik:
https://github.com/psieg/Lightpack/releases

Components Required

About the Components

Arduino Nano

The microcontroller handles serial data from the PC and converts it into LED control signals with precise timing.

  • Operating Voltage: 5V
  • Input Voltage (VIN): 7V to 12V
  • Microcontroller: ATmega328P (8-bit AVR)
  • Clock Speed: 16 MHz
  • Flash Memory: 32 KB (2 KB used by bootloader)
  • SRAM / EEPROM: 2 KB / 1 KB
  • Digital I/O Pins: 14 (out of which 6 provide PWM output)
  • Analog Input Pins: 8 (10-bit resolution)

WS2812B LED Strip

Each LED is individually addressable, allowing exact color mapping from different regions of the screen.

  • Voltage: 5V DC (Highly sensitive to overvoltage)
  • LED Density: 60 LEDs per meter
  • Individually Addressable: Integrated driver in each LED
  • IP Rating: IP20 (Non-waterproof, for indoor use only)
  • Protocol: One-wire digital communication
  • Power Note: Significant power consumption at high brightness; requires a stable external supply.

Circuit Connection

Fig. CIrcuit Diagram

Fig Schemetic Diagram

Wiring Details

  • LED 5V → External Power Supply (+)
  • LED GND → Power Supply (-) & Arduino GND
  • LED DIN → Arduino Pin 6
  • USB → PC

Code Explanation

Library

#include <FastLED.h>
  • Provides low-level control for addressable LEDs
  • Handles timing-critical signal generation internally

Configuration

#define NUM_LEDS 65
#define DATA_PIN 6
#define serialRate 115200
  • NUM_LEDS → Total LEDs in strip
  • DATA_PIN → Pin used for LED data transmission
  • serialRate → Serial communication speed

Global Variables

uint8_t prefix[] = {'A', 'd', 'a'}, hi, lo, chk, i;
CRGB leds[NUM_LEDS];
  • prefix → Expected header sequence for synchronization
  • hi, lo → Incoming LED count bytes (protocol requirement)
  • chk → Checksum for packet validation
  • i → Shared loop index (used in header parsing)
  • leds[] → Buffer storing RGB values for entire strip

Setup Function

FastLED.addLeds(leds, NUM_LEDS);
  • Initializes LED strip driver
FastLED.showColor(CRGB(255, 0, 0)); delay(500);
FastLED.showColor(CRGB(0, 255, 0)); delay(500);
FastLED.showColor(CRGB(0, 0, 255)); delay(500);
FastLED.showColor(CRGB(0, 0, 0));
  • Startup diagnostic sequence
  • Confirms each color channel works
Serial.begin(serialRate);
Serial.print("Ada\n");
  • Starts serial communication
  • Sends readiness signal to host software

Adalight Packet Structure

  • Header → "Ada"
  • LED Count → 2 bytes (hi, lo)
  • Checksum → hi XOR lo XOR 0x55
  • Payload → RGB data (3 bytes × NUM_LEDS)

Main Loop Execution

1. Header Synchronization

for(i = 0; i < sizeof prefix; ++i)
  • Matches incoming serial bytes with "Ada"
  • waitLoop blocks until data is available
  • If mismatch occurs:
    • Resets index i = 0
    • Jumps back using goto waitLoop
  • Ensures exact alignment with packet start

2. Read Metadata

  • Reads hi, lo, and chk sequentially
  • Each read is blocking using while(!Serial.available())

3. Checksum Verification

if (chk != (hi ^ lo ^ 0x55))
  • Validates packet integrity
  • If invalid:
    • Resets parsing state
    • Jumps to waitLoop
    • Entire packet is discarded

4. Clear Frame Buffer

memset(leds, 0, NUM_LEDS * sizeof(struct CRGB));
  • Resets all LED values to zero
  • Prevents residual data artifacts

5. RGB Data Acquisition

for (uint8_t i = 0; i < NUM_LEDS; i++)
  • Iterates through all LEDs
  • Reads three bytes per LED:
    • Red
    • Green
    • Blue
  • Blocking reads ensure complete frame reception
  • Stores values directly into leds[] buffer

6. LED Output

FastLED.show();
  • Transfers buffer data to physical LEDs
  • All LEDs update simultaneously (frame-based rendering)

Control Flow Characteristics

  • Fully blocking design → waits for complete data before processing
  • goto waitLoop used for fast resynchronization
  • No partial updates → only valid frames are displayed
  • Header + checksum prevent drift and corruption

System Summary

Host software continuously streams LED color data using the Adalight protocol. The microcontroller enforces strict synchronization using header matching and checksum validation. Only verified frames are accepted, stored, and rendered in a single update cycle, ensuring stable, flicker-free ambient lighting output.

Result

The system successfully produces real-time ambient lighting that mirrors on-screen content with high accuracy and minimal latency.

  • LED colors dynamically match screen edges in real time
  • Smooth transitions with no visible flicker
  • Stable communication using Adalight protocol (no frame corruption)
  • Uniform brightness and consistent color output across the strip
  • Low latency response suitable for video, gaming, and general use

Checkout the full video tutorial:

Code

#include "FastLED.h"

#define NUM_LEDS 65
#define DATA_PIN 6
#define serialRate 115200

uint8_t prefix[] = {'A', 'd', 'a'}, hi, lo, chk, i;

CRGB leds[NUM_LEDS];

void setup() {
FastLED.addLeds(leds, NUM_LEDS);

FastLED.showColor(CRGB(255, 0, 0)); delay(500);
FastLED.showColor(CRGB(0, 255, 0)); delay(500);
FastLED.showColor(CRGB(0, 0, 255)); delay(500);
FastLED.showColor(CRGB(0, 0, 0));

Serial.begin(serialRate);
Serial.print("Ada\n");
}

void loop() {
for(i = 0; i < sizeof prefix; ++i) {
waitLoop: while (!Serial.available());
if(prefix[i] == Serial.read()) continue;
i = 0;
goto waitLoop;
}

while (!Serial.available());
hi = Serial.read();
while (!Serial.available());
lo = Serial.read();
while (!Serial.available());
chk = Serial.read();

if (chk != (hi ^ lo ^ 0x55)) {
i = 0;
goto waitLoop;
}

memset(leds, 0, NUM_LEDS * sizeof(struct CRGB));

for (uint8_t i = 0; i < NUM_LEDS; i++) {
byte r, g, b;
while(!Serial.available()); r = Serial.read();
while(!Serial.available()); g = Serial.read();
while(!Serial.available()); b = Serial.read();
leds[i].r = r;
leds[i].g = g;
leds[i].b = b;
}

FastLED.show();
} 
Prev Post
Next Post

Leave a comment

Please note, comments need to be approved before they are published.

Thanks for subscribing!

This email has been registered!

Shop the look

Choose Options

Edit Option
Back In Stock Notification
is added to your shopping cart.
this is just a warning
Login