🖥️ Interface and Application Programming



🐲 1. Project Overview

This week I focused on creating a web-based interface that communicates directly with my custom XIAO ESP32C3 board. The goal was to control an RGB LED strip based on color input from the APDS-9960 sensor and view it in real time on a local webpage.



🐲 2. Tools & Setup

  • - Microcontroller: XIAO ESP32C3
  • - Sensor: APDS-9960 (Color sensor)
  • - Output: 8-LED NeoPixel Stick (SK6812)
  • - Communication: Web server hosted on ESP32C3
  • - Libraries: FastLED, SparkFun APDS9960, WiFi, WebServer


🐲 3. The Web Interface

The ESP32C3 acts as a standalone web server. When accessed through a browser, the interface displays:

  • 🎨 The name of the detected color
  • 🌈 The RGB values from the sensor
  • 💡 A checkbox to toggle the NeoPixel LEDs on/off

The webpage auto-refreshes every 2 seconds for live updates.



🐲 How Communication Works

Here's a step-by-step guide on how to set up the system from start to finish:


  1. Wiring the Components:
    • - Connect APDS-9960 sensor using I2C (SCL to GPIO7, SDA to GPIO6, GND, and 3.3V).
    • - Connect the NeoPixel Stick to GPIO9, GND, and 5V.

  2. Install Libraries:
    • - In Arduino IDE, install: FastLED, SparkFun_APDS9960, and ESP32 WebServer libraries.

  3. Prevent Library Conflict:
    • - Add #undef WAIT before including <FastLED.h> to resolve macro conflict with APDS9960.

  4. Connect to Wi-Fi:
    • - Set your Wi-Fi SSID and password in the code.
    • - Use Serial Monitor to confirm IP address once connected.

  5. Program Behavior:
    • - The ESP32 reads RGB values from the sensor.
    • - It lights up the NeoPixels accordingly.
    • - A local web page is served showing the detected color and values, with an LED toggle control.

  6. Access the Interface:
    • - Open your browser and visit the IP shown in the Serial Monitor (e.g., http://192.168.X.X).

  7. Test and Verify:
    • - Move different colors in front of the sensor.
    • - Observe changes in webpage and LED strip in real-time.

This step-by-step setup ensures full communication between your ESP32C3, sensors, outputs, and browser interface.


Serial Monitor

Web Server

Arduino Code (Final)



#include <WiFi.h>
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#undef WAIT  // Fix macro conflict with FastLED
#include <FastLED.h>
#include <WebServer.h>

// Wi-Fi credentials
const char* ssid = "BSC-GF";
const char* password = "bsc@2030";

// LED settings
#define LED_PIN 9
#define NUM_LEDS 8
CRGB leds[NUM_LEDS];
bool ledsOn = true;

// Color sensor
SparkFun_APDS9960 apds;
String currentColor = "Unknown";
uint16_t r = 0, g = 0, b = 0;

// Web server
WebServer server(80);

void setup() {
  Serial.begin(115200);
  Wire.begin();

  FastLED.addLeds<SK6812, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.clear(); FastLED.show();

  if (!apds.init()) {
    Serial.println("APDS-9960 init failed!");
    while (1);
  }
  apds.enableLightSensor(false);
  delay(500);

  WiFi.begin(ssid, password);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); Serial.print(".");
  }
  Serial.println("\nWi-Fi connected. IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.on("/toggle", HTTP_POST, handleToggle);
  server.begin();
  Serial.println("Web server started");
}

void loop() {
  server.handleClient();
  uint16_t c;
  if (apds.readRedLight(r) && apds.readGreenLight(g) && apds.readBlueLight(b) && apds.readAmbientLight(c)) {
    currentColor = detectColor(r, g, b);
    Serial.print("Detected: ");
    Serial.print(currentColor);
    Serial.print("  | R: "); Serial.print(r);
    Serial.print(" G: "); Serial.print(g);
    Serial.print(" B: "); Serial.println(b);

    if (ledsOn) {
      showColor(r, g, b);
    } else {
      FastLED.clear(); FastLED.show();
    }
  }
  delay(500);
}

String detectColor(uint16_t r, uint16_t g, uint16_t b) {
  if (r > g && r > b) return "Red";
  else if (g > r && g > b) return "Green";
  else if (b > r && b > g) return "Blue";
  else if (r > 200 && g > 200 && b > 200) return "White";
  else return "Unknown";
}

void showColor(uint16_t r, uint16_t g, uint16_t b) {
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB(r / 4, g / 4, b / 4);
    FastLED.show();
    delay(50);
  }
}

void handleRoot() {
  String state = ledsOn ? "checked" : "";
  server.send(200, "text/html", htmlPage(state));
}

void handleToggle() {
  if (server.hasArg("led")) {
    ledsOn = true;
  } else {
    ledsOn = false;
    FastLED.clear(); FastLED.show();
  }
  server.sendHeader("Location", "/");
  server.send(303);
}

String htmlPage(String state) {
  return "<!DOCTYPE html><html><head><meta charset='UTF-8'>" 
         "<meta http-equiv='refresh' content='2'>" 
         "<meta name='viewport' content='width=device-width, initial-scale=1'>" 
         "<title>ESP32 Color Sensor</title>" 
         "<style>body{font-family:sans-serif;text-align:center;padding:40px;} .switch{margin-top:20px;}</style></head><body>" 
         "<h2>🎨 Detected Color: <span style='color:" + currentColor + "'>" + currentColor + "</span></h2>" 
         "<p>🌈 RGB Values → R: " + String(r) + " G: " + String(g) + " B: " + String(b) + "</p>" 
         "<form action='/toggle' method='POST'><label>💡 LEDs On/Off</label><br>" 
         "<input type='checkbox' name='led' onchange='this.form.submit()' " + state + "></form>" 
         "</body></html>";
}


🐲 5. Results & Observations

  • - Accurate Detection: The system successfully detects color values and displays them both visually on the webpage and physically via the NeoPixel LED strip.
  • - Interactive Control: The web interface includes a live toggle (checkbox) that instantly enables or disables the LEDs.
  • - Live Updates: RGB values from the sensor are updated regularly, giving a clear sense of real-time feedback.


🐲 6. Key Takeaways & Fixes


General Takeaways

  • - ESP32 Web Interface: Hosting a local web server on the XIAO ESP32C3 is a great way to interact with real-world sensors and outputs.
  • - Simple UI, Big Impact: A minimal HTML setup with auto-refresh offers quick and useful control/feedback with almost no front-end overhead.
  • - FastLED Integration: FastLED handles smooth, vibrant control of NeoPixel LEDs — perfect for color-based output from sensors.

Issues & Fixes

  • - Macro Conflict: A name clash between FastLED and the APDS9960 library caused a compile error. Adding #undef WAIT before #include <FastLED.h> fixed it.
  • - GPIO10 Wi-Fi Conflict: GPIO10 interferes with Wi-Fi on the XIAO ESP32C3 (used internally for flash). Switching to GPIO9 solved this issue and restored connectivity.
  • - Slow Update Delay: The combination of a delay(500) in the loop and a 2s page auto-refresh leads to visible lag. Replacing auto-refresh with AJAX/WebSocket can greatly enhance UI responsiveness.


🐲 7. Hero Shot

⬆ Top 🏠 Home