RGB Picker Web Interface – My First C++ and Arduino Project

A simple color picker for controlling the built-in RGB LED on the Arduino Nano ESP32.

Welcome! After almost a year, I'm finally publishing a new post. This time, I'm diving into C++ and Arduino to create an interactive RGB Picker Web Interface to select colors and display them on the RGB LED.

This project sets up an ESP32 Nano as a web server that allows users to control an RGB LED using a color picker on a web page. It enables both WiFi Station (STA) and Access Point (AP) modes, allowing users to connect either through an existing network or directly to the ESP32's own WiFi hotspot. The full code is available on GitHub.

Libraries Used

#include <Arduino.h>
#include <ArduinoJson.h>
#include <AsyncJson.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <WiFi.h>
  • Arduino.h: Core Arduino functions.
  • ArduinoJson.h: JSON handling.
  • AsyncJson.h: JSON support for the web server.
  • AsyncTCP.h: Handles non-blocking TCP connections.
  • ESPAsyncWebServer.h: Enables fast, asynchronous web server.
  • WiFi.h: WiFi management.

WiFi Configuration

static const char* ap_ssid = "Arduino Nano ESP32";
static const char* ap_passphrase = "12345678";

static const char* sta_ssid = "My Home WiFi";
static const char* sta_passphrase = "12345678";

The ESP32 is configured to work in dual-mode:

  1. Access Point (AP) mode allows direct connection to the ESP32.
  2. Station (STA) mode connects to an existing WiFi network.

If ap_passphrase is set to NULL, the AP mode will be open (no password required).

WiFi.mode(WIFI_AP_STA);
WiFi.softAP(ap_ssid, ap_passphrase);
WiFi.begin(sta_ssid, sta_passphrase);
  • Enables both Access Point and Station Mode.
  • If the ESP32 fails to connect to WiFi, it remains in AP mode.

Web Page & Color Picker UI

The ESP32 serves an HTML page containing a JavaScript-based color picker.

static const char* indexHtml PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
...
</html>
)rawliteral";
  • The HTML page includes CSS and JavaScript for the color picker.
  • When the user selects a color, RGBA (Red, Green, Blue, Alpha) values are sent to the ESP32 through fetch API POST request.

Storing RGB Values

int rangeRed = 0;
int rangeGreen = 0;
int rangeBlue = 0;
float rangeAlpha = 0.0;
  • These variables store the current color values.
  • The Alpha value controls the transparency of the color.

JSON API for RGB Data

AsyncJsonResponse* getRgbaJsonResponse() {
  AsyncJsonResponse* response = new AsyncJsonResponse();

  JsonObject root = response->getRoot().to<JsonObject>();
  root["red"] = rangeRed;
  root["green"] = rangeGreen;
  root["blue"] = rangeBlue;
  root["alpha"] = rangeAlpha;

  return response;
}
  • This function returns RGB values in JSON format.
  • The webpage fetches this JSON to display the current LED color.

Web Server Setup

static AsyncWebServer server(80);
  • This creates a web server running on port 80.
  • Handles HTTP requests for serving the webpage and RGB updates.

Handling HTTP Requests

Serve the Web Page

server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
  request->send(200, "text/html", (uint8_t*)indexHtml, indexHtmlLength);
});
  • Serves the color picker HTML page when the user visits the ESP32's IP address.

Fetch Current RGB Values (GET Request)

server.on("/rest/rgba", HTTP_GET, [](AsyncWebServerRequest *request) {
  AsyncJsonResponse* response = getRgbaJsonResponse();

  response->setLength();
  response->setCode(200);
  request->send(response);
});
  • The webpage fetches current RGB values using this endpoint.

Update RGB Values (POST Request)

AsyncCallbackJsonWebHandler* restRgbaJsonHandler =
    new AsyncCallbackJsonWebHandler("/rest/rgba", [](AsyncWebServerRequest* request, JsonVariant& json) {
      JsonObject body = json.as<JsonObject>();

      // validation here to check if body attributes are of correct types

      int red = body["red"];
      int green = body["green"];
      int blue = body["blue"];
      float alpha = body["alpha"];

      // validation here to check if values are valid and acceptable

      rangeRed = red;
      rangeGreen = green;
      rangeBlue = blue;
      rangeAlpha = alpha;

      AsyncJsonResponse* response = getRgbaJsonResponse();

      response->setLength();
      response->setCode(200);
      request->send(response);
    });
restRgbaJsonHandler->setMethod(HTTP_POST);

server.addHandler(restRgbaJsonHandler);
  • The webpage sends new color values using a POST request.
  • The ESP32 updates the LED color and brightness variables accordingly.
  • Responds back with updated RGBA values.

Controlling the RGB LED

// built-in rgb led pins are active-low
analogWrite(LED_RED, 255 - (int)round(rangeRed * rangeAlpha));
analogWrite(LED_GREEN, 255 - (int)round(rangeGreen * rangeAlpha));
analogWrite(LED_BLUE, 255 - (int)round(rangeBlue * rangeAlpha));
  • The ESP32 adjusts PWM values to change LED color and brightness based on RGBA values.

The Arduino Nano ESP32 has built-in active-low RGB LED, therefore I am using it. In case your board does not have it or you are connecting your RGB LED through pins, don't forget to define LED_RED, LED_GREEN and LED_BLUE with respective pin numbers.

How It Works

  • Power on ESP32 Nano → Starts WiFi AP & STA mode.
  • User connects to ESP32 WiFi or local network.
  • User opens webpage → Hosted on ESP32.
  • User picks a color → Sends data to ESP32.
  • ESP32 updates RGB LED → LED color changes instantly.
  • Webpage fetches current color values → Displays them in UI.

Advantages

  • Wireless Control: No need for direct wired connections.
  • Dual WiFi Mode: Works in both AP & STA mode.
  • Real-time Updates: Changes LED color instantly.
  • JSON API: Makes integration easy for other applications.
  • Low Power Usage: ESP32 is optimized for IoT projects.

Limitations & Future Improvements

  • No User Authentication: Anyone can access the color picker.
  • Limited Range: WiFi signal strength affects performance.
  • No Persistence: RGB values reset on power loss (EEPROM can fix this).
  • Could add WebSockets: For faster real-time updates.

Conclusion

This project demonstrates how to control an RGB LED wirelessly using an ESP32 Nano. By serving a webpage with a color picker, users can remotely adjust LED colors via a JSON-based API. The ESP32 runs in dual WiFi mode, making it accessible both through home networks and direct ESP32 hotspots.

This setup is ideal for IoT lighting projects, smart home applications, and WiFi-based LED controllers. 🚀

About the author

Deø Kumar
Lost in the echoes of another realm.

2 comments

  1. Aisosa
    Aisosa
    🔥🔥
    1. Deø Kumar
      Deø Kumar
      😀
To avoid SPAM, all comments will be moderated before being displayed.