Powerful LED Strip Patterns | Learn C++ Overloading with ESP32
Introduction
Learn how to create professional LED strip patterns using C++ and ESP-IDF framework. This guide demonstrates how to leverage C++ function overloading for clean, efficient LED control while utilizing the full power of ESP-IDF.
Contents
Development Environment Setup
1. Install Visual Studio Code from the official website.
2. Install the ESP-IDF plugin.
Setting Up Your ESP32 for LED Strip Projects
1. In VS Code, press Ctrl (Cmd) + Shift + P, and enter ESP-IDF: New Project.
2. Choose a template project (e.g., blink example), set the project name (e.g., my_project), and choose a storage path.
3. The system will generate a new ESP-IDF project with a basic CMake file and example code.
Project File Structure
my_project/
├── CMakeLists.txt # Build configuration
├── main/
│ ├── CMakeLists.txt # Main component's CMake configuration
│ └── main.cpp # LED Strip class and application logic
└── sdkconfig # Project configuration
Getting Started with Function Overloading
Inheritance is a key feature of OOP that allows classes to derive properties and methods from other classes. By implementing a base class that encapsulates common functionality, we can reduce code duplication and simplify complex, multi-task systems. When applied to FreeRTOS on the ESP32, inheritance allows us to create versatile task classes that streamline the process of creating, managing, and reusing multiple tasks.
Set Up the LED Strip Class
The LEDStrip class will contain functions to initialize the strip and apply various lighting patterns, such as a solid color, color wave, and blinking effect.
class LEDStrip {
public:
// Constructor
LEDStrip(int numLEDs, gpio_num_t dataPin);
// Basic color set function
void setPattern(uint8_t red, uint8_t green, uint8_t blue);
// Overloaded pattern function for a color wave effect
void setPattern(uint8_t red, uint8_t green, uint8_t blue, int waveDelay, int waveLength);
// Overloaded pattern function for a blinking effect
void setPattern(std::vector<std::pair<uint8_t, uint8_t, uint8_t>> colors, int blinkDelay);
private:
int numLEDs;
gpio_num_t dataPin;
void show(); // Placeholder function to simulate LED update
};
Complete main.cpp
Code for LED Patterns
This code will initialize the ESP32, set up a simple LEDStrip class, and implement three LED patterns: solid color, color wave, and blinking—all in one file.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include <vector>
#include <utility> // for std::pair
#include <chrono> // for timing
// Define the tag for logging
static const char* TAG = "LEDStrip";
// LEDStrip class definition and implementation
class LEDStrip {
public:
LEDStrip(int numLEDs, gpio_num_t dataPin)
: numLEDs(numLEDs), dataPin(dataPin) {
gpio_reset_pin(dataPin);
gpio_set_direction(dataPin, GPIO_MODE_OUTPUT);
ESP_LOGI(TAG, "LED strip initialized on GPIO %d with %d LEDs", dataPin, numLEDs);
// Initialize last log time for controlling log frequency
lastLogTime = 0;
}
// Solid color pattern
void setPattern(uint8_t red, uint8_t green, uint8_t blue) {
ESP_LOGI(TAG, "Setting solid color pattern: R=%d, G=%d, B=%d", red, green, blue);
for (int i = 0; i < numLEDs; i++) {
// Log every 5th LED being set to the specified color
if (i % 5 == 0) {
logLEDChange(i, red, green, blue);
}
// Actual LED control code would go here
}
show();
}
// Color wave pattern
void setPattern(uint8_t red, uint8_t green, uint8_t blue, int waveDelay, int waveLength) {
ESP_LOGI(TAG, "Starting color wave pattern with R=%d, G=%d, B=%d, delay=%d ms, wave length=%d LEDs",
red, green, blue, waveDelay, waveLength);
for (int i = 0; i < numLEDs + waveLength; i++) {
for (int j = 0; j < waveLength; j++) {
int ledIndex = (i + j) % numLEDs;
// Log every 5th LED being set in the wave effect
if (ledIndex % 5 == 0) {
logLEDChange(ledIndex, red, green, blue);
}
// Set LED color here
}
show();
vTaskDelay(waveDelay / portTICK_PERIOD_MS);
}
ESP_LOGI(TAG, "Color wave pattern completed");
}
// Blinking multi-color pattern
void setPattern(std::vector<std::pair<uint8_t, uint8_t, uint8_t>> colors, int blinkDelay) {
ESP_LOGI(TAG, "Starting blinking pattern with %d colors, delay=%d ms", colors.size(), blinkDelay);
for (const auto& color : colors) {
uint8_t red = color.first, green = color.second, blue = color.second; // Fix accessing color components
ESP_LOGD(TAG, "Blinking color: R=%d, G=%d, B=%d", red, green, blue);
for (int i = 0; i < numLEDs; i++) {
// Log every 5th LED being set to the current color
if (i % 5 == 0) {
logLEDChange(i, red, green, blue);
}
// Set each LED to the current color here
}
show();
vTaskDelay(blinkDelay / portTICK_PERIOD_MS);
}
ESP_LOGI(TAG, "Blinking pattern completed");
}
private:
int numLEDs;
gpio_num_t dataPin;
unsigned long lastLogTime; // To track the last log time
const unsigned long logInterval = 500; // Minimum interval between logs in milliseconds
void logLEDChange(int ledIndex, uint8_t red, uint8_t green, uint8_t blue) {
unsigned long currentMillis = xTaskGetTickCount() * portTICK_PERIOD_MS;
if (currentMillis - lastLogTime >= logInterval) {
ESP_LOGD(TAG, "Setting LED %d to color: R=%d, G=%d, B=%d", ledIndex, red, green, blue);
lastLogTime = currentMillis;
}
}
void show() {
ESP_LOGD(TAG, "LEDs updated"); // Simulate the LED update
}
};
// Main function
extern "C" void app_main() {
esp_log_level_set("*", ESP_LOG_INFO); // Set global logging level to INFO
esp_log_level_set("LEDStrip", ESP_LOG_DEBUG); // Set specific logging level for LEDStrip class
LEDStrip strip(30, GPIO_NUM_5);
// Example patterns with controlled delays
ESP_LOGI("MAIN", "Setting solid color pattern to Red");
strip.setPattern(255, 0, 0);
vTaskDelay(2000 / portTICK_PERIOD_MS); // Wait 2 seconds
ESP_LOGI("MAIN", "Setting color wave pattern to Green");
strip.setPattern(0, 255, 0, 100, 5);
vTaskDelay(2000 / portTICK_PERIOD_MS); // Wait 2 seconds
ESP_LOGI("MAIN", "Setting blinking pattern with multiple colors");
std::vector<std::pair<uint8_t, uint8_t, uint8_t>> colors = {{255, 0, 0}, {0, 255, 0}, {0, 0, 255}};
strip.setPattern(colors, 500);
}
Explanation of Code
1. LED Strip Class Setup:
- The LEDStrip class is defined within main.cpp. It has a constructor to initialize the GPIO pin and three different setPattern functions for solid color, color wave, and blinking patterns.
2. Patterns Implementation:
- Each pattern method uses esp_log to print useful information:
- ESP_LOGI logs information about the pattern being applied (e.g., color, delay).
- ESP_LOGD provides detailed debug logs, such as the state of each LED during a wave or blink effect.
3. Logging in app_main:
- Each pattern call in app_main is preceded by a logging statement, providing context on which pattern is being executed.
4. Log Levels:
- esp_log_level_set controls log levels. Here, "LEDStrip" is set to ESP_LOG_DEBUG to get detailed logging only for the LED operations, while other logs remain at ESP_LOG_INFO.
Compiling and Flashing
In the VSCode window, find the ESP32-IDF : Build, Flash and Monitor icon to compile and flash the program.
Program Output
Once the program runs, you should see the following output in the terminal:
I (1234) LEDStrip: LED strip initialized on GPIO 5 with 30 LEDs
I (1234) MAIN: Setting solid color pattern to Red
I (1234) LEDStrip: Setting solid color pattern: R=255, G=0, B=0
D (1234) LEDStrip: Setting LED 0 to color: R=255, G=0, B=0
D (1239) LEDStrip: Setting LED 5 to color: R=255, G=0, B=0
D (1244) LEDStrip: Setting LED 10 to color: R=255, G=0, B=0
D (1249) LEDStrip: Setting LED 15 to color: R=255, G=0, B=0
D (1254) LEDStrip: Setting LED 20 to color: R=255, G=0, B=0
D (1259) LEDStrip: Setting LED 25 to color: R=255, G=0, B=0
D (1264) LEDStrip: LEDs updated
I (2264) MAIN: Setting color wave pattern to Green
I (2264) LEDStrip: Starting color wave pattern with R=0, G=255, B=0, delay=100 ms, wave length=5 LEDs
D (2264) LEDStrip: Setting LED 0 to color: R=0, G=255, B=0
D (2269) LEDStrip: Setting LED 5 to color: R=0, G=255, B=0
D (2274) LEDStrip: Setting LED 10 to color: R=0, G=255, B=0
D (2279) LEDStrip: Setting LED 15 to color: R=0, G=255, B=0
D (2284) LEDStrip: Setting LED 20 to color: R=0, G=255, B=0
D (2289) LEDStrip: Setting LED 25 to color: R=0, G=255, B=0
D (2294) LEDStrip: LEDs updated
I (3294) MAIN: Setting blinking pattern with multiple colors
I (3294) LEDStrip: Starting blinking pattern with 3 colors, delay=500 ms
D (3294) LEDStrip: Blinking color: R=255, G=0, B=0
D (3294) LEDStrip: Setting LED 0 to color: R=255, G=0, B=0
D (3299) LEDStrip: Setting LED 5 to color: R=255, G=0, B=0
D (3304) LEDStrip: Setting LED 10 to color: R=255, G=0, B=0
D (3309) LEDStrip: Setting LED 15 to color: R=255, G=0, B=0
D (3314) LEDStrip: Setting LED 20 to color: R=255, G=0, B=0
D (3319) LEDStrip: Setting LED 25 to color: R=255, G=0, B=0
D (3324) LEDStrip: LEDs updated
Conclusion
With this simplified code structure, beginners can now create complex LED Strip patterns using a single main.cpp file. This example also introduces the powerful esp_log logging system, helping track and debug each LED pattern step-by-step.
This method is ideal for learning, as you can quickly see how different patterns behave and experiment by adjusting parameters directly in one place. Happy experimenting!