使用 C++ Overloading 和 ESP32 | 掌握強大 LED Strip 技術
簡介
了解如何使用 C++ 和 ESP-IDF 框架創建專業的 LED Strip (燈帶) 圖案。本指南演示如何利用 C++ 重載 (Overloading) 來保持代碼的整潔與高效的 LED 控制,同時充分發揮 ESP-IDF 的強大功能。
Contents
開發環境設置
1. 從官方網站安裝 Visual Studio Code。
2. 安裝 ESP-IDF 插件。
為 LED Strip 項目設置 ESP32
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.
檔案結構
my_project/
├── CMakeLists.txt # 構建配置
├── main/
│ ├── CMakeLists.txt # 主組件的 CMake 配置
│ └── main.cpp # LED 燈帶類和應用邏輯
└── sdkconfig # 項目配置
重載 Overloading
繼承是面向對象編程(OOP)的關鍵特性,它允許類從其他類派生屬性和方法。通過實現一個封裝常用功能的基類,我們可以減少代碼重複並簡化複雜的多任務系統。當將其應用於 ESP32 上的 FreeRTOS 時,繼承使我們能夠創建多功能的任務類,從而簡化創建、管理和重用多個任務的過程。
設置 LED Strip 類別
LED Strip 類將包含用於初始化燈帶和應用各種照明模式的函數,例如固態顏色、顏色波和閃爍效果。
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
};
完整的 main.cpp 代碼用於 LED Strip
此代碼將初始化 ESP32,設置一個簡單的 LEDStrip 類,並實現三種 LED 圖案:固態顏色、顏色波和閃爍——所有內容都在一個文件中。
#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);
}
代碼解釋
1. LED 燈帶類別設置:
- LEDStrip 類別在 main.cpp 中定義。它有一個構造函數來初始化 GPIO 引腳,以及三個不同的 setPattern 函數,用於設置固態顏色、顏色波浪和閃爍圖案。
2. 圖案實現:
- 每個圖案方法使用 esp_log 來打印有用的信息:
- ESP_LOGI 記錄有關正在應用的圖案的信息(例如顏色、延遲)。
- ESP_LOGD 提供詳細的調試日誌,例如波浪或閃爍效果中每個 LED 的狀態。
3. 在 app_main 中的日誌:
- app_main 中的每個圖案調用前都有一個日誌語句,提供有關正在執行的圖案的上下文。
4. 日誌級別:
- esp_log_level_set 控制日誌級別。在這裡,"LEDStrip" 設置為 ESP_LOG_DEBUG,以獲得僅針對 LED 操作的詳細日誌,而其他日誌則保持在 ESP_LOG_INFO。
編譯與燒錄
在 VSCode 視窗最下方中找到 "ESP32-IDF : Build, Flash and Monitor" ICON 執行和燒錄。
程式運行效果
運行程式後,您將在終端機中看到以下輸出:
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
結論
這種簡化的代碼結構讓初學者能夠通過一個 main.cpp 文件創建複雜的 LED Strip 圖案。這個例子還引入了強大的 esp_log 日誌系統,幫助逐步跟蹤和調試每個 LED 圖案的運行過程。
這種方法非常適合學習,因為您可以迅速看到不同圖案的行為,並通過直接在一個地方調整參數來進行實驗。祝您實驗愉快!