diff --git a/.gitignore b/.gitignore index 13f15f0..176e5c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ cmake-build-debug build +log .idea diff --git a/Lib/BAT_Driver/BAT_Driver.c b/Lib/BAT_Driver/BAT_Driver.c new file mode 100644 index 0000000..dfd69ba --- /dev/null +++ b/Lib/BAT_Driver/BAT_Driver.c @@ -0,0 +1,117 @@ +#include "BAT_Driver.h" + +const static char *ADC_TAG = "ADC"; + +float BAT_analogVolts = 0; + +/*--------------------------------------------------------------- + ADC Calibration +---------------------------------------------------------------*/ +static bool example_adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_cali_handle_t *out_handle) +{ + adc_cali_handle_t handle = NULL; + esp_err_t ret = ESP_FAIL; + bool calibrated = false; + +#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED + if (!calibrated) { + ESP_LOGI(ADC_TAG, "calibration scheme version is %s", "Curve Fitting"); + adc_cali_curve_fitting_config_t cali_config = { + .unit_id = unit, + .chan = channel, + .atten = atten, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle); + if (ret == ESP_OK) { + calibrated = true; + } + } +#endif + +#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED + if (!calibrated) { + ESP_LOGI(ADC_TAG, "calibration scheme version is %s", "Line Fitting"); + adc_cali_line_fitting_config_t cali_config = { + .unit_id = unit, + .atten = atten, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle); + if (ret == ESP_OK) { + calibrated = true; + } + } +#endif + + *out_handle = handle; + if (ret == ESP_OK) { + ESP_LOGI(ADC_TAG, "Calibration Success"); + } else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) { + ESP_LOGW(ADC_TAG, "eFuse not burnt, skip software calibration"); + } else { + ESP_LOGE(ADC_TAG, "Invalid arg or no memory"); + } + + return calibrated; +} + +// static void example_adc_calibration_deinit(adc_cali_handle_t handle) +// { +// #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED +// ESP_LOGI(ADC_TAG, "deregister %s calibration scheme", "Curve Fitting"); +// ESP_ERROR_CHECK(adc_cali_delete_scheme_curve_fitting(handle)); + +// #elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED +// ESP_LOGI(ADC_TAG, "deregister %s calibration scheme", "Line Fitting"); +// ESP_ERROR_CHECK(adc_cali_delete_scheme_line_fitting(handle)); +// #endif +// } + +adc_oneshot_unit_handle_t adc1_handle; +bool do_calibration1_chan3; +adc_cali_handle_t adc1_cali_chan3_handle = NULL; + +int adc_raw[2][10]; +int voltage[2][10]; +void ADC_Init(void) +{ + //-------------ADC1 Init---------------// + adc_oneshot_unit_init_cfg_t init_config1 = { + .unit_id = ADC_UNIT_1, + }; + ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); + + //-------------ADC1 Config---------------// + adc_oneshot_chan_cfg_t config = { + .atten = EXAMPLE_ADC_ATTEN, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN, &config)); + + //-------------ADC1 Calibration Init---------------// + do_calibration1_chan3 = example_adc_calibration_init(ADC_UNIT_1, EXAMPLE_ADC1_CHAN, EXAMPLE_ADC_ATTEN, &adc1_cali_chan3_handle); + + // //Tear Down + // ESP_ERROR_CHECK(adc_oneshot_del_unit(adc1_handle)); + // if (do_calibration1_chan3) { + // example_adc_calibration_deinit(adc1_cali_chan3_handle); + // } +} + +void BAT_Init(void) +{ + ADC_Init(); +} +float BAT_Get_Volts(void) +{ + adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN, &adc_raw[0][0]); + // printf( "ADC%d Channel[%d] Raw Data: %d\r\n", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN, adc_raw[0][0]); + if (do_calibration1_chan3) { + ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan3_handle, adc_raw[0][0], &voltage[0][0])); + // printf("ADC%d Channel[%d] Cali Voltage: %d mV\r\n", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN, voltage[0][0]); + BAT_analogVolts = (float)(voltage[0][0] * 3.0 / 1000.0) / Measurement_offset; + // printf("BAT voltage : %.2f V\r\n", BAT_analogVolts); + } + return BAT_analogVolts; +} \ No newline at end of file diff --git a/Lib/BAT_Driver/BAT_Driver.h b/Lib/BAT_Driver/BAT_Driver.h new file mode 100644 index 0000000..e86c281 --- /dev/null +++ b/Lib/BAT_Driver/BAT_Driver.h @@ -0,0 +1,21 @@ +#pragma once + +#include "esp_log.h" +#include "esp_adc/adc_oneshot.h" +#include "esp_adc/adc_cali.h" +#include "esp_adc/adc_cali_scheme.h" + + +/*--------------------------------------------------------------- + ADC General Macros +---------------------------------------------------------------*/ +//ADC1 Channels +#define EXAMPLE_ADC1_CHAN ADC_CHANNEL_7 +#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_12 // ADC_ATTEN_DB_12 + +#define Measurement_offset 0.994500 + +extern float BAT_analogVolts; + +void BAT_Init(void); +float BAT_Get_Volts(void); \ No newline at end of file diff --git a/build_flash_monitor.sh b/build_flash_monitor.sh index af228b8..97ce982 100755 --- a/build_flash_monitor.sh +++ b/build_flash_monitor.sh @@ -1,18 +1,25 @@ #!/usr/bin/env zsh -### 本脚本实现了Linux下的esp idf的一键编译,烧录,与监视,并且监视具有交互能力 -### Code by Misaki ---- 2025.8.22 +### 本脚本实现了 Linux 下 ESP-IDF 的一键编译、烧录与监视, +### 监视器内容会自动写入到脚本同目录 log/ 下的时间戳日志文件。 +### Code by Misaki ---- 2025.8.22 (Modified 2025.8.23) -# 如果 idf.py 不在 PATH,请 source export.sh 或手动 export IDF_PATH/PATH +# 如果 idf.py 不在 PATH,请事先 source export.sh 或手动 export IDF_PATH/PATH # source $HOME/Apps/esp/esp-idf/export.sh set -e # 任何一步失败就退出 PORT=${1:-/dev/ttyACM0} # 允许外部传参,默认 /dev/ttyACM0 +# 0) 准备日志目录与文件名 +SCRIPT_DIR=${0:a:h} # zsh 取脚本所在绝对目录 +LOG_DIR="$SCRIPT_DIR/log" +mkdir -p "$LOG_DIR" # 没有就自动创建 +LOG_FILE="$LOG_DIR/$(date +%Y_%m_%d_%H_%M_%S).log" + # 1) 实时 build + flash export PYTHONUNBUFFERED=1 idf.py -p "$PORT" build flash -# 2) 在外部 Konsole 打开 monitor (注意,这个地方要根据自己系统使用的终端来修改,我使用的是konsole + zsh -# --new-tab 在当前窗口新建标签页 -# --hold monitor 退出后不自动关窗口 -konsole --new-tab --hold -e zsh -c "idf.py -p $PORT monitor" \ No newline at end of file +# 2) 在外部 Konsole 打开 monitor,同时把内容实时写入 $LOG_FILE +# tee -a 追加写入,--hold 让窗口在 monitor 退出后保留 +konsole --new-tab --hold \ + -e zsh -c "idf.py -p $PORT monitor 2>&1 | tee -a '$LOG_FILE'" \ No newline at end of file diff --git a/main/Bionic_sphere.c b/main/Bionic_sphere.c index 8522429..53cd94d 100644 --- a/main/Bionic_sphere.c +++ b/main/Bionic_sphere.c @@ -8,5 +8,6 @@ void app_main(void) { - imu_test(); // imu测试 + // imu_test(); // imu测试 + battery_test(); } diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index e4587b9..8fa361b 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -2,8 +2,10 @@ idf_component_register(SRCS "Bionic_sphere.c" "../test/driver_test/drivers_test.c" # 测试用例 "../Lib/I2C_Driver/I2C_Driver.c" # IIC底层驱动库 "../Lib/QMI8658/QMI8658.c" # IMU驱动库 + "../Lib/BAT_Driver/BAT_Driver.c" # 电池adc驱动库 INCLUDE_DIRS "." "../test/driver_test" "../Lib/I2C_Driver" "../Lib/QMI8658" + "../Lib/BAT_Driver" ) diff --git a/test/driver_test/drivers_test.c b/test/driver_test/drivers_test.c index 7e451c7..7b710ea 100644 --- a/test/driver_test/drivers_test.c +++ b/test/driver_test/drivers_test.c @@ -5,8 +5,8 @@ #include -#include -#include +#include "I2C_Driver.h" +#include "QMI8658.h" extern IMUdata Accel; extern IMUdata Gyro; void imu_test(void) @@ -19,3 +19,27 @@ void imu_test(void) ESP_LOGD("app_main", "Gyro X: %f, Y: %f, Z: %f", Gyro.x, Gyro.y, Gyro.z); } } + +#include "BAT_Driver.h" +void battery_test(void) +{ + // 初始化电池驱动 + BAT_Init(); + + while(1) { + float voltage = BAT_Get_Volts(); + ESP_LOGI("BAT_TEST", "Battery Voltage: %.2f V", voltage); + + // 电池状态判断 + if (voltage > 4.0) { + ESP_LOGI("BAT_TEST", "Battery Status: Full"); + } else if (voltage > 3.7) { + ESP_LOGI("BAT_TEST", "Battery Status: Good"); + } else if (voltage > 3.4) { + ESP_LOGI("BAT_TEST", "Battery Status: Low"); + } else { + ESP_LOGI("BAT_TEST", "Battery Status: Critical"); + } + } + +} diff --git a/test/driver_test/drivers_test.h b/test/driver_test/drivers_test.h index a620b27..e82f319 100644 --- a/test/driver_test/drivers_test.h +++ b/test/driver_test/drivers_test.h @@ -8,5 +8,8 @@ // imu测试 void imu_test(void); +// 电池adc测试 +void battery_test(void); + #endif //BIONIC_SPHERE_DRIVERS_TEST_H \ No newline at end of file diff --git a/项目开发日志.md b/项目开发日志.md index 14b07ef..3245432 100644 --- a/项目开发日志.md +++ b/项目开发日志.md @@ -8,3 +8,10 @@ 实际完成任务: - [x] 1. 实现了Linux下的esp idf的一键编译,烧录,与监视,并且监视具有交互能力 - [x] 2. 测试了QMI8658的驱动,正常读出x,y,z轴数据,得到的pitch, roll, yaw正常 + +#### Day2 2025.8.23 +##### 主要目标:测试开发板官方提供的例程中的驱动能否使用 +实际完成任务: +- [x] 1. 测试了电池adc的驱动,正常读出数据,且电压与万用表示一致,测试通过 +- [ ] 2. + diff --git a/项目开发规划.md b/项目开发规划.md index e3e8728..a1ed1bc 100644 --- a/项目开发规划.md +++ b/项目开发规划.md @@ -20,22 +20,25 @@ 客户端架构:采用ESP32 IDF开发框架,充分发挥esp32s3的双核性能 客户端编程语言选择:C/C++混编 对于项目需求的初步实施过程: - - [ ] 封装宠物基类,实现通用模型加载与切换,宠物身份信息等 - - [ ] 进一步派生出宠物三个阶段的子类 - - [ ] 封装通信类,自定义报文,便于与服务端进行交互 - - [ ] 封装工具类,实现对外设的驱动,例如屏幕,语音输入输出,电源管理,OTA更新等 - - [ ] 封装屏幕UI类,提供一些基础的控件 - - [ ] 基于屏幕UI类进一步实现一个管理界面,方便用户快速配网,快速上手使用 + +- [ ] 封装宠物基类,实现通用模型加载与切换,宠物身份信息等 +- [ ] 进一步派生出宠物三个阶段的子类 +- [ ] 封装通信类,自定义报文,便于与服务端进行交互 +- [ ] 封装工具类,实现对外设的驱动,例如屏幕,语音输入输出,电源管理,OTA更新等 +- [ ] 封装屏幕UI类,提供一些基础的控件 +- [ ] 基于屏幕UI类进一步实现一个管理界面,方便用户快速配网,快速上手使用 服务端架构:优先采用Go开发框架做服务端底层(高性能支持) 后端API风格:优先RESTful API 对于项目需求的初步实施过程: - - [ ] 后端部分主要是实现一些向下的接口,To ESP32,例如身份鉴权,模型发送与切换,OTA更新等,需要相应客户端的各种请求。 - - [ ] 后端另一部分要实现一些向上的配置接口,提供给Web管理端使用,这一部分只是为了方便项目的后期维护使用。 - - [ ] 实现一个或多个客户端的管理 - - [ ] 可选是否支持服务端自部署,也就是用户自部署服务端(待服务端完成后) + +- [ ] 后端部分主要是实现一些向下的接口,To ESP32,例如身份鉴权,模型发送与切换,OTA更新等,需要相应客户端的各种请求。 +- [ ] 后端另一部分要实现一些向上的配置接口,提供给Web管理端使用,这一部分只是为了方便项目的后期维护使用。 +- [ ] 实现一个或多个客户端的管理 +- [ ] 可选是否支持服务端自部署,也就是用户自部署服务端(待服务端完成后) #### 项目周期 + 1. 首先会在2~4天内实现最基本的客户端模型(gif)显示,以及esp32相关的外设驱动验证(验证+测试) 2. 接着在1周左右完成客户端的全部实施过程,同时着手服务端的设计 3. 在一周左右完成服务端向下接口的封装,尽量优化服务端架构(因为需要调用各种大模型或者本地部署的模型,以及其他的各种API),提高服务端响应速度 diff --git a/项目部署说明.md b/项目部署说明.md new file mode 100644 index 0000000..9b6f387 --- /dev/null +++ b/项目部署说明.md @@ -0,0 +1,90 @@ +## 项目部署说明 + +#### 此文件用于说明如何部署本项目 + +#### 部署步骤 + +- 安装对应平台的esp idf环境 +- 简单修改一个或者多个项目的配置文件以适配自己的平台 + +#### 演示平台 +- CPU: AMD R5 3600 +- 系统: Kubuntu 24.04 +- 终端: zsh +- IDE: Clion2025.2 + +#### 主要参考教程 +- [esp-idf官方教程](https://docs.espressif.com/projects/esp-idf/zh_CN/release-v5.3/esp32s3/get-started/linux-macos-setup.html) + + +#### 部署步骤 +前置: 安装Clion 2025.2, 此IDE非商业免费 + +参考官方教程中给出的步骤(主要是从源码编译idf),因此对于不同的平台,有不同的安装方式 +对于windows来说,只需要下载对应版本的已经编译好的idf可执行文件即可,可以参考我bilibili录制的教程 +[【Misaki】ESP-32 IDF Clion开发环境搭建](https://www.bilibili.com/video/BV1Q7epebEbb) + +而开发环境使用的系统为Kubuntu 24.0,为Linux环境,在此给出Linux环境下的项目部署步骤 +1. 编译 ESP-IDF 需要以下软件包。请根据使用的 Linux 发行版本,下面给出的是Ubuntu 和 Debian的安装命令。 + ```bash + sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 + ``` + +2. 获取 ESP-IDF,获取 ESP-IDF 的本地副本,在终端中执行下面的命令,注意选择合适的安装目录 + ```bash + mkdir -p ~/esp + cd ~/esp + git clone -b release/v5.3 --recursive https://github.com/espressif/esp-idf.git + ``` + +3. 为idf的环境创建一个快速启动,因为idf框架下包含了非常多的组件,需要添加一些环境变量,为了不污染系统环境变量,我们可以执行以下操作 + + 1. 复制并粘贴以下命令到 shell 配置文件中(.profile、.bashrc、.zprofile 等),我使用的是zsh, 因此将此命令复制到.zshrc文件中 + + ```bash + # 注意这里的esp-idf的路径,请根据你的安装路径进行修改 + alias get_idf='. $HOME/esp/esp-idf/export.sh' + ``` + + `` + 这样当你打开一个新窗口就可以使用get_idf命令来快速启动idf环境了 + `` + +4. 设置工具 + 1. 除了 ESP-IDF 本身,还需要为支持 ESP32-S3 的项目安装 ESP-IDF 使用的各种工具,比如编译器、调试器、Python 包等。 + ```bash + cd ~/esp/esp-idf + ./install.sh all + ``` + + 2. 注意,如果你处在国内网络,那么可以先执行以下命令,再执行上面的步骤,以加速下载 + ```bash + export IDF_GITHUB_ASSETS="dl.espressif.cn/github_assets" + ``` + + +5. 创建并编译一个项目以完整下载idf框架下的所有组件 + + 1. 首先基于上一步的操作,打开一个新终端,输入get_idf以启动idf环境,接着输入下面的命令 + ```bash + idf.py create-project Demo # 创建一个名为Demo的项目 + cd Demo + + idf.py build # 编译项目,此时会自动去下载idf框架下的所有组件(如果是第一次使用) + ``` + 2. 注意,如果你处在国内网络,而且你的github无法clone仓库,那么可以先添加以下命添加代理(需要你拥有一个代理服务器,如Clash) + ```bash + git config --global http.proxy http://127.0.0.1:7890 # 设置代理,7890为代理端口,替换为你的代理服务器的端口 + git config --global https.proxy http://127.0.0.1:7890 + + # 如果需要取消代理,请执行以下命令 + git config --global --unset http.proxy + git config --global --unset https.proxy + ``` + 3. 到此所有需要下载的组件已经下载完毕,可以开始开发或者编译项目了 + +6. 针对Clion的一些配置 + 1. 将本项目使用Clion打开,接着在设置 -> 编译、执行、部署 -> 工具链 中新增一个工具链esp32 + 2. 点击添加环境,环境文件中放export.sh文件的路径, 例如:`/home/misaki/Apps/esp/esp-idf/export.sh` + 3. 接着在设置 -> 编译、执行、部署 -> CMake 中切换工具链为esp32,最后点击确定,此时项目会自动加载,CMake加载无报错即成功 + 4. 连接板子,选择flash_monitor_gui这个CMake应用,点击编译按钮即可一件启动编译、烧录、监视操作 \ No newline at end of file