Differences

This shows you the differences between two versions of the page.

Link to this comparison view

iothings:proiecte:2025sric:ledstrip [2025/04/24 08:11]
andrei.besliu
iothings:proiecte:2025sric:ledstrip [2025/05/29 00:48] (current)
andrei.besliu [ESP32 Web-based LED strip]
Line 1: Line 1:
-====== ESP32 Web-based LED strip ======+====== ESP32 BLE-based LED strip ======
  
   * Author: Besliu Andrei-Cornel   * Author: Besliu Andrei-Cornel
   * Email: andrei.besliu@stud.acs.pub.ro   * Email: andrei.besliu@stud.acs.pub.ro
   * Master: SCPD   * Master: SCPD
 +  * Video Link: https://​youtu.be/​Q6bHqYo0OGY 
 +  * Source Code: {{:​iothings:​proiecte:​2025sric:​besliu_andrei_iot.zip}}
 ====== Introduction ====== ====== Introduction ======
  
-Provide smart lighting to a home using an RGB LED strip and an ESP32. The ESP32 will act as web server, accessible ​from devices ​such as a smartphone or desktop PC.+Provide smart lighting to a home using an RGB LED strip and an ESP32. The ESP32 will expose ​BLE server ​that can receive commands ​from any BLE client. To prove functionality I implemented some simple features ​such as selecting from number of preset colors and adjusting brightness.
  
-====== Context ====== 
  
 ====== Hardware ====== ====== Hardware ======
 +  * **ESP32-WROOM-32:​** 1 x ESP32 Sparrow development board 
 +  * **NeoPixel LED Strip:** 1 x 5m NeoPixel LED strip, 300 LED's.
 +  * **Breadboard:​** 1x Breadboard for securing connections.
 +  * **Connecting Cables**
 +  * **USB-A to micro USB cable**
 +====== Diagram ======
  
 +{{ :​iothings:​proiecte:​2025sric:​diagram_ledstrip.png }}
 +
 +====== Actual Hardware ======
 +
 +{{ :​iothings:​proiecte:​2025sric:​actualHw_ledStrip.jpeg?​500 |}}
 +
 +The NeoPixel LED strip need +5V and GND to power the LED's and the addresing is done using a single data pin, which I have connected to GPIO 17.
 ====== Software ====== ====== Software ======
  
-=== Code Snippets ===+   * Arduino IDE for development 
 +   * Adafruit_NeoPixel library for easy LED strip manipulation 
 +   * ArduinoBLE library for Bluetooth service.
  
-==== Firebase ​====+====== ​Code Snippets ​====== 
 +Setting up BLE service with 2 Characteristics,​ one for setting the color and one for setting the brightness. The color receives a string 
 +with the desired color ("​red",​ "​blue",​ "​yellow",​ "​green",​ "​purple",​ "​orange",​ "​cyan"​) and the brightness is a single 8-bit value where 0 is off and 255 is the highest possible brightness.
  
 +<code C++>
 +// BLE server callback
 +class MyServerCallbacks:​ public BLEServerCallbacks {
 +  void onConnect(BLEServer* pServer) {
 +    deviceConnected = true;
 +  };
 +
 +  void onDisconnect(BLEServer* pServer) {
 +    deviceConnected = false;
 +  }
 +};
 +
 +/* BLE Characteristics */
 +BLECharacteristic *colorCharacteristic;​
 +class ColorCallback:​ public BLECharacteristicCallbacks {
 +  void onWrite(BLECharacteristic *colorCharacteristic) {
 +    receivedColor = colorCharacteristic->​getValue();​
 +    if (receivedColor.length() > 0) {
 +      Serial.print("​Received Color: ");
 +      Serial.println(receivedColor.c_str());​
 +    }
 +  }
 +};
 +
 +BLECharacteristic *brightCharacteristic;​
 +class BrightnessCallback:​ public BLECharacteristicCallbacks {
 +  void onWrite(BLECharacteristic *brightCharacteristic) {
 +    receivedBrightness = brightCharacteristic->​getValue().c_str()[0];​
 +    Serial.print("​Received Brightness: ");
 +    Serial.println(receivedBrightness,​ DEC);
 +  }
 +};
 +
 +[ ... ]
 +
 +// Initialize BLE
 +BLEDevice::​init("​ESP32_LED_Strip"​);​
 +BLEServer *pServer = BLEDevice::​createServer();​
 +pServer->​setCallbacks(new MyServerCallbacks());​
 +
 +BLEService *bmeService = pServer->​createService(SERVICE_UUID);​
 +
 +// Create colorCharacteristic
 +colorCharacteristic = bmeService->​createCharacteristic(
 +                    COLOR_UUID,
 +                    BLECharacteristic::​PROPERTY_READ |
 +                    BLECharacteristic::​PROPERTY_WRITE
 +                );
 +colorCharacteristic->​setCallbacks(new ColorCallback());​
 +colorCharacteristic->​setValue("​Hello,​ World!"​);​
 +
 +// Create colorCharacteristic
 +brightCharacteristic = bmeService->​createCharacteristic(
 +                    BRIGHTNESS_UUID,​
 +                    BLECharacteristic::​PROPERTY_READ |
 +                    BLECharacteristic::​PROPERTY_WRITE
 +                );
 +brightCharacteristic->​setCallbacks(new BrightnessCallback());​
 +int defaultBrightness = 255;
 +brightCharacteristic->​setValue(defaultBrightness);​
 +
 +// Start bme service.
 +bmeService->​start();​
 +
 +// Start Advertising
 +pServer->​getAdvertising()->​start();​
 +Serial.println("​Waiting a client connection to notify..."​);​
 +
 +</​code>​
 +
 +Setting up the LedStrip and control logic is straight-forward. We have global variables holding the current state of the strip that get update on BLECallback triggers. We also have a chgStrip boolean that prevents unneccesary updating of the LedStrip if no changes are currently performed.
 +<code c++>
 +// Initialize the NeoPixel library
 +strip.begin();​
 +// Set all pixels to '​off'​
 +strip.show();​
 +
 +// Set some default strip values;
 +actualBrightness = 128;
 +actualColor = strip.Color(0,​ 75, 0); // moderately bright green
 +chgStrip = true;
 +
 +[ ... ]
 +
 +// Check if a device was connected
 +if (deviceConnected) {
 +  if (!receivedColor.isEmpty()) {
 +    actualColor = getColor(receivedColor);​
 +    receivedColor = "";​
 +    chgStrip = true;
 +  }
 +
 +  if (receivedBrightness != 0) {
 +    actualBrightness = receivedBrightness;​
 +    receivedBrightness = 0;
 +    chgStrip = true;
 +  }
 +}
 +
 +// Update Strip.
 +if (chgStrip) {
 +  strip.clear();​
 + 
 +  for(int i=0; i<​NUM_PIXELS;​ i++) { // For each pixel...
 +    strip.setPixelColor(i,​ actualColor);​
 +  }
 +
 +  strip.setBrightness(actualBrightness);​
 +  strip.show();​
 +
 +  // Do not change strip next cycle
 +  chgStrip = false;
 +}
 +
 +</​code>​
 ====== Challenges ====== ====== Challenges ======
  
-====== References ======+Not having proper soldering tools leads to bad electrical contacts and makes it a nightmare to debug any issues. Thankfully, jamming a wire through the ESP32 DevBoard pins worked brilliantly,​ just don't ask me to move it anywhere.
  
 +Initially I wanted to use both BLE and a webpage hosted on the ESP32 itself to allow control of the LED strip from multiple sources but due to memory constraints on the ESP32 I had to choose only one (91% memory usage with the BLE implementation alone).
  
 +I find it very annoying how BLE handles characteristics,​ only having a predefined set of BLEUUID'​s available to pick and choose from. For example, the was no readily available UUID for brightness or color, just a generic "LED Array" or "Led Strip"​.
 +
 +I choose BLE due to the easy implementaion as baking-in a HTML page in the Arduino IDE seems janky to me. The right way to approach would be by installing a lightweight RTOS such as NuttX or freeRTOS and ditching the BLE for a more customizable webpage, as in our case  battery and power constraints are irrelevant.
 +
 +====== References ======
 +  * Adafruit_NeoPixel:​ https://​github.com/​adafruit/​Adafruit_NeoPixel
 +  * ArduinoBle: https://​docs.arduino.cc/​libraries/​arduinoble/​
 +  * Our OCW labs.
 +  * Some helpful StackOverflow threads.
iothings/proiecte/2025sric/ledstrip.1745471501.txt.gz · Last modified: 2025/04/24 08:11 by andrei.besliu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0