Skip to content

Commit 97d70b5

Browse files
committed
feat(keyboard): Add ble battery level report
1 parent 6f25eba commit 97d70b5

File tree

7 files changed

+163
-5
lines changed

7 files changed

+163
-5
lines changed

examples/keyboard/components/esp32_s3_kbd_kit/include/bsp/keyboard.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ extern "C" {
4949
#define KBD_WS2812_POWER_IO 1
5050

5151
/*!< Battery monitor GPIO */
52-
#define KBD_BATTERY_MONITOR_IO 2
52+
#define KBD_BATTERY_MONITOR_IO 2
53+
#define KBD_BATTERY_MONITOR_CHANNEL ADC_CHANNEL_1
5354

5455
#ifdef __cplusplus
5556
}

examples/keyboard/main/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
idf_component_register(SRCS "main.c" "../hid_device/usb_descriptors.c" "tinyusb_hid.c" "ble_hid.c" "esp_hid_gap.c" "btn_progress.c" "settings.c"
2-
INCLUDE_DIRS "../hid_device")
1+
idf_component_register(SRCS "main.c" "../hid_device/usb_descriptors.c" "tinyusb_hid.c" "ble_hid.c" "esp_hid_gap.c" "btn_progress.c" "settings.c" "battery_adc.c"
2+
INCLUDE_DIRS "../hid_device")
33

44
idf_component_get_property(tusb_lib espressif__tinyusb COMPONENT_LIB)
55

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <driver/adc.h>
8+
9+
#include "battery_adc.h"
10+
11+
#include "ble_hid.h"
12+
#include <esp_log.h>
13+
#include <esp_adc/adc_oneshot.h>
14+
15+
#include "bsp/esp-bsp.h"
16+
17+
int g_battery_percent;
18+
19+
static const char *TAG = "BATTERY-ADC";
20+
21+
static adc_oneshot_unit_handle_t adc1_handle;
22+
static TaskHandle_t battery_task_handle = NULL;
23+
24+
static void battery_monitor_task(void *pvParameters);
25+
26+
/* Pull up resistor value. Unit: KOhm */
27+
#define PULL_UP_RESISTOR (51)
28+
/* Pull down resistor value. Unit: KOhm */
29+
#define PULL_DOWN_RESISTOR (100)
30+
/* Max voltage value. Unit: mV */
31+
#define MAX_REF_VOLTAGE (3469)
32+
33+
esp_err_t battery_adc_init(void)
34+
{
35+
if (battery_task_handle != NULL) {
36+
ESP_LOGW(TAG, "Battery ADC already initialized");
37+
return ESP_OK;
38+
}
39+
40+
/* ADC1 Init */
41+
adc_oneshot_unit_init_cfg_t unit_init_cfg = {
42+
.unit_id = ADC_UNIT_1,
43+
.clk_src = ADC_RTC_CLK_SRC_DEFAULT,
44+
.ulp_mode = ADC_ULP_MODE_DISABLE
45+
};
46+
ESP_ERROR_CHECK(adc_oneshot_new_unit(&unit_init_cfg, &adc1_handle));
47+
48+
/* ADC1 Config */
49+
adc_oneshot_chan_cfg_t channel_config = {
50+
/* Theoretical battery voltage measurement range is about 2.45 to 2.78V.
51+
* So set the input attenuation to 12 dB (about 4x) */
52+
.atten = ADC_ATTEN_DB_12,
53+
.bitwidth = ADC_BITWIDTH_12
54+
};
55+
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, KBD_BATTERY_MONITOR_CHANNEL, &channel_config));
56+
57+
ESP_LOGI(TAG, "Free memory size: %"PRIu32, esp_get_free_heap_size());
58+
if (xTaskCreate(battery_monitor_task, "battery_monitor", 4096, NULL, 2, &battery_task_handle) != pdPASS) {
59+
return ESP_ERR_NO_MEM;
60+
}
61+
ESP_LOGI(TAG, "Free memory size: %"PRIu32, esp_get_free_heap_size());
62+
63+
return ESP_OK;
64+
}
65+
66+
static void battery_monitor_task(void *pvParameters)
67+
{
68+
ESP_UNUSED(pvParameters);
69+
/* The table of voltage convert percent. */
70+
const static int ocv_capacity_table[] = {
71+
3680, 3700, 3740, 3770, 3790, 3820, 3870, 3920, 3980, 4060, 4200
72+
};
73+
74+
int adc_raw_value;
75+
int adc_voltage;
76+
int battery_voltage;
77+
78+
int battery_level;
79+
80+
while (1) {
81+
adc_oneshot_read(adc1_handle, KBD_BATTERY_MONITOR_CHANNEL, &adc_raw_value);
82+
83+
/* Get the battery voltage. */
84+
adc_voltage = MAX_REF_VOLTAGE * adc_raw_value / 4095;
85+
battery_voltage = adc_voltage * (PULL_UP_RESISTOR + PULL_DOWN_RESISTOR) / PULL_DOWN_RESISTOR;
86+
87+
/* Get the percent. */
88+
for (battery_level = 0; battery_level < 11; ++battery_level) {
89+
if (battery_voltage <= ocv_capacity_table[battery_level]) {
90+
break;
91+
}
92+
}
93+
94+
if (battery_level == 0) {
95+
/* Low battery. */
96+
g_battery_percent = 0;
97+
} else if (battery_level >= 11) {
98+
/* Over voltage. */
99+
g_battery_percent = 100;
100+
} else {
101+
g_battery_percent = (battery_level - 1) * 10;
102+
g_battery_percent += ((battery_voltage - ocv_capacity_table[battery_level]) * 10 / (
103+
ocv_capacity_table[battery_level] - ocv_capacity_table[battery_level - 1]));
104+
}
105+
106+
ble_hid_battery_report(g_battery_percent);
107+
108+
/* Sample period. */
109+
vTaskDelay(pdMS_TO_TICKS(10000));
110+
}
111+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
#include "esp_err.h"
14+
15+
/**
16+
* @brief Initialize battery ADC.
17+
*
18+
* @return
19+
* - ESP_OK: Success
20+
* - ESP_ERR_NO_MEM: Out of memory.
21+
*/
22+
esp_err_t battery_adc_init(void);
23+
24+
#ifdef __cpluscpls
25+
}
26+
#endif

examples/keyboard/main/ble_hid.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -161,3 +161,13 @@ void ble_hid_keyboard_report(hid_report_t report)
161161
break;
162162
}
163163
}
164+
165+
void ble_hid_battery_report(int battery_level)
166+
{
167+
if (s_ble_hid_param.is_connected == false) {
168+
return;
169+
}
170+
171+
ESP_LOGI(TAG, "Report level: %d", battery_level);
172+
esp_hidd_dev_battery_set(s_ble_hid_param.hid_dev, (uint8_t)battery_level);
173+
}

examples/keyboard/main/ble_hid.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
/* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
1+
/*
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
23
*
34
* SPDX-License-Identifier: Apache-2.0
45
*/
@@ -36,6 +37,13 @@ esp_err_t ble_hid_deinit(void);
3637
*/
3738
void ble_hid_keyboard_report(hid_report_t report);
3839

40+
/**
41+
* @brief Send ble hid battery level
42+
*
43+
* @param battery_level
44+
*/
45+
void ble_hid_battery_report(int battery_level);
46+
3947
#ifdef __cplusplus
4048
}
4149
#endif

examples/keyboard/main/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "bsp/esp-bsp.h"
1111
#include "bsp/keycodes.h"
1212
#include "btn_progress.h"
13+
#include "battery_adc.h"
1314
#include "esp_log.h"
1415
#include "esp_pm.h"
1516
#include "keyboard_button.h"
@@ -115,4 +116,5 @@ void app_main(void)
115116
keyboard_button_register_cb(kbd_handle, cb_cfg, NULL);
116117

117118
xTaskCreate(light_progress_task, "light_progress_task", 4096, NULL, 5, &light_progress_task_handle);
119+
battery_adc_init();
118120
}

0 commit comments

Comments
 (0)