Wi-Fi RGB Light Show Functions Using NodeMCU

 

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

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

How RGB LEDs work and how to control color

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.

Hardware Setup Diagram

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
Note: All three LED cathodes connect to a common GND pin on the NodeMCU.

Assembly Instructions

  1. Place all three RGB LEDs on the breadboard with their cathodes (longer leg) oriented consistently.
  2. Connect a 220Ω resistor in series with each of the 9 R/G/B leads.
  3. Wire each resistor to its corresponding NodeMCU GPIO pin as listed in the table above.
  4. Connect all three LED cathodes to a common GND pin on the NodeMCU.
  5. Double-check all connections before powering the board.
  6. 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

  1. Download and install Arduino IDE.
  2. 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.
  3. 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.

Note: Before uploading, replace the 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

  1. Open the sketch in Arduino IDE.
  2. Verify that the pin assignments match the hardware connections.
  3. Click Verify to compile the code.
  4. Click Upload to flash the code to the NodeMCU.
  5. 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

Arduino / C++
#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 &param, 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

  1. Initialize the NodeMCU pins and connect to the Blynk cloud over Wi-Fi.
  2. Listen for datastream events from the Blynk app (button presses, color picker changes, slider adjustments).
  3. Update the selected LED(s) using either direct color control or brightness-scaled RGB values.
  4. On every loop, advance any active running-light effect or color pattern based on elapsed time.
  5. 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.

Blynk Setup 1 Blynk Setup 2 Blynk Setup 3

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
Quality Checked by
  • Lukie-Mar Lonzaga
  • Miles Darren Bagnol
  • Elijah Joseph Orias
Wi-Fi Controlled RGB Lighting System using NodeMCU (ESP8266) and Blynk App – CreateLabz

 

Blynk, Control light, Esp8266, Ledcontrol, Light sensor, Light show, Nodemcu, Rgb

Leave a comment

All comments are moderated before being published