From 799302e1e6acad559db510ec2268f6560283e3c4 Mon Sep 17 00:00:00 2001 From: Y1hsiaochunnn <66012385+Y1hsiaochunnn@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:25:11 +0800 Subject: [PATCH] Added functionality to Waveshare ESP32-S3-Touch-AMOLED-1.8 (#228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added functionality to Waveshare ESP32-S3-Touch-AMOLED-1.8 * Update board_control.cc 不要提交没有使用的功能到main分支 --------- Co-authored-by: Xiaoxia --- .../esp32-s3-touch-amoled-1.8/axp2101.cc | 59 +++++++++++++ .../esp32-s3-touch-amoled-1.8/axp2101.h | 19 +++++ .../board_control.cc | 50 +++++++++++ .../boards/esp32-s3-touch-amoled-1.8/config.h | 1 + .../esp32-s3-touch-amoled-1.8.cc | 82 +++++++++++++++++++ 5 files changed, 211 insertions(+) create mode 100644 main/boards/esp32-s3-touch-amoled-1.8/axp2101.cc create mode 100644 main/boards/esp32-s3-touch-amoled-1.8/axp2101.h create mode 100644 main/boards/esp32-s3-touch-amoled-1.8/board_control.cc diff --git a/main/boards/esp32-s3-touch-amoled-1.8/axp2101.cc b/main/boards/esp32-s3-touch-amoled-1.8/axp2101.cc new file mode 100644 index 00000000..b905f8b3 --- /dev/null +++ b/main/boards/esp32-s3-touch-amoled-1.8/axp2101.cc @@ -0,0 +1,59 @@ +#include "axp2101.h" +#include "board.h" +#include "display.h" + +#include + +#define TAG "Axp2101" + +Axp2101::Axp2101(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { + // ** EFUSE defaults ** + WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable + WriteReg(0x27, 0x10); // hold 4s to power off + + WriteReg(0x93, 0x1C); // 配置 aldo2 输出为 3.3V + + uint8_t value = ReadReg(0x90); // XPOWERS_AXP2101_LDO_ONOFF_CTRL0 + value = value | 0x02; // set bit 1 (ALDO2) + WriteReg(0x90, value); // and power channels now enabled + + WriteReg(0x64, 0x03); // CV charger voltage setting to 4.2V + + WriteReg(0x61, 0x05); // set Main battery precharge current to 125mA + WriteReg(0x62, 0x0A); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) + WriteReg(0x63, 0x15); // set Main battery term charge current to 125mA + + WriteReg(0x14, 0x00); // set minimum system voltage to 4.1V (default 4.7V), for poor USB cables + WriteReg(0x15, 0x00); // set input voltage limit to 3.88v, for poor USB cables + WriteReg(0x16, 0x05); // set input current limit to 2000mA + + WriteReg(0x24, 0x01); // set Vsys for PWROFF threshold to 3.2V (default - 2.6V and kill battery) + WriteReg(0x50, 0x14); // set TS pin to EXTERNAL input (not temperature) +} + +int Axp2101::GetBatteryCurrentDirection() { + return (ReadReg(0x01) & 0b01100000) >> 5; +} + +bool Axp2101::IsCharging() { + return GetBatteryCurrentDirection() == 1; +} + +bool Axp2101::IsDischarging() { + return GetBatteryCurrentDirection() == 2; +} + +bool Axp2101::IsChargingDone() { + uint8_t value = ReadReg(0x01); + return (value & 0b00000111) == 0b00000100; +} + +int Axp2101::GetBatteryLevel() { + return ReadReg(0xA4); +} + +void Axp2101::PowerOff() { + uint8_t value = ReadReg(0x10); + value = value | 0x01; + WriteReg(0x10, value); +} diff --git a/main/boards/esp32-s3-touch-amoled-1.8/axp2101.h b/main/boards/esp32-s3-touch-amoled-1.8/axp2101.h new file mode 100644 index 00000000..db9a497e --- /dev/null +++ b/main/boards/esp32-s3-touch-amoled-1.8/axp2101.h @@ -0,0 +1,19 @@ +#ifndef __AXP2101_H__ +#define __AXP2101_H__ + +#include "i2c_device.h" + +class Axp2101 : public I2cDevice { +public: + Axp2101(i2c_master_bus_handle_t i2c_bus, uint8_t addr); + bool IsCharging(); + bool IsDischarging(); + bool IsChargingDone(); + int GetBatteryLevel(); + void PowerOff(); + +private: + int GetBatteryCurrentDirection(); +}; + +#endif diff --git a/main/boards/esp32-s3-touch-amoled-1.8/board_control.cc b/main/boards/esp32-s3-touch-amoled-1.8/board_control.cc new file mode 100644 index 00000000..0630e4a5 --- /dev/null +++ b/main/boards/esp32-s3-touch-amoled-1.8/board_control.cc @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +#include "board.h" +#include "boards/common/wifi_board.h" +#include "boards/esp32-s3-touch-amoled-1.8/config.h" +#include "iot/thing.h" + +#define TAG "BoardControl" + +namespace iot { + +class BoardControl : public Thing { +public: + BoardControl() : Thing("BoardControl", "当前 AI 机器人管理和控制") { + // 添加电池电量属性 + properties_.AddNumberProperty("BatteryLevel", "当前电池电量百分比", [this]() -> int { + int level = 0; + bool charging = false; + Board::GetInstance().GetBatteryLevel(level, charging); + ESP_LOGI(TAG, "当前电池电量: %d%%, 充电状态: %s", level, charging ? "充电中" : "未充电"); + return level; + }); + + // 添加充电状态属性 + properties_.AddBooleanProperty("Charging", "是否正在充电", [this]() -> bool { + int level = 0; + bool charging = false; + Board::GetInstance().GetBatteryLevel(level, charging); + ESP_LOGI(TAG, "当前电池电量: %d%%, 充电状态: %s", level, charging ? "充电中" : "未充电"); + return charging; + }); + + // 修改重新配网 + methods_.AddMethod("ResetWifiConfiguration", "重新配网", ParameterList(), + [this](const ParameterList& parameters) { + ESP_LOGI(TAG, "ResetWifiConfiguration"); + auto board = static_cast(&Board::GetInstance()); + if (board && board->GetBoardType() == "wifi") { + board->ResetWifiConfiguration(); + } + }); + } +}; + +} // namespace iot + +DECLARE_THING(BoardControl); diff --git a/main/boards/esp32-s3-touch-amoled-1.8/config.h b/main/boards/esp32-s3-touch-amoled-1.8/config.h index ccb591ee..c9040537 100644 --- a/main/boards/esp32-s3-touch-amoled-1.8/config.h +++ b/main/boards/esp32-s3-touch-amoled-1.8/config.h @@ -17,6 +17,7 @@ #define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_14 #define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR +#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 #define BOOT_BUTTON_GPIO GPIO_NUM_0 #define EXAMPLE_PIN_NUM_LCD_CS GPIO_NUM_12 diff --git a/main/boards/esp32-s3-touch-amoled-1.8/esp32-s3-touch-amoled-1.8.cc b/main/boards/esp32-s3-touch-amoled-1.8/esp32-s3-touch-amoled-1.8.cc index 5824777c..fdc627a4 100644 --- a/main/boards/esp32-s3-touch-amoled-1.8/esp32-s3-touch-amoled-1.8.cc +++ b/main/boards/esp32-s3-touch-amoled-1.8/esp32-s3-touch-amoled-1.8.cc @@ -9,12 +9,15 @@ #include "led/single_led.h" #include "iot/thing_manager.h" #include "config.h" +#include "axp2101.h" +#include "i2c_device.h" #include #include #include #include #include +#include "esp_io_expander_tca9554.h" #define TAG "waveshare_amoled_1_8" @@ -65,8 +68,12 @@ public: class waveshare_amoled_1_8 : public WifiBoard { private: i2c_master_bus_handle_t codec_i2c_bus_; + Axp2101* axp2101_ = nullptr; + esp_timer_handle_t power_save_timer_ = nullptr; + Button boot_button_; LcdDisplay* display_; + esp_io_expander_handle_t io_expander = NULL; void InitializeCodecI2c() { // Initialize I2C peripheral @@ -85,6 +92,64 @@ private: ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); } + void InitializeTca9554(void) + { + esp_err_t ret = esp_io_expander_new_i2c_tca9554(codec_i2c_bus_, I2C_ADDRESS, &io_expander); + if(ret != ESP_OK) + ESP_LOGE(TAG, "TCA9554 create returned error"); + ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1 |IO_EXPANDER_PIN_NUM_2, IO_EXPANDER_OUTPUT); + ESP_ERROR_CHECK(ret); + ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1|IO_EXPANDER_PIN_NUM_2, 1); + ESP_ERROR_CHECK(ret); + vTaskDelay(pdMS_TO_TICKS(100)); + ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1|IO_EXPANDER_PIN_NUM_2, 0); + ESP_ERROR_CHECK(ret); + vTaskDelay(pdMS_TO_TICKS(300)); + ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1|IO_EXPANDER_PIN_NUM_2, 1); + ESP_ERROR_CHECK(ret); + } + + void InitializeAxp2101() { + // 使用 ESP_LOGI 宏记录信息日志,TAG 是日志标签,"Init AXP2101" 是日志信息 + ESP_LOGI(TAG, "Init AXP2101"); + // 创建一个新的 Axp2101 对象,该对象通过 I2C 总线 i2c_bus_ 和设备地址 0x34 进行初始化 + // axp2101_ 是一个指向 Axp2101 对象的指针 + axp2101_ = new Axp2101(codec_i2c_bus_, 0x34); + } + + void InitializePowerSaveTimer() { + esp_timer_create_args_t power_save_timer_args = { + .callback = [](void *arg) { + auto board = static_cast(arg); + board->PowerSaveCheck(); + }, + .arg = this, + .dispatch_method = ESP_TIMER_TASK, + .name = "Power Save Timer", + .skip_unhandled_events = false, + }; + ESP_ERROR_CHECK(esp_timer_create(&power_save_timer_args, &power_save_timer_)); + ESP_ERROR_CHECK(esp_timer_start_periodic(power_save_timer_, 1000000)); + } + + void PowerSaveCheck() { + // 电池放电模式下,如果待机超过一定时间,则自动关机 + const int seconds_to_shutdown = 600; + static int seconds = 0; + if (Application::GetInstance().GetDeviceState() != kDeviceStateIdle) { + seconds = 0; + return; + } + if (!axp2101_->IsDischarging()) { + seconds = 0; + return; + } + + seconds++; + if (seconds >= seconds_to_shutdown) { + axp2101_->PowerOff(); + } + } void InitializeSpi() { spi_bus_config_t buscfg = {}; buscfg.sclk_io_num = GPIO_NUM_11; @@ -152,15 +217,19 @@ private: void InitializeIot() { auto& thing_manager = iot::ThingManager::GetInstance(); thing_manager.AddThing(iot::CreateThing("Speaker")); + thing_manager.AddThing(iot::CreateThing("BoardControl")); } public: waveshare_amoled_1_8() : boot_button_(BOOT_BUTTON_GPIO) { InitializeCodecI2c(); + InitializeTca9554(); + InitializeAxp2101(); InitializeSpi(); InitializeSH8601Display(); InitializeButtons(); + InitializePowerSaveTimer(); InitializeIot(); } @@ -176,6 +245,19 @@ public: virtual Display* GetDisplay() override { return display_; } + + virtual bool GetBatteryLevel(int &level, bool& charging) override { + static int last_level = 0; + static bool last_charging = false; + level = axp2101_->GetBatteryLevel(); + charging = axp2101_->IsCharging(); + if (level != last_level || charging != last_charging) { + last_level = level; + last_charging = charging; + ESP_LOGI(TAG, "Battery level: %d, charging: %d", level, charging); + } + return true; + } }; DECLARE_BOARD(waveshare_amoled_1_8);