Wi-Fi Controlled RGB Lighting System using NodeMCU (ESP8266) and Blynk App
01 Overview
In this project, we will build a Wi-Fi-controlled RGB lighting system using NodeMCU (ESP8266) and the Blynk app. It features individual control of 3 RGB LEDs, a color picker for custom hues, and a pattern mode for automated light shows.
Designed for applications in home automation, commercial ambiance control, and educational demonstrations, it features smooth PWM-based color transitions and energy efficiency. With straightforward hardware connections and intuitive software integration via Blynk, this project highlights how low-cost IoT devices can deliver dynamic lighting effects, laying the groundwork for future enhancements like audio-reactive visuals or AI-driven color adaptation.
Project Use Case
This project can be used anywhere a small, app-controlled lighting display is needed without building custom electronics or a dedicated mobile app. It suits home automation accent lighting, small-scale stage or display lighting, retail and commercial ambiance control, and classroom demonstrations of Wi-Fi, PWM, and cloud-connected IoT concepts.
02 Hardware and Software Components
Gather everything below before you start.
Hardware Components
| Component | Description |
|---|---|
| NodeMCU ESP8266 | Wi-Fi-enabled microcontroller board that runs the main sketch, connects to the Blynk cloud, and drives the RGB LEDs via PWM. |
| RGB LED (Diffused) | Tri-color common-cathode LED used to display selectable colors and animated light patterns. Three units are used for a synchronized light show. |
| 220Ω Resistors | Current-limiting resistors placed in series with each LED lead to protect the diodes from excess current. |
| Breadboard | Provides a temporary platform for assembling and testing the LED wiring. |
| Jumper Wires | Used to connect the NodeMCU GPIO pins to the LEDs and resistors on the breadboard. |
Software Tools
| Software | Version / Details | Description |
|---|---|---|
| Arduino IDE | Latest Version | Used to write, compile, and upload the sketch to the NodeMCU board. |
| Blynk App | Latest Version, with a linked Blynk Cloud template | Mobile app used to build the control dashboard (color picker, power button, brightness/speed sliders, pattern buttons) that communicates with the NodeMCU over Wi-Fi. |
03 Application Discussion
NodeMCU
NodeMCU is an open-source firmware and development board based on the ESP8266 Wi-Fi microcontroller, designed for IoT and embedded projects. Originally developed to run Lua scripts, it now supports programming via Arduino IDE and MicroPython, offering Wi-Fi connectivity (802.11 b/g/n), GPIO pins for sensors/actuators, and a built-in USB interface for easy flashing and power.
Specifications:
- Microcontroller: ESP8266 (32-bit Tensilica L106 @ 80–160 MHz)
- Wi-Fi: 802.11 b/g/n (2.4 GHz), supports STA/AP/STA+AP modes
- Flash Memory: 4MB (varies by model)
- RAM: 64KB (for user programs) + 96KB (system reserved)
- GPIO Pins: 10–17 (multiplexed, some support PWM/I²C/SPI)
- Analog Input: 1x 10-bit ADC (max 3.3V input)
- Digital Interfaces: UART, SPI, I²C
- USB-to-Serial: CH340G/CP2102 (for programming)
- Power Supply: 3.3V (board includes 3.3V regulator, input: 5V via USB or 7–12V via Vin)
- Operating Voltage: 3.3V (GPIOs are not 5V-tolerant!)
RGB LED, Diffused

Specifications:
- 5mm / 10mm diameter
- Tricolor Red(R) Green(G) Blue(B) Common Cathode (CC); R: 620nm–625nm / G: 515nm–523nm / B: 450nm–467nm; Luminous Intensity (Brightness): R: 1000–2000mcd / G: 4000–5000mcd / B: 3000–4000mcd; Viewing Angle: 20–50 Degrees
- Parameters: DC 1.8V–2.2V (R), 3V–3.4V (G/B), 20mA. Polarity (2 V): Cathode "-" (Longer Leg) | Anode "+" (Shorter Leg). Foggy round small lens.
- LED diode (through-hole DIP, 4-pin leads), tricolor
- Compatible with: DIY PCB boards, Arduino, Raspberry Pi, hobby and science experiments, LED throwies, breadboards, and general bulk-parts replacement
- 4 pin, tiny bright light, low voltage and low power consumption: 1.8V, 2.2V, 3.2V, 3.4V
RGB LED Pinout

04 Hardware Setup
Wire the components to the breadboard using the pin table below. Each LED lead should pass through a 220Ω resistor before reaching its NodeMCU GPIO pin.
NodeMCU to RGB LED Pin Mapping
| LED | Color Channel | NodeMCU Pin |
|---|---|---|
| LED 1 | Red | D0 |
| LED 1 | Green | D1 |
| LED 1 | Blue | D2 |
| LED 2 | Red | D3 |
| LED 2 | Green | D4 |
| LED 2 | Blue | D5 |
| LED 3 | Red | D6 |
| LED 3 | Green | D7 |
| LED 3 | Blue | D8 |
Assembly Instructions
- Place all three RGB LEDs on the breadboard with their cathodes (longer leg) oriented consistently.
- Connect a 220Ω resistor in series with each of the 9 R/G/B leads.
- Wire each resistor to its corresponding NodeMCU GPIO pin as listed in the table above.
- Connect all three LED cathodes to a common GND pin on the NodeMCU.
- Double-check all connections before powering the board.
- Connect the NodeMCU to your computer via USB cable to power the board and upload the sketch.
05 Software Setup
Follow these steps in order before uploading the sketch.
Step 1 — Install Arduino IDE and ESP8266 Board Support
- Download and install Arduino IDE.
- Open Arduino IDE and add ESP8266 board support via File → Preferences → Additional Board Manager URLs, then install esp8266 by ESP8266 Community through the Board Manager.
- Under Tools → Board, select NodeMCU 1.0 (ESP-12E Module).
Step 2 — Install the Blynk Library
Open Arduino IDE → Sketch → Include Library → Manage Libraries, then install Blynk by Volodymyr Shymanskyy.
Step 3 — Set Up the Blynk Template
Create a new template in the Blynk app (or Blynk Cloud console) and note its Template ID, Template Name, and Auth Token — these go at the top of the sketch. See the Blynk Setup section for the datastream configuration used by this project.
ssid, pass, and BLYNK_AUTH_TOKEN values in the sketch with your own Wi-Fi credentials and your own Blynk Auth Token. Never share your Auth Token publicly, since it grants control of your connected device.Step 4 — Upload the Code
- Open the sketch in Arduino IDE.
- Verify that the pin assignments match the hardware connections.
- Click Verify to compile the code.
- Click Upload to flash the code to the NodeMCU.
- Open the Blynk app and confirm the device comes online.
06 Code
Below is the complete Arduino sketch for the project. Read the Code Breakdown section to understand what each part does.
NodeMCU RGB Light Show Sketch
#define BLYNK_TEMPLATE_ID "TMPL6bYnZicw8"
#define BLYNK_TEMPLATE_NAME "RGB LIGHT SHOW"
#define BLYNK_AUTH_TOKEN "3dnat1_YCGM6TwpRnW4i4O3eBx8rgW7N"
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
char ssid[] = "dyemwifi";
char pass[] = "dy3mdyem098";
// LED Pins
const int ledPin11 = D0; // LED1 Red
const int ledPin12 = D1; // LED1 Green
const int ledPin13 = D2; // LED1 Blue
const int ledPin21 = D3; // LED2 Red
const int ledPin22 = D4; // LED2 Green
const int ledPin23 = D5; // LED2 Blue
const int ledPin31 = D6; // LED3 Red
const int ledPin32 = D7; // LED3 Green
const int ledPin33 = D8; // LED3 Blue
// Control variables
struct RGBColor {
int r;
int g;
int b;
};
// For RGB widget control
RGBColor selectedColor = {255, 255, 255};
int brightness = 100; // 0-100%
bool rgbWidgetMode = false;
bool runningEffect = false;
unsigned long effectMillis = 0;
int effectSpeed = 300; // milliseconds between changes
int currentRunningLED = 1;
// For pattern control
enum Pattern { NONE, RED_RUN, GREEN_RUN, BLUE_RUN, RAINBOW_CHASE };
Pattern currentPattern = NONE;
unsigned long patternMillis = 0;
int patternPosition = 0;
void turnOffAllLEDs() {
analogWrite(ledPin11, 0);
analogWrite(ledPin12, 0);
analogWrite(ledPin13, 0);
analogWrite(ledPin21, 0);
analogWrite(ledPin22, 0);
analogWrite(ledPin23, 0);
analogWrite(ledPin31, 0);
analogWrite(ledPin32, 0);
analogWrite(ledPin33, 0);
}
void setLEDColor(int ledNumber, int color) {
// For individual color control (0=red, 1=green, 2=blue)
int r = (color == 0) ? 255 : 0;
int g = (color == 1) ? 255 : 0;
int b = (color == 2) ? 255 : 0;
switch(ledNumber) {
case 1:
analogWrite(ledPin11, r);
analogWrite(ledPin12, g);
analogWrite(ledPin13, b);
break;
case 2:
analogWrite(ledPin21, r);
analogWrite(ledPin22, g);
analogWrite(ledPin23, b);
break;
case 3:
analogWrite(ledPin31, r);
analogWrite(ledPin32, g);
analogWrite(ledPin33, b);
break;
}
}
void setLEDRGB(int ledNumber, RGBColor color) {
// Apply brightness to each color channel
int r = map(color.r, 0, 255, 0, brightness * 2.55);
int g = map(color.g, 0, 255, 0, brightness * 2.55);
int b = map(color.b, 0, 255, 0, brightness * 2.55);
switch(ledNumber) {
case 1:
analogWrite(ledPin11, r);
analogWrite(ledPin12, g);
analogWrite(ledPin13, b);
break;
case 2:
analogWrite(ledPin21, r);
analogWrite(ledPin22, g);
analogWrite(ledPin23, b);
break;
case 3:
analogWrite(ledPin31, r);
analogWrite(ledPin32, g);
analogWrite(ledPin33, b);
break;
}
}
void updateEffects() {
unsigned long currentMillis = millis();
// Handle RGB widget running effect
if (runningEffect && rgbWidgetMode) {
if (currentMillis - effectMillis >= effectSpeed) {
effectMillis = currentMillis;
turnOffAllLEDs();
setLEDRGB(currentRunningLED, selectedColor);
currentRunningLED = (currentRunningLED % 3) + 1; // Cycle through 1-3
}
}
// Handle color patterns
else if (currentPattern != NONE) {
if (currentMillis - patternMillis >= effectSpeed) {
patternMillis = currentMillis;
switch(currentPattern) {
case RED_RUN:
turnOffAllLEDs();
setLEDColor(patternPosition + 1, 0);
break;
case GREEN_RUN:
turnOffAllLEDs();
setLEDColor(patternPosition + 1, 1);
break;
case BLUE_RUN:
turnOffAllLEDs();
setLEDColor(patternPosition + 1, 2);
break;
case RAINBOW_CHASE:
turnOffAllLEDs();
setLEDColor(1, patternPosition % 3);
setLEDColor(2, (patternPosition + 1) % 3);
setLEDColor(3, (patternPosition + 2) % 3);
break;
case NONE:
break;
}
patternPosition = (patternPosition + 1) % 3;
}
}
}
// Individual LED control (V0-V8)
BLYNK_WRITE(V0) { if (!rgbWidgetMode) setLEDColor(1, param.asInt() ? 0 : -1); }
BLYNK_WRITE(V1) { if (!rgbWidgetMode) setLEDColor(1, param.asInt() ? 1 : -1); }
BLYNK_WRITE(V2) { if (!rgbWidgetMode) setLEDColor(1, param.asInt() ? 2 : -1); }
BLYNK_WRITE(V3) { if (!rgbWidgetMode) setLEDColor(2, param.asInt() ? 0 : -1); }
BLYNK_WRITE(V4) { if (!rgbWidgetMode) setLEDColor(2, param.asInt() ? 1 : -1); }
BLYNK_WRITE(V5) { if (!rgbWidgetMode) setLEDColor(2, param.asInt() ? 2 : -1); }
BLYNK_WRITE(V6) { if (!rgbWidgetMode) setLEDColor(3, param.asInt() ? 0 : -1); }
BLYNK_WRITE(V7) { if (!rgbWidgetMode) setLEDColor(3, param.asInt() ? 1 : -1); }
BLYNK_WRITE(V8) { if (!rgbWidgetMode) setLEDColor(3, param.asInt() ? 2 : -1); }
// Pattern control (V9-V12)
BLYNK_WRITE(V9) { handlePatternControl(param, RED_RUN); }
BLYNK_WRITE(V10) { handlePatternControl(param, GREEN_RUN); }
BLYNK_WRITE(V11) { handlePatternControl(param, BLUE_RUN); }
BLYNK_WRITE(V12) { handlePatternControl(param, RAINBOW_CHASE); }
void handlePatternControl(const BlynkParam ¶m, Pattern pattern) {
if (param.asInt()) {
rgbWidgetMode = false;
runningEffect = false;
currentPattern = pattern;
patternPosition = 0;
patternMillis = millis();
} else if (currentPattern == pattern) {
currentPattern = NONE;
turnOffAllLEDs();
}
}
// RGB Widget control (V13-V17)
BLYNK_WRITE(V13) { // COLOR datastream
selectedColor.r = param[0].asInt();
selectedColor.g = param[1].asInt();
selectedColor.b = param[2].asInt();
if (rgbWidgetMode && !runningEffect) {
setLEDRGB(1, selectedColor);
setLEDRGB(2, selectedColor);
setLEDRGB(3, selectedColor);
}
}
BLYNK_WRITE(V14) { // BUTTON datastream (power)
bool state = param.asInt();
if (state) {
rgbWidgetMode = true;
runningEffect = false;
currentPattern = NONE;
setLEDRGB(1, selectedColor);
setLEDRGB(2, selectedColor);
setLEDRGB(3, selectedColor);
} else {
turnOffAllLEDs();
}
}
BLYNK_WRITE(V15) { // BRIGHTNESS datastream
brightness = param.asInt();
if (rgbWidgetMode && !runningEffect) {
setLEDRGB(1, selectedColor);
setLEDRGB(2, selectedColor);
setLEDRGB(3, selectedColor);
}
}
BLYNK_WRITE(V16) { // ANIMATION SPEED datastream
// Invert the mapping so higher values = slower speed
effectSpeed = map(param.asInt(), 0, 100, 5000, 100); // 100ms to 5000ms
}
BLYNK_WRITE(V17) { // EFFECT TOGGLE
bool state = param.asInt();
if (state) {
rgbWidgetMode = true;
currentPattern = NONE;
runningEffect = true;
currentRunningLED = 1;
effectMillis = millis();
} else {
runningEffect = false;
if (rgbWidgetMode) {
setLEDRGB(1, selectedColor);
setLEDRGB(2, selectedColor);
setLEDRGB(3, selectedColor);
}
}
}
void setup() {
// Initialize all LED pins
pinMode(ledPin11, OUTPUT);
pinMode(ledPin12, OUTPUT);
pinMode(ledPin13, OUTPUT);
pinMode(ledPin21, OUTPUT);
pinMode(ledPin22, OUTPUT);
pinMode(ledPin23, OUTPUT);
pinMode(ledPin31, OUTPUT);
pinMode(ledPin32, OUTPUT);
pinMode(ledPin33, OUTPUT);
// Start with all LEDs off
turnOffAllLEDs();
// Connect to Blynk
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
}
void loop() {
Blynk.run();
updateEffects();
}
07 Code Breakdown
Here is what each part of the code does.
Libraries
| Library | Purpose |
|---|---|
| ESP8266WiFi.h | Handles the NodeMCU's Wi-Fi connection to the local network. |
| BlynkSimpleEsp8266.h | Connects the sketch to the Blynk cloud service and routes datastream events to/from the app. |
Key Functions
setup()
Configures all nine LED pins as outputs, turns every LED off, and connects to the Blynk server using the Wi-Fi credentials and Auth Token defined at the top of the sketch.
loop()
Keeps the Blynk connection alive with Blynk.run() and calls updateEffects() on every cycle to advance any active animation.
turnOffAllLEDs()
Sets all nine PWM outputs to 0, switching every LED off. Used as a reset step before applying a new color or pattern frame.
setLEDColor(ledNumber, color)
Drives one LED to a full-intensity primary color (red, green, or blue) based on an index. Used by the individual per-LED buttons and the running color patterns.
setLEDRGB(ledNumber, color)
Drives one LED to a custom RGB color from the Blynk color picker, scaling each channel by the current brightness setting before writing it out via PWM.
updateEffects()
Runs on every loop iteration and checks elapsed time against effectSpeed. If the RGB widget's running-light mode is active, it walks the selected color across LEDs 1→2→3. If a pattern is active instead, it advances that pattern's frame (red run, green run, blue run, or rainbow chase).
handlePatternControl(param, pattern)
Shared handler for the four pattern buttons. Turning a pattern on disables RGB widget mode and starts that pattern from position 0; turning the active pattern off stops it and clears the LEDs.
Blynk Virtual Pin Map
| Virtual Pin | Widget | Function |
|---|---|---|
| V0 – V2 | Buttons | Individual Red/Green/Blue control for LED 1. |
| V3 – V5 | Buttons | Individual Red/Green/Blue control for LED 2. |
| V6 – V8 | Buttons | Individual Red/Green/Blue control for LED 3. |
| V9 – V12 | Buttons | Pattern selection: Red Run, Green Run, Blue Run, Rainbow Chase. |
| V13 | Color Picker (zeRGBa) | Sets the custom RGB color used by the widget mode. |
| V14 | Button | Power toggle — turns the RGB widget mode on/off. |
| V15 | Slider | Sets overall brightness (0–100%). |
| V16 | Slider | Sets animation speed (inverted: higher value = slower). |
| V17 | Button | Toggles the running-light chase effect on/off. |
General Program Workflow
- Initialize the NodeMCU pins and connect to the Blynk cloud over Wi-Fi.
- Listen for datastream events from the Blynk app (button presses, color picker changes, slider adjustments).
- Update the selected LED(s) using either direct color control or brightness-scaled RGB values.
- On every loop, advance any active running-light effect or color pattern based on elapsed time.
- Repeat continuously so the lighting stays synchronized with the app in real time.
08 Blynk Setup
Below are the Blynk configurations and setup used for this project's dashboard.
09 System Demonstration
Video Demonstration
10 Conclusion
This project successfully demonstrates how low-cost microcontrollers can achieve professional-grade lighting effects. Its modular design allows easy adaptation to art installations, stage lighting, or smart home systems, while the Blynk platform eliminates complex app development. Future iterations could integrate machine learning for adaptive color schemes based on room occupancy or audio input.
11 References
- How to set up the new Blynk app step by step | NodeMCU ESP8266 with Blynk app
- How to Setup and Program NodeMCU ESP8266 – Complete Guide
12 Project Authors
- Jonah James Simene
- Lukie-Mar Lonzaga
- Miles Darren Bagnol
- Elijah Joseph Orias
