Update to v1.9.4 (#1374)

* fix: Corrected the inverted touch screen parameter configuration of lichuang_S3_dev, which caused touch offset. (#1209)

* ci: support multiple variants per board (#1036)

* fix release.py

* OTTO 左右腿反了 (#1239)

* Change the button array to ADC buttons as in the board for esp32s3-korv2 (#1256)

* Change the button array to ADC buttons as in the board for esp32s3-korv2

* Add MuteVol function to control audio volume

* Optimize AdcBatteryMonitor to work without charge detection pin. (#1276)

Co-authored-by: Yuv Zhao <admin@yuvcloud.com>

* 修复charging_pin为NC充电时Battery Level不更新的问题 (#1316)

Co-authored-by: Yuv Zhao <admin@yuvcloud.com>

* Bump to 1.9.4

---------

Co-authored-by: ZhouShaoYuan <cnfalcon@qq.com>
Co-authored-by: laride <198868291+laride@users.noreply.github.com>
Co-authored-by: Toby <naivetoby@gmail.com>
Co-authored-by: masc2008 <masc2008@gmail.com>
Co-authored-by: konglingboy <konglingboy@sina.com>
Co-authored-by: Yuv Zhao <admin@yuvcloud.com>
This commit is contained in:
Xiaoxia
2025-11-04 05:03:40 +08:00
committed by GitHub
parent 5fd9e4273e
commit 3ced7709c6
8 changed files with 398 additions and 139 deletions

View File

@@ -3,32 +3,42 @@
AdcBatteryMonitor::AdcBatteryMonitor(adc_unit_t adc_unit, adc_channel_t adc_channel, float upper_resistor, float lower_resistor, gpio_num_t charging_pin)
: charging_pin_(charging_pin) {
// Initialize charging pin
gpio_config_t gpio_cfg = {
.pin_bit_mask = 1ULL << charging_pin,
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
ESP_ERROR_CHECK(gpio_config(&gpio_cfg));
// Initialize charging pin (only if it's not NC)
if (charging_pin_ != GPIO_NUM_NC) {
gpio_config_t gpio_cfg = {
.pin_bit_mask = 1ULL << charging_pin,
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
ESP_ERROR_CHECK(gpio_config(&gpio_cfg));
}
// Initialize ADC battery estimation
adc_battery_estimation_t adc_cfg = {
.internal = {
.adc_unit = adc_unit,
.adc_bitwidth = ADC_BITWIDTH_12,
.adc_bitwidth = ADC_BITWIDTH_DEFAULT,
.adc_atten = ADC_ATTEN_DB_12,
},
.adc_channel = adc_channel,
.upper_resistor = upper_resistor,
.lower_resistor = lower_resistor
};
adc_cfg.charging_detect_cb = [](void *user_data) -> bool {
AdcBatteryMonitor *self = (AdcBatteryMonitor *)user_data;
return gpio_get_level(self->charging_pin_) == 1;
};
adc_cfg.charging_detect_user_data = this;
// 在ADC配置部分进行条件设置
if (charging_pin_ != GPIO_NUM_NC) {
adc_cfg.charging_detect_cb = [](void *user_data) -> bool {
AdcBatteryMonitor *self = (AdcBatteryMonitor *)user_data;
return gpio_get_level(self->charging_pin_) == 1;
};
adc_cfg.charging_detect_user_data = this;
} else {
// 不设置回调让adc_battery_estimation库使用软件估算
adc_cfg.charging_detect_cb = nullptr;
adc_cfg.charging_detect_user_data = nullptr;
}
adc_battery_estimation_handle_ = adc_battery_estimation_create(&adc_cfg);
// Initialize timer
@@ -48,12 +58,29 @@ AdcBatteryMonitor::~AdcBatteryMonitor() {
if (adc_battery_estimation_handle_) {
ESP_ERROR_CHECK(adc_battery_estimation_destroy(adc_battery_estimation_handle_));
}
if (timer_handle_) {
esp_timer_stop(timer_handle_);
esp_timer_delete(timer_handle_);
}
}
bool AdcBatteryMonitor::IsCharging() {
bool is_charging = false;
ESP_ERROR_CHECK(adc_battery_estimation_get_charging_state(adc_battery_estimation_handle_, &is_charging));
return is_charging;
// 优先使用adc_battery_estimation库的功能
if (adc_battery_estimation_handle_ != nullptr) {
bool is_charging = false;
esp_err_t err = adc_battery_estimation_get_charging_state(adc_battery_estimation_handle_, &is_charging);
if (err == ESP_OK) {
return is_charging;
}
}
// 回退到GPIO读取或返回默认值
if (charging_pin_ != GPIO_NUM_NC) {
return gpio_get_level(charging_pin_) == 1;
}
return false;
}
bool AdcBatteryMonitor::IsDischarging() {
@@ -61,9 +88,17 @@ bool AdcBatteryMonitor::IsDischarging() {
}
uint8_t AdcBatteryMonitor::GetBatteryLevel() {
// 如果句柄无效,返回默认值
if (adc_battery_estimation_handle_ == nullptr) {
return 100;
}
float capacity = 0;
ESP_ERROR_CHECK(adc_battery_estimation_get_capacity(adc_battery_estimation_handle_, &capacity));
return capacity;
esp_err_t err = adc_battery_estimation_get_capacity(adc_battery_estimation_handle_, &capacity);
if (err != ESP_OK) {
return 100; // 出错时返回默认值
}
return (uint8_t)capacity;
}
void AdcBatteryMonitor::OnChargingStatusChanged(std::function<void(bool)> callback) {

View File

@@ -5,6 +5,7 @@
#include "button.h"
#include "config.h"
#include "i2c_device.h"
#include "assets/lang_config.h"
#include <esp_log.h>
#include <esp_lcd_panel_vendor.h>
@@ -16,6 +17,16 @@
#include "esp32_camera.h"
#define TAG "esp32s3_korvo2_v3"
/* ADC Buttons */
typedef enum {
BSP_ADC_BUTTON_REC,
BSP_ADC_BUTTON_VOL_MUTE,
BSP_ADC_BUTTON_PLAY,
BSP_ADC_BUTTON_SET,
BSP_ADC_BUTTON_VOL_DOWN,
BSP_ADC_BUTTON_VOL_UP,
BSP_ADC_BUTTON_NUM
} bsp_adc_button_t;
LV_FONT_DECLARE(font_puhui_20_4);
LV_FONT_DECLARE(font_awesome_20_4);
@@ -45,6 +56,10 @@ static const ili9341_lcd_init_cmd_t vendor_specific_init[] = {
class Esp32S3Korvo2V3Board : public WifiBoard {
private:
Button boot_button_;
Button* adc_button_[BSP_ADC_BUTTON_NUM];
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
adc_oneshot_unit_handle_t bsp_adc_handle = NULL;
#endif
i2c_master_bus_handle_t i2c_bus_;
LcdDisplay* display_;
esp_io_expander_handle_t io_expander_ = NULL;
@@ -131,7 +146,103 @@ private:
ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO));
}
void ChangeVol(int val) {
auto codec = GetAudioCodec();
auto volume = codec->output_volume() + val;
if (volume > 100) {
volume = 100;
}
if (volume < 0) {
volume = 0;
}
codec->SetOutputVolume(volume);
GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
}
void MuteVol() {
auto codec = GetAudioCodec();
auto volume = codec->output_volume();
if (volume > 1) {
volume = 0;
} else {
volume = 50;
}
codec->SetOutputVolume(volume);
GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
}
void InitializeButtons() {
button_adc_config_t adc_cfg = {};
adc_cfg.adc_channel = ADC_CHANNEL_4; // ADC1 channel 0 is GPIO5
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
const adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1,
};
adc_oneshot_new_unit(&init_config1, &bsp_adc_handle);
adc_cfg.adc_handle = &bsp_adc_handle;
#endif
adc_cfg.button_index = BSP_ADC_BUTTON_REC;
adc_cfg.min = 2310; // middle is 2410mV
adc_cfg.max = 2510;
adc_button_[0] = new AdcButton(adc_cfg);
adc_cfg.button_index = BSP_ADC_BUTTON_VOL_MUTE;
adc_cfg.min = 1880; // middle is 1980mV
adc_cfg.max = 2080;
adc_button_[1] = new AdcButton(adc_cfg);
adc_cfg.button_index = BSP_ADC_BUTTON_PLAY;
adc_cfg.min = 1550; // middle is 1650mV
adc_cfg.max = 1750;
adc_button_[2] = new AdcButton(adc_cfg);
adc_cfg.button_index = BSP_ADC_BUTTON_SET;
adc_cfg.min = 1015; // middle is 1115mV
adc_cfg.max = 1215;
adc_button_[3] = new AdcButton(adc_cfg);
adc_cfg.button_index = BSP_ADC_BUTTON_VOL_DOWN;
adc_cfg.min = 720; // middle is 820mV
adc_cfg.max = 920;
adc_button_[4] = new AdcButton(adc_cfg);
adc_cfg.button_index = BSP_ADC_BUTTON_VOL_UP;
adc_cfg.min = 280; // middle is 380mV
adc_cfg.max = 480;
adc_button_[5] = new AdcButton(adc_cfg);
auto volume_up_button = adc_button_[BSP_ADC_BUTTON_VOL_UP];
volume_up_button->OnClick([this]() {ChangeVol(10);});
volume_up_button->OnLongPress([this]() {
GetAudioCodec()->SetOutputVolume(100);
GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME);
});
auto volume_down_button = adc_button_[BSP_ADC_BUTTON_VOL_DOWN];
volume_down_button->OnClick([this]() {ChangeVol(-10);});
volume_down_button->OnLongPress([this]() {
GetAudioCodec()->SetOutputVolume(0);
GetDisplay()->ShowNotification(Lang::Strings::MUTED);
});
auto volume_mute_button = adc_button_[BSP_ADC_BUTTON_VOL_MUTE];
volume_mute_button->OnClick([this]() {MuteVol();});
auto play_button = adc_button_[BSP_ADC_BUTTON_PLAY];
play_button->OnClick([this]() {
ESP_LOGI(TAG, " TODO %s:%d\n", __func__, __LINE__);
});
auto set_button = adc_button_[BSP_ADC_BUTTON_SET];
set_button->OnClick([this]() {
ESP_LOGI(TAG, "TODO %s:%d\n", __func__, __LINE__);
});
auto rec_button = adc_button_[BSP_ADC_BUTTON_REC];
rec_button->OnClick([this]() {
ESP_LOGI(TAG, "TODO %s:%d\n", __func__, __LINE__);
});
boot_button_.OnClick([this]() {});
boot_button_.OnClick([this]() {
auto& app = Application::GetInstance();
if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) {

View File

@@ -173,8 +173,8 @@ private:
{
esp_lcd_touch_handle_t tp;
esp_lcd_touch_config_t tp_cfg = {
.x_max = DISPLAY_WIDTH,
.y_max = DISPLAY_HEIGHT,
.x_max = DISPLAY_HEIGHT,
.y_max = DISPLAY_WIDTH,
.rst_gpio_num = GPIO_NUM_NC, // Shared with LCD reset
.int_gpio_num = GPIO_NUM_NC,
.levels = {

View File

@@ -389,7 +389,7 @@ void Otto::ShakeLeg(int steps, int period, int dir) {
int homes[SERVO_COUNT] = {90, 90, 90, 90, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION};
// Changes in the parameters if left leg is chosen
if (dir == -1) {
if (dir == 1) {
shake_leg1[2] = 180 - 35;
shake_leg1[3] = 180 - 58;
shake_leg2[2] = 180 - 120;

View File

@@ -13,9 +13,9 @@ dependencies:
espressif/esp_io_expander_tca9554: ==2.0.0
espressif/esp_lcd_panel_io_additions: ^1.0.1
78/esp_lcd_nv3023: ~1.0.0
78/esp-wifi-connect: ~2.5.2
78/esp-wifi-connect: ~2.6.1
78/esp-opus-encoder: ~2.4.1
78/esp-ml307: ~3.3.5
78/esp-ml307: ~3.3.7
78/xiaozhi-fonts: ~1.5.2
espressif/led_strip: ~3.0.1
espressif/esp_codec_dev: ~1.4.0