This is an old revision of the document!


Smart NeoPixel LED Strip

Overview

General Idea

The idea for this project came as I wanted to add some backlight to my computer and desk so that it would be more cozy especially during the night. I wanted to be able to have more mods and have a finer control on the LEDs, so I chose a NeoPixels LED Strip, where I can control each LED of the Strip individually.

For the communication protocol between the ESP32 controller and my phone, I decided to use the Bluetooth LowEnergy protocol. I will use my phone as a remote control to send commands to the ESP32 controller and control the LED strip.

I used an OLED display as a way to better visualize the current status of the system, like if there is a device connected, if the lights are turned on or of, and what mode is currently selected.

Hardware Components Used

  • ESP32-WROOM-32: 1 x ESP32 Sparrow development board (purchased from here)
  • NeoPixel LED Strip: 1 x 5m NeoPixel LED Strip (became 4m after an accident =)) (300 NeoPixel LEDs for 5m or 270 NeoPixel LEDs for 4m)
  • Breadboard: 1 x 830 holes Breadboard
  • OLED Display: 1 x 0.91inch OLED Display
  • Connection Cables
  • USB-A to MicroUSB Cable

Software

  • Arduino IDE for code development and Serial Monitor
  • BLE Scanner Android App for connecting my phone to the ESP32 board via BLE

Architecture

Physical Architecture

Diagram

Real Hardware

Software Architecture

Setup de BLE Service

// BLE settings
#define SERVICE_UUID        "LED12345-1234-1234-1234-123456789LED"
#define CHARACTERISTIC_UUID "87654321-4321-4321-4321-LED987654321"
 
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
std::string receivedValue;
 
// BLE server callback
class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  };
 
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};
 
// BLE characteristic callback
class MyCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    receivedValue = pCharacteristic->getValue();
    if (receivedValue.length() > 0) {
      Serial.print("Received Value: ");
      Serial.println(receivedValue.c_str());
    }
  }
};
 
void setup() {
  Serial.begin(115200);
 
  // Initialize the NeoPixel library
  strip.begin();
  // Set all pixels to 'off'
  strip.show();
 
  // Initialize BLE
  BLEDevice::init("ESP32_LED_Control");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
 
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ |
                      BLECharacteristic::PROPERTY_WRITE
                    );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->setValue("Hello, World!");
  pService->start();
 
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();
 
  Serial.println("Waiting for a client connection to notify...");
}

Get the commands from the phone via the created service

void loop() {
  // Check if a device was connected
  if (deviceConnected) {
    if (!receivedValue.empty()) {
      handleCommand(receivedValue);
      receivedValue = "";
    }
  }
}
 
// Function that handles the commands got from the Phone via BLE
void handleCommand(const std::string& command) {
  if (command == "off") {
    lightsOn = false;
    strip.clear();
    strip.show();
  } else {
    lightsOn = true;
    mode = command;
  }
}

How it works

Challenges

Initially, I wanted to use both WiFi and BLE to control the LED Strip, but I had to limit myself to just one of them, so I chose BLE. The issue was that the WiFi library was just too big in size, taking over 59% of the text memory on my development board, so I dropped it.

By dropping the WiFi features, I had to drop the automatic time triggering as I could not set the time. To set the time to the Local Time, i would have to use a NTP server, but without the WiFi library, I could not connect to one. One other option was to pass the time as a parameter when the code is flashed on the board, but this is not optimal. Other option is to pass it as a command through my phone, but this just destroys the purpose of it being automatic.

Lastly, I found to my surprise that the ESP32 development board I have bought has not a LTR308 module on it, so I was unable to set an automatic detection of light in the room and trigger the light when needed.

Next Steps

First of all, buy a better development board, one that has at leas a LTR308 module on it. After that, I will implement the automatic light detection function and have the lights start automatically when it becomes dark in the room.

Resources

iothings/proiecte/2023sric/smartled.1717018280.txt.gz · Last modified: 2024/05/30 00:31 by dragos.petre
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