forked from xiaozhi/xiaozhi-esp32
添加普通LED支持,支持不同状态亮度设置和呼吸灯效果 (#283)
This commit is contained in:
@@ -6,6 +6,7 @@ set(SOURCES "audio_codecs/audio_codec.cc"
|
||||
"audio_codecs/cores3_audio_codec.cc"
|
||||
"led/single_led.cc"
|
||||
"led/circular_strip.cc"
|
||||
"led/gpio_led.cc"
|
||||
"display/display.cc"
|
||||
"display/no_display.cc"
|
||||
"display/lcd_display.cc"
|
||||
@@ -38,7 +39,7 @@ if(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI)
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ML307)
|
||||
set(BOARD_TYPE "bread-compact-ml307")
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ESP32)
|
||||
set(BOARD_TYPE "bread-compact-esp32")
|
||||
set(BOARD_TYPE "bread-compact-esp32")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_BOX_3)
|
||||
set(BOARD_TYPE "esp-box-3")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_BOX)
|
||||
@@ -48,7 +49,7 @@ elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_1)
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_2)
|
||||
set(BOARD_TYPE "kevin-box-2")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_C3)
|
||||
set(BOARD_TYPE "kevin-c3")
|
||||
set(BOARD_TYPE "kevin-c3")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V3_DEV)
|
||||
set(BOARD_TYPE "kevin-sp-v3-dev")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_YUYING_313LCD)
|
||||
@@ -72,13 +73,13 @@ elseif(CONFIG_BOARD_TYPE_ATOMS3_ECHO_BASE)
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMS3R_ECHO_BASE)
|
||||
set(BOARD_TYPE "atoms3r-echo-base")
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMMATRIX_ECHO_BASE)
|
||||
set(BOARD_TYPE "atommatrix-echo-base")
|
||||
set(BOARD_TYPE "atommatrix-echo-base")
|
||||
elseif(CONFIG_BOARD_TYPE_XMINI_C3)
|
||||
set(BOARD_TYPE "xmini-c3")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_KORVO2_V3)
|
||||
set(BOARD_TYPE "esp32s3-korvo2-v3")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_SPARKBOT)
|
||||
set(BOARD_TYPE "esp-sparkbot")
|
||||
set(BOARD_TYPE "esp-sparkbot")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_AMOLED_1_8)
|
||||
set(BOARD_TYPE "esp32-s3-touch-amoled-1.8")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_85C)
|
||||
@@ -88,21 +89,21 @@ elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_85)
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_46)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-1.46")
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_LCD)
|
||||
set(BOARD_TYPE "bread-compact-wifi-lcd")
|
||||
set(BOARD_TYPE "bread-compact-wifi-lcd")
|
||||
elseif(CONFIG_BOARD_TYPE_TUDOUZI)
|
||||
set(BOARD_TYPE "tudouzi")
|
||||
set(BOARD_TYPE "tudouzi")
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CIRCLE_S3)
|
||||
set(BOARD_TYPE "lilygo-t-circle-s3")
|
||||
set(BOARD_TYPE "lilygo-t-circle-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3)
|
||||
set(BOARD_TYPE "lilygo-t-cameraplus-s3")
|
||||
set(BOARD_TYPE "lilygo-t-cameraplus-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_MOVECALL_MOJI_ESP32S3)
|
||||
set(BOARD_TYPE "movecall-moji-esp32s3")
|
||||
set(BOARD_TYPE "movecall-moji-esp32s3")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3)
|
||||
set(BOARD_TYPE "atk-dnesp32s3")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box")
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box")
|
||||
elseif(CONFIG_BOARD_TYPE_DU_CHATX)
|
||||
set(BOARD_TYPE "du-chatx")
|
||||
set(BOARD_TYPE "du-chatx")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Taiji_Pi)
|
||||
set(BOARD_TYPE "taiji-pi-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_96OLED_WIFI)
|
||||
@@ -116,7 +117,7 @@ elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_1_54TFT_ML307)
|
||||
elseif(CONFIG_BOARD_TYPE_SENSECAP_WATCHER)
|
||||
set(BOARD_TYPE "sensecap-watcher")
|
||||
endif()
|
||||
file(GLOB BOARD_SOURCES
|
||||
file(GLOB BOARD_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.c
|
||||
)
|
||||
@@ -173,7 +174,7 @@ add_custom_command(
|
||||
COMMAND python ${PROJECT_DIR}/scripts/gen_lang.py
|
||||
--input "${LANG_JSON}"
|
||||
--output "${LANG_HEADER}"
|
||||
DEPENDS
|
||||
DEPENDS
|
||||
${LANG_JSON}
|
||||
${PROJECT_DIR}/scripts/gen_lang.py
|
||||
COMMENT "Generating ${LANG_DIR} language config"
|
||||
|
||||
235
main/led/gpio_led.cc
Normal file
235
main/led/gpio_led.cc
Normal file
@@ -0,0 +1,235 @@
|
||||
#include "gpio_led.h"
|
||||
#include "application.h"
|
||||
#include <esp_log.h>
|
||||
|
||||
#define TAG "GpioLed"
|
||||
|
||||
#define DEFAULT_BRIGHTNESS 50
|
||||
#define HIGH_BRIGHTNESS 100
|
||||
#define LOW_BRIGHTNESS 10
|
||||
|
||||
#define IDLE_BRIGHTNESS 5
|
||||
#define SPEAKING_BRIGHTNESS 75
|
||||
#define UPGRADING_BRIGHTNESS 25
|
||||
#define ACTIVATING_BRIGHTNESS 35
|
||||
|
||||
#define BLINK_INFINITE -1
|
||||
|
||||
// GPIO_LED
|
||||
#define LEDC_LS_TIMER LEDC_TIMER_1
|
||||
#define LEDC_LS_MODE LEDC_LOW_SPEED_MODE
|
||||
#define LEDC_LS_CH0_CHANNEL LEDC_CHANNEL_0
|
||||
|
||||
#define LEDC_DUTY (4096)
|
||||
#define LEDC_FADE_TIME (1000)
|
||||
// GPIO_LED
|
||||
|
||||
GpioLed::GpioLed(gpio_num_t gpio, int output_invert) {
|
||||
// If the gpio is not connected, you should use NoLed class
|
||||
assert(gpio != GPIO_NUM_NC);
|
||||
|
||||
/*
|
||||
* Prepare and set configuration of timers
|
||||
* that will be used by LED Controller
|
||||
*/
|
||||
ledc_timer_config_t ledc_timer = {};
|
||||
ledc_timer.duty_resolution = LEDC_TIMER_13_BIT; // resolution of PWM duty
|
||||
ledc_timer.freq_hz = 4000; // frequency of PWM signal
|
||||
ledc_timer.speed_mode = LEDC_LS_MODE; // timer mode
|
||||
ledc_timer.timer_num = LEDC_LS_TIMER; // timer index
|
||||
ledc_timer.clk_cfg = LEDC_AUTO_CLK; // Auto select the source clock
|
||||
|
||||
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
|
||||
|
||||
ledc_channel_.channel = LEDC_LS_CH0_CHANNEL,
|
||||
ledc_channel_.duty = 0,
|
||||
ledc_channel_.gpio_num = gpio,
|
||||
ledc_channel_.speed_mode = LEDC_LS_MODE,
|
||||
ledc_channel_.hpoint = 0,
|
||||
ledc_channel_.timer_sel = LEDC_LS_TIMER,
|
||||
ledc_channel_.flags.output_invert = output_invert & 0x01,
|
||||
|
||||
// Set LED Controller with previously prepared configuration
|
||||
ledc_channel_config(&ledc_channel_);
|
||||
|
||||
// Initialize fade service.
|
||||
ledc_fade_func_install(0);
|
||||
|
||||
// When the callback registered by ledc_cb_degister is called, run led ->OnFadeEnd()
|
||||
ledc_cbs_t ledc_callbacks = {
|
||||
.fade_cb = FadeCallback
|
||||
};
|
||||
ledc_cb_register(ledc_channel_.speed_mode, ledc_channel_.channel, &ledc_callbacks, this);
|
||||
|
||||
esp_timer_create_args_t blink_timer_args = {
|
||||
.callback = [](void *arg) {
|
||||
auto led = static_cast<GpioLed*>(arg);
|
||||
led->OnBlinkTimer();
|
||||
},
|
||||
.arg = this,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "Blink Timer",
|
||||
.skip_unhandled_events = false,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&blink_timer_args, &blink_timer_));
|
||||
|
||||
ledc_initialized_ = true;
|
||||
}
|
||||
|
||||
GpioLed::~GpioLed() {
|
||||
esp_timer_stop(blink_timer_);
|
||||
if (ledc_initialized_) {
|
||||
ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
|
||||
ledc_fade_func_uninstall();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GpioLed::SetBrightness(uint8_t brightness) {
|
||||
duty_ = brightness * LEDC_DUTY / 100;
|
||||
}
|
||||
|
||||
void GpioLed::TurnOn() {
|
||||
if (!ledc_initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(blink_timer_);
|
||||
ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
|
||||
ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, duty_);
|
||||
ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel);
|
||||
}
|
||||
|
||||
void GpioLed::TurnOff() {
|
||||
if (!ledc_initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(blink_timer_);
|
||||
ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
|
||||
ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, 0);
|
||||
ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel);
|
||||
}
|
||||
|
||||
void GpioLed::BlinkOnce() {
|
||||
Blink(1, 100);
|
||||
}
|
||||
|
||||
void GpioLed::Blink(int times, int interval_ms) {
|
||||
StartBlinkTask(times, interval_ms);
|
||||
}
|
||||
|
||||
void GpioLed::StartContinuousBlink(int interval_ms) {
|
||||
StartBlinkTask(BLINK_INFINITE, interval_ms);
|
||||
}
|
||||
|
||||
void GpioLed::StartBlinkTask(int times, int interval_ms) {
|
||||
if (!ledc_initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(blink_timer_);
|
||||
ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
|
||||
|
||||
blink_counter_ = times * 2;
|
||||
blink_interval_ms_ = interval_ms;
|
||||
esp_timer_start_periodic(blink_timer_, interval_ms * 1000);
|
||||
}
|
||||
|
||||
void GpioLed::OnBlinkTimer() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
blink_counter_--;
|
||||
if (blink_counter_ & 1) {
|
||||
ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, duty_);
|
||||
} else {
|
||||
ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, 0);
|
||||
|
||||
if (blink_counter_ == 0) {
|
||||
esp_timer_stop(blink_timer_);
|
||||
}
|
||||
}
|
||||
ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel);
|
||||
}
|
||||
|
||||
void GpioLed::StartFadeTask() {
|
||||
if (!ledc_initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
esp_timer_stop(blink_timer_);
|
||||
ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
|
||||
fade_up_ = true;
|
||||
ledc_set_fade_with_time(ledc_channel_.speed_mode,
|
||||
ledc_channel_.channel, LEDC_DUTY, LEDC_FADE_TIME);
|
||||
ledc_fade_start(ledc_channel_.speed_mode,
|
||||
ledc_channel_.channel, LEDC_FADE_NO_WAIT);
|
||||
}
|
||||
|
||||
void GpioLed::OnFadeEnd() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
fade_up_ = !fade_up_;
|
||||
ledc_set_fade_with_time(ledc_channel_.speed_mode,
|
||||
ledc_channel_.channel, fade_up_ ? LEDC_DUTY : 0, LEDC_FADE_TIME);
|
||||
ledc_fade_start(ledc_channel_.speed_mode,
|
||||
ledc_channel_.channel, LEDC_FADE_NO_WAIT);
|
||||
}
|
||||
|
||||
bool GpioLed::FadeCallback(const ledc_cb_param_t *param, void *user_arg) {
|
||||
if (param->event == LEDC_FADE_END_EVT) {
|
||||
auto led = static_cast<GpioLed*>(user_arg);
|
||||
led->OnFadeEnd();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GpioLed::OnStateChanged() {
|
||||
auto& app = Application::GetInstance();
|
||||
auto device_state = app.GetDeviceState();
|
||||
switch (device_state) {
|
||||
case kDeviceStateStarting:
|
||||
SetBrightness(DEFAULT_BRIGHTNESS);
|
||||
StartContinuousBlink(100);
|
||||
break;
|
||||
case kDeviceStateWifiConfiguring:
|
||||
SetBrightness(DEFAULT_BRIGHTNESS);
|
||||
StartContinuousBlink(500);
|
||||
break;
|
||||
case kDeviceStateIdle:
|
||||
SetBrightness(IDLE_BRIGHTNESS);
|
||||
TurnOn();
|
||||
// TurnOff();
|
||||
break;
|
||||
case kDeviceStateConnecting:
|
||||
SetBrightness(DEFAULT_BRIGHTNESS);
|
||||
TurnOn();
|
||||
break;
|
||||
case kDeviceStateListening:
|
||||
if (app.IsVoiceDetected()) {
|
||||
SetBrightness(HIGH_BRIGHTNESS);
|
||||
} else {
|
||||
SetBrightness(LOW_BRIGHTNESS);
|
||||
}
|
||||
// TurnOn();
|
||||
StartFadeTask();
|
||||
break;
|
||||
case kDeviceStateSpeaking:
|
||||
SetBrightness(SPEAKING_BRIGHTNESS);
|
||||
TurnOn();
|
||||
break;
|
||||
case kDeviceStateUpgrading:
|
||||
SetBrightness(UPGRADING_BRIGHTNESS);
|
||||
StartContinuousBlink(100);
|
||||
break;
|
||||
case kDeviceStateActivating:
|
||||
SetBrightness(ACTIVATING_BRIGHTNESS);
|
||||
StartContinuousBlink(500);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unknown gpio led event: %d", device_state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
45
main/led/gpio_led.h
Normal file
45
main/led/gpio_led.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef _GPIO_LED_H_
|
||||
#define _GPIO_LED_H_
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "led.h"
|
||||
#include <driver/gpio.h>
|
||||
#include <driver/ledc.h>
|
||||
#include <esp_timer.h>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
class GpioLed : public Led {
|
||||
public:
|
||||
GpioLed(gpio_num_t gpio, int output_invert=0);
|
||||
virtual ~GpioLed();
|
||||
|
||||
void OnStateChanged() override;
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
TaskHandle_t blink_task_ = nullptr;
|
||||
ledc_channel_config_t ledc_channel_ = {0};
|
||||
bool ledc_initialized_ = false;
|
||||
uint32_t duty_ = 0;
|
||||
int blink_counter_ = 0;
|
||||
int blink_interval_ms_ = 0;
|
||||
esp_timer_handle_t blink_timer_ = nullptr;
|
||||
bool fade_up_ = true;
|
||||
|
||||
void StartBlinkTask(int times, int interval_ms);
|
||||
void OnBlinkTimer();
|
||||
|
||||
void BlinkOnce();
|
||||
void Blink(int times, int interval_ms);
|
||||
void StartContinuousBlink(int interval_ms);
|
||||
void TurnOn();
|
||||
void TurnOff();
|
||||
void SetBrightness(uint8_t brightness);
|
||||
void StartFadeTask();
|
||||
void OnFadeEnd();
|
||||
static bool FadeCallback(const ledc_cb_param_t *param, void *user_arg);
|
||||
};
|
||||
|
||||
#endif // _GPIO_LED_H_
|
||||
Reference in New Issue
Block a user