7,731
簡介
在物聯網開發中,ESP32 是一款功能強大的微控制器。若在開發中結合 C++ 的模板(template)特性,代碼會變得更加高效、靈活且可重用。本文將示範如何使用 C++ 模板與 ESP32 IDF,開發一個簡單的感測器專案來讀取溫度和光線數據,並使用 ESP-IDF 的 esp_log 來記錄輸出。
什麼是 C++ 模板 ( template )?
C++ 模板允許您撰寫可以適用於多種數據型態的通用函數或類別。透過模板,您可以減少撰寫重複的函數或類別,從而提高代碼的重用性。例如,一個 add 函數可以對 int 或 float 型態的數據進行加法運算,而不需要重複撰寫多種型態的 add 函數。
為何在 ESP32 上使用模板?
ESP32 相較於電腦系統,內存有限,因此優化代碼顯得尤為重要。使用模板可以減少重複的函數或類別拷貝,節省內存。此外,在物聯網專案中,模板能夠讓程式更具可讀性與模組化,適用於多樣化的感測器數據處理。
開發環境設置
1. 安裝 Visual Studio Code ,可從官方網站下載並且安裝。
2. 安裝 ESP-IDF 插件 。
創建一個新項目
1. 在 VS Code 中,按下 Ctrl (Cmd) + Shift + P,然後輸入 ESP-IDF: New Project。 2. 選擇一個樣板專案(如 blink example),設定專案名稱(例如 my_project),並選擇存儲路徑。 3. 此時,系統會自動為您生成一個新的 ESP-IDF 項目,其中包含基本的 CMake 文件和一個範例程式碼。
檔案結構
本專案將模擬兩個感測器類別: TemperatureSensor:模擬溫度感測器 LightSensor:模擬光線感測器 並結合 C++ 模板,建立一個通用函數來讀取這兩個感測器的數據。
my_project/ // 專案根目錄 ├── CMakeLists.txt // CMake 設定文件 ├── main/ // 主程式目錄 | ├── CMakeLists.txt // 主程式的 CMakeLists.txt │ ├── main.cpp // 主程式入口文件 (app_main) │ ├── TemperatureSensor.h // TemperatureSensor 類別的定義 │ ├── TemperatureSensor.cpp // TemperatureSensor 類別的實作 │ ├── LightSensor.h // LightSensor 類別的定義 │ └── LightSensor.cpp // LightSensor 類別的實作 └── sdkconfig // ESP-IDF 設定文件
需要在主程的 CMakeLists.txt 中將 TemperatureSensor.cpp 和 LightSensor.cpp 加入到 idf_component_register 的 SRCS 參數中,以確保這些源文件在編譯時被包含。這樣,編譯器才能找到這些檔案並將它們編譯到最終的固件中.
TemperatureSensor 類別
TemperatureSensor 類別模擬了溫度感測器,提供了初始化(begin())和數據讀取(readValue())方法。
TemperatureSensor.h
#ifndef TEMPERATURE_SENSOR_H
#define TEMPERATURE_SENSOR_H
class TemperatureSensor {
public:
void begin();
float readValue();
};
#endif // TEMPERATURE_SENSOR_H
TemperatureSensor.cpp
#include "TemperatureSensor.h"
#include "esp_log.h"
void TemperatureSensor::begin() {
ESP_LOGI("TemperatureSensor", "Temperature sensor initialized.");
}
float TemperatureSensor::readValue() {
// Simulate temperature data, range from 25°C to 35°C
return 25.0 + (rand() % 100) / 10.0; // Generate a random temperature value
}
此類別的 readValue 方法返回模擬的溫度數據,在真實應用中可以替換為實際的溫度感測邏輯。
LightSensor 類別
LightSensor 類別模擬了光線感測器,提供了與 TemperatureSensor 類似的方法。
LightSensor.h
#ifndef LIGHT_SENSOR_H
#define LIGHT_SENSOR_H
class LightSensor {
public:
void begin();
float readValue();
};
#endif // LIGHT_SENSOR_H
LightSensor.cpp
#include "LightSensor.h"
#include "esp_log.h"
void LightSensor::begin() {
ESP_LOGI("LightSensor", "Light sensor initialized.");
}
float LightSensor::readValue() {
// Simulate light data, range from 200 to 1000
return 200.0 + (rand() % 800); // Generate a random light intensity
}
在此類別的 readValue 方法中,生成模擬的光線強度數據,同樣可替換為真實的感測邏輯。
通用 templet 函數 readSensor
我們可以使用模板函數 readSensor,來讀取溫度或光線感測器的數據,這樣可以避免為每個感測器類別重複編寫代碼。
template <typename SensorType>
float readSensor(SensorType &sensor) {
return sensor.readValue();
}
主程式 app_main
main.cpp 是專案的主文件,在這裡調用 TemperatureSensor 和 LightSensor 類別並記錄讀取的數據
#include "TemperatureSensor.h"
#include "LightSensor.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
static const char *TAG = "SensorApp";
template <typename SensorType>
float readSensor(SensorType &sensor) {
return sensor.readValue();
}
extern "C" void app_main() {
TemperatureSensor tempSensor;
LightSensor lightSensor;
tempSensor.begin();
lightSensor.begin();
while (true) {
float temp = readSensor(tempSensor);
float light = readSensor(lightSensor);
ESP_LOGI(TAG, "Temperature: %.2f °C", temp);
ESP_LOGI(TAG, "Light Level: %.2f lux", light);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
解說 : 1. 創建了 TemperatureSensor 和 LightSensor 物件。 2. 使用模板函數 readSensor 讀取每個感測器的數據,並使用 ESP_LOGI 記錄溫度和光線數據。 3. 透過 vTaskDelay 設置延遲,每秒讀取一次數據。
編譯與燒錄
在 VSCode 視窗最下方中找到 "ESP32-IDF : Build, Flash and Monitor" ICON 執行和燒錄。
程式運行效果
運行程式後,您將在終端機中看到以下輸出:
I (1234) I (10) TemperatureSensor: Temperature sensor initialized.
I (10) LightSensor: Light sensor initialized.
I (1010) SensorApp: Temperature: 26.3 °C
I (1010) SensorApp: Light Level: 458.0 lux
I (2010) SensorApp: Temperature: 29.1 °C
I (2010) SensorApp: Light Level: 712.0 lux
I (3010) SensorApp: Temperature: 25.7 °C
I (3010) SensorApp: Light Level: 325.0 lux
I (4010) SensorApp: Temperature: 31.2 °C
I (4010) SensorApp: Light Level: 567.0 lux
結論
這個範例展示了如何在 ESP32 專案中利用 C++ 模板的特性來實現通用的感測器讀取函數,使代碼更加靈活與模組化。透過模板,我們可以輕鬆擴展支援新的感測器,只需撰寫新類別並使用模板函數進行調用即可。這種結構能有效提升代碼的重用性,並降低開發的複雜度,是物聯網開發中實用的技巧。 希望這篇文章幫助您更好地理解 C++ 模板在 ESP32 開發中的應用!