# powermanager **Repository Path**: oneos-ability/powermanager ## Basic Information - **Project Name**: powermanager - **Description**: 电源管理组件是针对使用电池供电的智能表计终端推出的行业特色组件。此文档为电压管理框架 VoltageMonitor的用户使用手册。 - **Primary Language**: C - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-08-29 - **Last Updated**: 2024-03-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 电源管理框架使用手册 - [电源管理框架使用手册](#电源管理框架使用手册) - [电压管理框架——VoltageMonitor V1.3使用手册](#电压管理框架voltagemonitor-v13使用手册) - [一、简介](#一简介) - [二、工程配置](#二工程配置) - [1. 配置示例](#1-配置示例) - [2. 特殊配置说明](#2-特殊配置说明) - [3. flash分区说明](#3-flash分区说明) - [三、重要定义及数据结构](#三重要定义及数据结构) - [框架使能中可配置项类型](#框架使能中可配置项类型) - [温度修正回调类型](#温度修正回调类型) - [告警通知回调类型](#告警通知回调类型) - [四、VoltageMonitor API](#四voltagemonitor-api) - [基本接口](#基本接口) - [拓展接口](#拓展接口) - [五、使用方式](#五使用方式) - [六、使用示例](#六使用示例) - [七、注意与说明](#七注意与说明) - [电量管理框架——QuantityEstimator V1.0使用手册](#电量管理框架quantityestimator-v10使用手册) - [一、简介](#一简介-1) - [二、工程配置](#二工程配置-1) - [1. 配置示例](#1-配置示例-1) - [2. 特殊配置说明](#2-特殊配置说明-1) - [三、重要定义及数据结构](#三重要定义及数据结构-1) - [工作电流配置文件相关](#工作电流配置文件相关) - [四、QuantityEstimator API](#四quantityestimator-api) - [框架控制接口](#框架控制接口) - [查询接口](#查询接口) - [五、使用方式](#五使用方式-1) - [六、使用示例](#六使用示例-1) - [七、注意与说明](#七注意与说明-1) # 电压管理框架——VoltageMonitor V1.3使用手册 ## 一、简介 电源管理组件是针对使用电池供电的智能表计终端推出的行业特色组件。此文档为电压管理框架 `VoltageMonitor`的用户使用手册。 依赖:电压管理框架依赖如下,需确认是否支持 * ADC采集功能 * ADC-MCU内部温度采集(若使用温度修正功能需支持) 功能摘要:电压管理框架V1.3提供的功能主要如下 * 采样电池电压值 * 电池电压数据根据用户自定义温度修正函数、系数、基数进行电压值修正 * 电池电压报警,用户在设置电压告警值之后,若预设确认次数均低于告警电压,则主动通知用户应用层进行处理,防止因电池电量耗尽系统失效。 * 电池电压数据采集存储,写入flash,功能在将来会不断拓展。 * 历史电压数据查询功能, 单条查询及自定义数量查询 * 提供断电数据恢复功能 * 提供离线查看数据功能 V1.2更新内容: * flash写入功能更新,现各款MCU flash写入无需单独适配。 V1.3更新内容: * 温度获取现规范性使用驱动sensor框架进行获取。 --- ## 二、工程配置 ### 1. 配置示例 用户根据使用需求及软硬件环境,使能电压管理框架 `VoltageMonitor`,完成配置并保存,生成工程 > 组件路径:`(Top) → Components → PowerManager` ```c (Top) → Components→ PowerManager [*] Enable powermanager [*] Enable voltage monitor ------->电压管理框架使能 (adc) The device name of adc [battery voltage] ------->电池电压对应ADC设备名称 (11) ADC channel [battery voltage] ------->电池电压对应ADC通道 (sensor) on chip temperature sensor name ------->温度传感器对应设备名称 (5) ADC sampling recheck count ------->采样若低于阈值,数据确认次数 (5) Each time sampling, ADC sample times ------->单个电压数据生成所需采样取平均的样本个数 (10) voltage sampling duration with second. ------->采样间隔,单位[sec] (10) Maximum number of data to save. ------->最大保存数据历史条数 [*] Enable sampling data write to flash. ------->使能数据flash保存功能 (pm_vm) FAL part name ------->分区名称 (1024) Power Monitor task stack size ------->任务栈大小(通常无需修改) Power monitor log level (Output level [DEBUG]) ------->日志打印等级 ``` ### 2. 特殊配置说明 | NO. | 选项 | 说明 | | :-: | :-------------------- | :------------------------------------------------------------------------------------------------------------------------ | | 1 | 采样数据确认次数 | 在单次采样电压值低于阈值情况下,为确认立马进行重新采样次数(包括首次采样的总次数) | | 2 | 采样间隔 | 单位[sec], 正常触发两次电压测量间的间隔时间(非第1项中重新采样)。 | | 3 | 最大保存数据历史条数 | 历史数据最大记录条数,内存和flash通用。若达限值记录循环更新(即抛弃最早一条记录,添加一条最新数据) | | 4 | 使能数据flash保存功能 | 使能保存历史数据至flash功能 | | 5 | 分区名称 | 分区表中分区名称 | | 6 | 任务栈大小 | 通常无需修改 | | 7 | 日志打印等级 | 框架部分日志打印等级,若使能全部打印 `Output level [DEBUG]`可能需要调大任务栈大小及OS_TIMER栈大小(通常情况下无需修改) | > *注意* 一般情况请勿使能`Output level [DEBUG]`,若需开启请参考[注意与说明](#七注意与说明) ### 3. flash分区说明 如果用户有需求在关闭电压管理框架后仍需读取历史数据;或在再次开启本框架后,需恢复历史记录可选择开启flash写入功能。 flash写入功能为可选功能,于[menuconfig](#1-配置示例)中选择开启。开启此功能需要在分区表有对应分区。分区表默认位置于`工程目录\board\ports\fal_cfg.c`。 分区大小计算示例: 以`*最大保存数据历史条数=10`、`FLASH_PAGE_SIZE=0x800`和`page_size=8`(详见备注)示例。 1. 首先计算所需使用大小:固定头长度和数据长度分别按照`page_size`字节向上对其后的和的大小。即固定头长度[12]按照`page_size`字节对其后长度:`OS_ALIGN_UP(12, page_size)=16`,加上数据长度按照`page_size`字节对其后长度:`OS_ALIGN_UP(最大保存数据历史条数*sizeof(int32_t), page_size)=80`的和`(16+80)=96byte`。 2. 另查询到此MCU`FLASH_PAGE_SIZE(详见备注)`为 2048 Byte大小,此大小为flash最小擦除大小,分区大小不可低于此大小。 3. 故最小的分区大小取前两步计算后较大的 2048 Byte 即 0x800 Byte。 ```c static const fal_part_info_t fal_part_info[] = { /* part, flash, addr, size, lock */ { "pm_vm", "onchip_flash", 0x00080000, 0x00000800, FAL_PART_INFO_FLAGS_UNLOCKED}, }; ``` > *备注:* > > 1. `最大保存数据历史条数` 为 [menuconfig](#1-配置示例) 中 `最大保存数据历史条数(Maximum number of data to save)` > > 2. `工程目录\board\ports\flash_info.c`中定义了了`page_size`和`block_size`,另可由`block_size`查询到分区对应的`FLASH_PAGE_SIZE` > > 3. 有关分区详细规则请参考驱动文档示例。 --- ## 三、重要定义及数据结构 ### 框架使能中可配置项类型 可选配置项,供用户开启电压管理框架时自定义配置选项。可配置校准系数基数、工作间隔、自定义温度修正函数及自定义告警通知函数。 > 其中 `所有配置`均可置为空或赋0值 ```c typedef struct pm_vm_cfg { float calibration_coefficient; int32_t calibration_base; uint32_t sampling_duration_sec; pm_vm_temp_cb_t temp_correction_cb; pm_vm_notify_cb_t alert_notify_cb; } pm_vm_cfg_t; ``` | 重要成员 | 说明 | | :---------------------- | :---------------- | | calibration_coefficient | 电压校准系数 | | calibration_base | 电压校准基数 | | sampling_duration_sec | 采样工作间隔[sec] | | temp_correction_cb | 自定义温度修正函数 | | alert_notify_cb | 自定义告警通知函数 | > *注意* > > 电压校准公式如下,根据使用场景不同可以相应进行修改。 > > 校准电压 = 采样电压 \* 校准系数 \* 温度修正函数返回的温度修正系数 + 校准基数; ### 温度修正回调类型 框架使能接口中,可配置项里的温度修正函数指针类型。用户自定义的温度修正函数可以根据传入温度不同自定义返回温度修正系数。(用户通常需要根据温度进行分段或曲线温度修正) 请勿在回调中阻塞或进行耗时操作,否则在极端情况下会影响框架工作。 * [in] float 当前温度 * [out] float 修正系数 ```c typedef float (* pm_vm_temp_cb_t) (float temperature); ``` ### 告警通知回调类型 框架使能接口中,可配置项里的告警通知函数指针类型。当(多次确认)电压低于阈值时,框架调用此用户回调通知温度超限,并附带本次多次采样电压平均值。 请勿在回调中阻塞或进行耗时操作,否则在极端情况下会影响框架工作。 * [in] int32_t 当前电压 单位mv * [out] void 空 ```c typedef void (* pm_vm_notify_cb_t) (int32_t voltage); ``` --- ## 四、VoltageMonitor API ### 基本接口 #### **pm_voltage_monitor_on** 接口提供电压管理框架 `Voltage Monitor`开启功能。为方便用户使用,`Voltage Monitor`使能仅为一步操作,仅需要调用此API即可开启功能。此框架功能以单实例运行,其余接口仅在框架开启后生效。 ```c os_err_t pm_voltage_monitor_on(int32_t threshold_mv, pm_vm_cfg_t *optional_cfg); ``` | **参数** | **说明** | | :------------- | :--------------------------------- | | threshold_mv | 用户预设电压阈值,单位为毫伏[mV] | | optional_cfg | 可选配置项,若均无需设置,可置为空 | | **返回** | **说明** | | OS\_EOK | 成功 | | 非OS\_EOK | 失败 | > 可配置项详见[pm_vm_cfg_t](#pm_vm_cfg_t) > > 可选配置项这里提供两种方式设置: > > 1.仅在menuconfig里配置,可选配置项中内容若无需改动就在调用接口开启此项时置为空即可 > > 2.若手动开启时,某可选配置项需要临时改变,可由参数设置此项配置值,此时会优先采用参数传入配置(即不使用menuconfig里此项配置的值)。 #### **pm_voltage_monitor_off** 接口提供电压管理框架 `Voltage Monitor`关闭功能。为方便用户使用,`Voltage Monitor`关闭仅为一步操作,仅需要调用此API即可关闭功能。 ```c os_err_t pm_voltage_monitor_off(void); ``` | **参数** | **说明** | | :------------- | :------------- | | void | 空 | | **返回** | **说明** | | OS\_EOK | 成功 | | 非OS\_EOK | 失败 | #### **pm_vm_get_latest_data** 接口提供最近一条电压历史记录查询。接口返回电压值,单位[mV]。 ```c int32_t pm_vm_get_latest_data(void); ``` | **参数** | **说明** | | :------------- | :------------- | | void | 空 | | **返回** | **说明** | | < 0 | 获取错误 | | >= 0 | 电压值mV | #### **pm_vm_get_latest_data** 接口提供用户自定义条数电压历史记录查询。接口返回成功获取的历史记录条数。 ```c int32_t pm_vm_get_history_data(int32_t *data_array, os_size_t history_count); ``` | **参数** | **说明** | | :------------- | :----------------------------------------------------- | | data_array | 用户buffer,用于接收历史电压记录[int32_t *]类型指针 | | history_count | buffer可存历史条数 | | **返回** | **说明** | | < 0 | 获取错误 | | >= 0 | 实际写入历史记录条数 | ### 拓展接口 #### **pm_vm_set_voltage_threshold** 接口提供框架开启后更新电压阈值功能。用户可根据实际需求在使用中更新电压阈值。 ```c os_err_t pm_vm_set_voltage_threshold(int32_t threshold_mv); ``` | **参数** | **说明** | | :------------- | :----------------- | | threshold_mv | 电压阈值,单位[mV] | | **返回** | **说明** | | OS\_EOK | 成功 | | 非OS\_EOK | 失败 | #### **pm_vm_set_calibration_coefficient** 接口提供框架开启后更新电压校准系数功能。用户可根据实际需求在使用中更新电压校准系数。 ```c os_err_t pm_vm_set_calibration_coefficient(float calibration_coefficient); ``` | **参数** | **说明** | | :---------------------- | :------------------------ | | calibration_coefficient | 电压校准系数,类型[float] | | **返回** | **说明** | | OS\_EOK | 成功 | | 非OS\_EOK | 失败 | #### **pm_vm_set_calibration_base** 接口提供框架开启后更新电压校准基数功能。用户可根据实际需求在使用中更新电压校准基数。 ```c os_err_t pm_vm_set_calibration_base(int32_t calibration_base); ``` | **参数** | **说明** | | :---------------------- | :----------------------------- | | calibration_coefficient | 电压校准基数,类型[int32_t] | | **返回** | **说明** | | OS\_EOK | 成功 | | 非OS\_EOK | 失败 | #### **pm_vm_set_temp_correction_cb** 接口提供框架开启后更新自定义温度修正函数功能。用户可根据实际需求在使用中更新。若无需进行温度修正,将其置为空,可关闭温度修正功能。 ```c os_err_t pm_vm_set_temp_correction_cb(pm_vm_temp_cb_t temp_correction_cb); ``` | **参数** | **说明** | | :----------------- | :--------------- | | temp_correction_cb | 温度修正函数指针 | | **返回** | **说明** | | OS\_EOK | 成功 | | 非OS\_EOK | 失败 | ## 五、使用方式 > 调用API编译烧录即可 ## 六、使用示例 ```c #include #ifdef PM_USING_VOLTAGE_MONITOR #include #include #include #include #include /***************************************************************************** * init configuration * *****************************************************************************/ #define VM_CAL_COEFFICIENT (1.12) #define VM_CAL_BASE (12) #define VM_DURATION (10) #define VM_VOLTAGE_THRESHOLD (3301) #define TEST_LOG(fmt, ...) printf("[TEST_LOG] %s-%d: " fmt "\r\n", __func__, __LINE__, ##__VA_ARGS__); float temp_cb(float temperature) { TEST_LOG("temperature: %f", temperature); return (temperature >= 21) ? 0.3 : 2.1; } void aleart_cb(int32_t voltage) { TEST_LOG("aleart voltage:%d", voltage); } os_err_t voltage_monitor_on(int32_t argc, char **argv) { pm_vm_cfg_t cfg = { .calibration_coefficient = VM_CAL_COEFFICIENT, .calibration_base = VM_CAL_BASE, .sampling_duration_sec = VM_DURATION, .temp_correction_cb = temp_cb, .alert_notify_cb = aleart_cb, }; os_err_t result = pm_voltage_monitor_on(VM_VOLTAGE_THRESHOLD, &cfg); TEST_LOG("%s", OS_SUCCESS == result ? "SUCCESS" : "FAILED"); return result; } SH_CMD_EXPORT(pm_vm_on, voltage_monitor_on, "voltage monitor on"); os_err_t voltage_monitor_off(int32_t argc, char **argv) { os_err_t result = pm_voltage_monitor_off(); TEST_LOG("%s", OS_SUCCESS == result ? "SUCCESS" : "FAILED"); return result; } SH_CMD_EXPORT(pm_vm_off, voltage_monitor_off, "voltage monitor off"); os_err_t vm_get_latest_data(int32_t argc, char **argv) { int data = pm_vm_get_latest_data(); TEST_LOG("Voltage[%d]-%s", data, (0 < data) ? "SUCCESS" : "FAILED"); return OS_SUCCESS; } SH_CMD_EXPORT(pm_vm_data, vm_get_latest_data, "vm get latest data"); os_err_t vm_get_history_data(int32_t argc, char **argv) { int cnt = 0; int history[PM_VM_DATA_MAX] = {0}; cnt = pm_vm_get_history_data(history, PM_VM_DATA_MAX); printf("Voltage history - "); for (int i = 0; i < PM_VM_DATA_MAX; i++) { printf("[%d] ", history[i]); } printf("\r\n"); return (0 >= cnt) ? OS_FAILURE : OS_SUCCESS; } SH_CMD_EXPORT(pm_vm_history, vm_get_history_data, "vm get history data"); os_err_t vm_update_configure(int32_t argc, char **argv) { os_err_t result = OS_SUCCESS; result = pm_vm_set_voltage_threshold(32); TEST_LOG("pm_vm_set_voltage_threshold-%s", (OS_SUCCESS == result) ? "SUCCESS" : "FAILED"); result = pm_vm_set_calibration_coefficient(1.2); TEST_LOG("pm_vm_set_calibration_coefficient-%s", (OS_SUCCESS == result) ? "SUCCESS" : "FAILED"); result = pm_vm_set_calibration_base(-1); TEST_LOG("pm_vm_set_calibration_base-%s", (OS_SUCCESS == result) ? "SUCCESS" : "FAILED"); result = pm_vm_set_temp_correction_cb(OS_NULL); TEST_LOG("pm_vm_set_temp_correction_cb-%s", (OS_SUCCESS == result) ? "SUCCESS" : "FAILED"); return OS_SUCCESS; } SH_CMD_EXPORT(pm_vm_config, vm_update_configure, "vm update configuration"); os_err_t vm_clear_history() { os_err_t result = pm_vm_clear_history(); TEST_LOG("%s", OS_SUCCESS == result ? "SUCCESS" : "FAILED"); return result; } SH_CMD_EXPORT(pm_vm_clear, vm_clear_history, "vm clear history"); #endif /* PM_USING_VOLTAGE_MONITOR */ ``` ## 七、注意与说明 * 请勿在回调中阻塞或进行耗时操作,否则在极端情况下会影响框架工作。 * 所有电压返回类型均为mV为单位。 * 若使能日志的`调试`打印等级`Output level [DEBUG]`, 需要调大任务栈大小(根据实际情况)及OS_TIMER栈大小(参考值640),否则可能会产生异常错误。 * V1.2版本为试验版本,测试使用中如有额外需求或是根据项目应用需作出调整,可与开发联系修改。 --- # 电量管理框架——QuantityEstimator V1.0使用手册 ## 一、简介 电量管理组件是针对使用电池供电的智能表计终端推出的行业特色组件。此文档为电量管理框架`QuantityEstimator`的用户使用手册。 依赖:电量管理框架依赖如下,需确认是否支持 * RTC 电量管理框架V1.0提供的功能主要如下: * 开启期间记录用户关注的各个设备工作时间,并根据此估算设备运行时间的电量消耗 * 获取已使用电量估算值 * 获取安全电量内可用剩余电量估算值 * 判断电池是否电量不足 * 可支持电池更换情况,重设电池数据 * 低内存占用 --- ## 二、工程配置 ### 1. 配置示例 用户根据使用需求及软硬件环境,使能电量管理框架`QuantityEstimator`,完成配置并保存,生成工程 > 组件路径:`(Top) → Components → PowerManager` ```c (Top) → Components→ PowerManager [*] Enable quantity estimator ------->电量管理框架使能 Voltage Monitor configuration ------->电量管理框架配置项 [*] Auto start quantity estimator when OS srart. ------->电量管理框架配置自动启动使能 (9999) Battery capacity[mAh] ------->电量管理框架默认电池电量 (30) Low power percentage[%] ------->电量管理框架电池低电量所处百分比 Quantity estimator log level (Output level [DEBUG])--->日志打印等级 ``` > *注意:* > > `电量管理框架配置自动启动`此项配置针对用户需要统计系统默认上电开启的外设情况。使能后,会在所有外设open前开启电量管理框架。 > > 一般情况请勿使能`Output level [DEBUG]`,若需开启请参考[注意与说明](#七注意与说明) ### 2. 特殊配置说明 用户在使用前请根据实际测量值修改`powermanager\port\`位置处的设备`工作电流`的配置文件`pm_qe_cfg.c`,若不存在请自行新建此文件,文件名请设置为`pm_qe_cfg.c`,格式如下 其中分为`Fixed`和`Configurable`两部分,`Fixed`部分用户请勿删除设备项,仅能够配置对应工作电流。`Configurable`部分用户可根据实际关注外设添加或删除项,并配置其默认电流。 * 注意:请勿删除 "normal"、"lpm"两项固定内容,normal工作电流指:设备除去`Configurable`注册外设,正常工作电流(即设备静态电流),"lpm"指低功耗模式下的电流 * 配置电流单位均为[μA] 示例如下: ```c /** * NOTE: Do not remove 'lpm' & 'normal' device! * * Fixed: user can only change working current * Configurable: user can add/del device and change working current */ static const pm_qe_dev_list_t pm_qe_dev_list[] = { /* device name, working current[uA] */ /* Fixed */ { "normal", 2100 }, { "lpm", 12 }, /* Configurable */ { "uart1", 24 }, { "lcd", 128 }, { "adc", 3500 } }; ``` ## 三、重要定义及数据结构 ### 工作电流配置文件相关 配置文件中数组配型,即设备名和对应工作电流。其中,名称对应驱动设备名。 ```c typedef struct pm_qe_power_consumption_list { char name[OS_NAME_MAX + 1]; uint32_t working_current; } pm_qe_dev_list_t; ``` | 重要成员 | 说明 | | :---------------------- | :---------------------- | | name | 设备名称 | | working_current | 设备对应工作电流 | --- ## 四、QuantityEstimator API ### 框架控制接口 #### **pm_quantity_estimator_on** 接口提供电源管理框架`QuantityEstimator`开启功能。为方便用户使用,`Quantity Estimator`使能仅为一步操作,仅需要调用此API即可开启功能。查询及重设接口必须在框架使能后才可使用。 ```c os_err_t pm_quantity_estimator_on(uint32_t capacity, uint32_t low_battery_percentage); ``` | **参数** | **说明** | | :--------------------- | :--------------------------------| | capacity | 电池总电量,单位为毫安时[mAh] | | low_battery_percentage | 电池低电量所处百分比 | | **返回** | **说明** | | OS\_EOK | 成功 | | 非OS\_EOK | 失败 | > *注意* > > 若用户主动调用开启接口,预设默认值不会生效,框架采用用户传入值 #### **pm_quantity_estimator_off** 接口提供电源管理框架`QuantityEstimator`关闭功能。 ```c os_err_t pm_quantity_estimator_off(); ``` | **参数** | **说明** | | :-------- | :------- | | void | 空 | | **返回** | **说明** | | OS\_EOK | 成功 | | 非OS\_EOK | 失败 | #### **pm_quantity_estimator_is_on** 接口提供查询框架是否开启功能,在使用电量获取及判断相关功能前,为确保框架已开启,建议采用此查询接口判断框架是否已开启。 ```c os_bool_t pm_quantity_estimator_is_on(); ``` | **参数** | **说明** | | :-------- | :------- | | void | 空 | | **返回** | **说明** | | OS_FALSE | 评估框架未开启 | | OS_TRUE | 评估框架已开启 | #### **pm_qe_reset** 接口提供框架重置重置功能。场景对应更换电池后重设电池电量和告警百分比,以及重置记录数据。 ```c os_err_t pm_qe_reset(uint32_t capacity, uint32_t low_battery_percentage); ``` | **参数** | **说明** | | :--------------------- | :--------------------------------| | capacity | 电池总电量,单位为毫安时[mAh] | | low_battery_percentage | 电池低电量所处百分比 | | **返回** | **说明** | | OS\_EOK | 电池更换,数据重设成功 | | 非OS\_EOK | 电池更换,数据重设失败 | ### 查询接口 #### **pm_qe_used_get** 接口提供框架开启后查询框架预估的已使用电量值。 ```c int32_t pm_qe_used_get(); ``` | **参数** | **说明** | | :----------- | :------------------------------ | | void | 空 | | **返回** | **说明** | | >= 0 | 已使用电量值, 单位为毫安时[mAh] | > *注意* > > 获取已使用电量接口为预留接口,统计目前精确到1mAh,低功耗设备短时间测量获取到的已使用电量预估值为0。 #### **pm_qe_left_get** 接口提供框架开启后查询框架预估的安全容量中的剩余电量,其中`框架未统计的电量`参数为预留给用户,可根据实际情况作修正。 ```c int32_t pm_qe_left_get(uint32_t unstated_using); ``` | **参数** | **说明** | | :---------------------- | :------------------------------- | | unstated_using | 框架未统计的电量,类型[uint32_t] | | **返回** | **说明** | | >= 0 | 安全容量中的剩余电量值, 单位为毫安时[mAh] | | < 0 | 安全容量已全部耗尽 | > *注意* > > 获取预估安全容量剩余电量接口为预留接口,统计目前精确到1mAh。 #### **pm_qe_is_low** 接口提供框架开启后查询是否处于低电量状态。 ```c os_bool_t pm_qe_is_low(uint32_t unstated_using); ``` | **参数** | **说明** | | :---------------------- | :--------------------------- | | unstated_using | 框架未统计的电量,类型[uint32_t] | | **返回** | **说明** | | OS_FALSE | 电量处于正常状态 | | 非OS\_EOK | 电量处于低电量状态,需要及时更换电池 | ## 五、使用方式 > 调用API编译烧录即可 ## 六、使用示例 其中`pm_qe_demo_periodcally`部分为使用此框架周期性获取并将数据写入flash的简单示例。demo 这里以周期性获取已使用电量数据为示例,用户一般情况调用pm_qe_is_low判断是否为低电量即可。 ```c #include #ifdef PM_USING_QUANTITY_ESTIMATOR #include #include #include #include #include /***************************************************************************** * init configuration * *****************************************************************************/ #define PM_QE_BATTERY_CAPACITY (4500) #define PM_QE_UNSTATED_USING (10) #define PM_QE_CRITICAL_PERCENTAGE (20) #define PM_QE_TEST_DEV_NAME "adc" #define DEMO_TIMEOUT_SEC (20) #define DEMO_FAL_NAME "pm_vm" #define DEMO_FAL_DATA_SIZE (sizeof(int32_t)) #define DEMO_FAL_DATA_OFFSET (0) #define DEMO_UNSTATED_USING (0) static os_device_t *dev = OS_NULL; #define TEST_LOG(fmt, ...) printf("[TEST_LOG] %s: " fmt "\r\n", __func__, ##__VA_ARGS__); /* 基本接口使用示例 */ os_err_t pm_qe_on_sh(int32_t argc, char **argv) { os_err_t result = pm_quantity_estimator_on(PM_QE_BATTERY_CAPACITY, PM_QE_CRITICAL_PERCENTAGE); TEST_LOG("%s", OS_SUCCESS == result ? "SUCCESS" : "FAILED"); return result; } os_err_t pm_qe_off_sh(int32_t argc, char **argv) { os_err_t result = pm_quantity_estimator_off(); TEST_LOG("%s", OS_SUCCESS == result ? "SUCCESS" : "FAILED"); return result; } os_err_t pm_qe_is_on_sh(int32_t argc, char **argv) { TEST_LOG("QE is %s", pm_quantity_estimator_is_on() ? "ON" : "OFF"); return OS_SUCCESS; } os_err_t pm_qe_reset_sh(int32_t argc, char **argv) { os_err_t result = pm_qe_reset(PM_QE_BATTERY_CAPACITY, PM_QE_CRITICAL_PERCENTAGE); TEST_LOG("%s", OS_SUCCESS == result ? "SUCCESS" : "FAILED"); return result; } os_err_t pm_qe_battery_used_get_sh(int32_t argc, char **argv) { int32_t battery_used = pm_qe_used_get(); if (0 > battery_used) { TEST_LOG("Battery used get failed."); } else { TEST_LOG("Battery used: [%d]mAh", battery_used); } return OS_SUCCESS; } os_err_t pm_qe_remaining_battery_get_sh(int32_t argc, char **argv) { int32_t remaining_battery = pm_qe_left_get(PM_QE_UNSTATED_USING); if (0 > remaining_battery) { TEST_LOG("Low battery!"); } else { TEST_LOG("Remaining battery: [%d]mAh", remaining_battery); } return OS_SUCCESS; } os_err_t pm_qe_is_low_battery_sh(int32_t argc, char **argv) { TEST_LOG("QE is %s", pm_qe_is_low(PM_QE_UNSTATED_USING) ? "LOW BATTERY" : "STABLE"); return OS_SUCCESS; } os_err_t pm_qe_open_dev_sh(int32_t argc, char **argv) { os_err_t result = OS_SUCCESS; TEST_LOG("Device name:[%s]", PM_QE_TEST_DEV_NAME); dev = os_device_find(PM_QE_TEST_DEV_NAME); if (OS_NULL == dev) { TEST_LOG("Can not find device[%s].", PM_QE_TEST_DEV_NAME); return OS_FAILURE; } result = os_device_open(dev); if (OS_SUCCESS != result) { TEST_LOG("device[%s] open failed!", PM_QE_TEST_DEV_NAME); return result; } return result; } os_err_t pm_qe_close_dev_sh(int32_t argc, char **argv) { os_err_t result = OS_SUCCESS; if (OS_NULL == dev) { TEST_LOG("Can not find device."); return OS_FAILURE; } result = os_device_close(dev); if (OS_SUCCESS != result) { TEST_LOG("device[%s] close failed!", dev->name); } return result; } /* demo: 周期性获取已使用电量并写入flash示例 */ #include #include #include /** * timer create时注册的周期性回调。 * 注意:在本demo中仅为简单示例,这里为方便,调用接口及进行flash读写均在timer回调中进行。 * 实际使用中应当由timer触发后,在由其他task进行后续的接口调用及flash读写,建议不要在timer中进行此类操作 * 若在timer中完成相关业务逻辑(不推荐)需要适当调大timer的栈大小,否则会造成栈溢出 */ void pm_qe_perodic_cb(void *parameter) { int32_t battery_used = 0; int32_t fal_data_get = 0; os_size_t fal_cnt = 0; fal_part_t *fal_part = OS_NULL; /* Find FAL part by name */ fal_part = fal_part_find(DEMO_FAL_NAME); OS_ASSERT_EX(OS_NULL != fal_part, "Please add fal part first"); /* Make sure QE is on */ if (!pm_quantity_estimator_is_on()) { TEST_LOG("QE is off!"); return; } /* Get Battery power used */ battery_used = pm_qe_used_get(); TEST_LOG("Used battery: [%d]mAh", battery_used); fal_cnt = fal_part_erase_all(fal_part); OS_ASSERT(0 <= fal_cnt); /* Write data to flash */ fal_cnt = fal_part_write(fal_part, DEMO_FAL_DATA_OFFSET, (uint8_t *)&battery_used, DEMO_FAL_DATA_SIZE); if (DEMO_FAL_DATA_SIZE != fal_cnt) { TEST_LOG("FAL write failed!"); return; } TEST_LOG("FAL write success!"); /* Read data from flash */ fal_cnt = fal_part_read(fal_part, DEMO_FAL_DATA_OFFSET, (uint8_t *)&fal_data_get, DEMO_FAL_DATA_SIZE); if (DEMO_FAL_DATA_SIZE != fal_cnt) { TEST_LOG("FAL read failed."); return; } TEST_LOG("Data from flash:[%d]", fal_data_get); } os_err_t pm_qe_demo_periodcally_sh(int32_t argc, char **argv) { os_err_t result = OS_SUCCESS; os_timer_id pm_vm_timer = OS_NULL; /* Create & start timer */ pm_vm_timer = os_timer_create(NULL, DEMO_FAL_NAME, pm_qe_perodic_cb, OS_NULL, DEMO_TIMEOUT_SEC * OS_TICK_PER_SECOND, OS_TIMER_FLAG_PERIODIC); if (OS_NULL == pm_vm_timer) { TEST_LOG("Timer failed to create!"); return OS_FAILURE; } result = os_timer_start(pm_vm_timer); if (OS_SUCCESS != result) { TEST_LOG("Timer failed to start!"); return result; } /* Make sure the PE is on */ if (!pm_quantity_estimator_is_on()) { result = pm_quantity_estimator_on(PM_QE_BATTERY_CAPACITY, PM_QE_CRITICAL_PERCENTAGE); OS_ASSERT(OS_SUCCESS == result); } return result; } SH_CMD_EXPORT(pm_qe_on, pm_qe_on_sh, "Call pm_quantity_estimator_on"); SH_CMD_EXPORT(pm_qe_off, pm_qe_off_sh, "Call pm_quantity_estimator_off"); SH_CMD_EXPORT(pm_qe_is_on, pm_qe_is_on_sh, "Call pm_quantity_estimator_is_on"); SH_CMD_EXPORT(pm_qe_reset, pm_qe_reset_sh, "Call pm_qe_reset"); SH_CMD_EXPORT(pm_qe_used, pm_qe_battery_used_get_sh, "Call pm_qe_battery_used_get"); SH_CMD_EXPORT(pm_qe_remaining, pm_qe_remaining_battery_get_sh, "Call pm_qe_remaining_battery_get"); SH_CMD_EXPORT(pm_qe_is_low, pm_qe_is_low_battery_sh, "Call pm_qe_is_low_battery"); SH_CMD_EXPORT(pm_qe_dev_open, pm_qe_open_dev_sh, "Call pm_qe_open_dev_sh"); SH_CMD_EXPORT(pm_qe_dev_close, pm_qe_close_dev_sh, "Call pm_qe_close_dev_sh"); /* Demo for periodc get & write data to flash */ SH_CMD_EXPORT(pm_qe_demo_periodcally, pm_qe_demo_periodcally_sh, "Demo of get & write data to flash periodcally"); #endif /* PM_USING_QUANTITY_ESTIMATOR */ ``` ## 七、注意与说明 * 配置项所有电流单位为μA。 * 获取已使用、剩余安全电量接口为预留接口,统计目前精确到1mAh,一般情况使用`pm_qe_is_low`接口判断是否为低电量即可。若根据项目需求需要更改精度,可以作调整。 * V1.0版本为试验版本,测试使用中如有额外需求或是根据项目应用需作出调整,可与开发联系修改。 * 注意:针对demo中`pm_qe_demo_periodcally`仅为简单示例,这里为方便,调用接口及进行flash读写均在timer回调中进行。实际使用中应当由timer触发后,在由其他task进行后续的接口调用及flash读写,建议不要在timer中进行此类操作。若在timer中完成相关业务逻辑(不推荐),需要适当调大timer的栈大小,否则会造成栈溢出