mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-05-30 21:13:21 +00:00
Implement battery level interface (#24666)
Co-authored-by: Nick Brassel <nick@tzarc.org>
This commit is contained in:
parent
312f42945d
commit
6ee806f376
@ -934,6 +934,28 @@ ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
VALID_BATTERY_DRIVER_TYPES := adc custom vendor
|
||||||
|
|
||||||
|
BATTERY_DRIVER ?= adc
|
||||||
|
ifeq ($(strip $(BATTERY_DRIVER_REQUIRED)), yes)
|
||||||
|
ifeq ($(filter $(BATTERY_DRIVER),$(VALID_BATTERY_DRIVER_TYPES)),)
|
||||||
|
$(call CATASTROPHIC_ERROR,Invalid BATTERY_DRIVER,BATTERY_DRIVER="$(BATTERY_DRIVER)" is not a valid battery driver)
|
||||||
|
endif
|
||||||
|
|
||||||
|
OPT_DEFS += -DBATTERY_DRIVER
|
||||||
|
OPT_DEFS += -DBATTERY_$(strip $(shell echo $(BATTERY_DRIVER) | tr '[:lower:]' '[:upper:]'))
|
||||||
|
|
||||||
|
COMMON_VPATH += $(DRIVER_PATH)/battery
|
||||||
|
|
||||||
|
SRC += battery.c
|
||||||
|
SRC += battery_$(strip $(BATTERY_DRIVER)).c
|
||||||
|
|
||||||
|
# add extra deps
|
||||||
|
ifeq ($(strip $(BATTERY_DRIVER)), adc)
|
||||||
|
ANALOG_DRIVER_REQUIRED = yes
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
VALID_WS2812_DRIVER_TYPES := bitbang custom i2c pwm spi vendor
|
VALID_WS2812_DRIVER_TYPES := bitbang custom i2c pwm spi vendor
|
||||||
|
|
||||||
WS2812_DRIVER ?= bitbang
|
WS2812_DRIVER ?= bitbang
|
||||||
|
@ -227,6 +227,7 @@
|
|||||||
{ "text": "ADC Driver", "link": "/drivers/adc" },
|
{ "text": "ADC Driver", "link": "/drivers/adc" },
|
||||||
{ "text": "APA102 Driver", "link": "/drivers/apa102" },
|
{ "text": "APA102 Driver", "link": "/drivers/apa102" },
|
||||||
{ "text": "Audio Driver", "link": "/drivers/audio" },
|
{ "text": "Audio Driver", "link": "/drivers/audio" },
|
||||||
|
{ "text": "Battery Driver", "link": "/drivers/battery" },
|
||||||
{ "text": "EEPROM Driver", "link": "/drivers/eeprom" },
|
{ "text": "EEPROM Driver", "link": "/drivers/eeprom" },
|
||||||
{ "text": "Flash Driver", "link": "/drivers/flash" },
|
{ "text": "Flash Driver", "link": "/drivers/flash" },
|
||||||
{ "text": "I2C Driver", "link": "/drivers/i2c" },
|
{ "text": "I2C Driver", "link": "/drivers/i2c" },
|
||||||
|
51
docs/drivers/battery.md
Normal file
51
docs/drivers/battery.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Battery Driver
|
||||||
|
|
||||||
|
This driver provides support for sampling battery level.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To use this driver, add the following to your `rules.mk`:
|
||||||
|
|
||||||
|
```make
|
||||||
|
BATTERY_DRIVER_REQUIRED = yes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Basic Configuration {#basic-configuration}
|
||||||
|
|
||||||
|
Add the following to your `config.h`:
|
||||||
|
|
||||||
|
|Define |Default |Description |
|
||||||
|
|--------------------------|--------|--------------------------------------------------|
|
||||||
|
|`BATTERY_SAMPLE_INTERVAL` |`30000` |The time between battery samples in milliseconds. |
|
||||||
|
|
||||||
|
## Driver Configuration {#driver-configuration}
|
||||||
|
|
||||||
|
Driver selection can be configured in `rules.mk` as `BATTERY_DRIVER`. Valid values are `adc` (default), `vendor`, or `custom`. See below for information on individual drivers.
|
||||||
|
|
||||||
|
### ADC Driver {#adc-driver}
|
||||||
|
|
||||||
|
This is the default battery driver. The default configuration assumes the battery is connected to a ADC capable pin through a voltage divider.
|
||||||
|
|
||||||
|
```make
|
||||||
|
BATTERY_DRIVER = adc
|
||||||
|
```
|
||||||
|
|
||||||
|
The following `#define`s apply only to the `adc` driver:
|
||||||
|
|
||||||
|
|Define |Default |Description |
|
||||||
|
|-----------------------------|--------------|--------------------------------------------------------------|
|
||||||
|
|`BATTERY_PIN` |*Not defined* |The GPIO pin connected to the voltage divider. |
|
||||||
|
|`BATTERY_REF_VOLTAGE_MV` |`3300` |The ADC reverence voltage, in millivolts. |
|
||||||
|
|`BATTERY_VOLTAGE_DIVIDER_R1` |`100000` |The voltage divider resistance, in kOhm. Set to 0 to disable. |
|
||||||
|
|`BATTERY_VOLTAGE_DIVIDER_R1` |`100000` |The voltage divider resistance, in kOhm. Set to 0 to disable. |
|
||||||
|
|`BATTERY_ADC_RESOLUTION` |`10` |The ADC resolution configured for the ADC Driver. |
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
### `uint8_t battery_get_percent(void)` {#api-battery-get-percent}
|
||||||
|
|
||||||
|
Sample battery level.
|
||||||
|
|
||||||
|
#### Return Value {#api-battery-get-percent-return}
|
||||||
|
|
||||||
|
The battery percentage, in the range 0-100.
|
31
drivers/battery/battery.c
Normal file
31
drivers/battery/battery.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2025 QMK
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "battery_driver.h"
|
||||||
|
#include "battery.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
#ifndef BATTERY_SAMPLE_INTERVAL
|
||||||
|
# define BATTERY_SAMPLE_INTERVAL 30000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint8_t last_bat_level = 100;
|
||||||
|
|
||||||
|
void battery_init(void) {
|
||||||
|
battery_driver_init();
|
||||||
|
|
||||||
|
last_bat_level = battery_driver_sample_percent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void battery_task(void) {
|
||||||
|
static uint32_t bat_timer = 0;
|
||||||
|
if (timer_elapsed32(bat_timer) > BATTERY_SAMPLE_INTERVAL) {
|
||||||
|
last_bat_level = battery_driver_sample_percent();
|
||||||
|
|
||||||
|
bat_timer = timer_read32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t battery_get_percent(void) {
|
||||||
|
return last_bat_level;
|
||||||
|
}
|
34
drivers/battery/battery.h
Normal file
34
drivers/battery/battery.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2025 QMK
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* \defgroup battery Battery API
|
||||||
|
*
|
||||||
|
* \brief API to query battery status.
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize the battery driver.
|
||||||
|
*/
|
||||||
|
void battery_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Perform housekeeping tasks.
|
||||||
|
*/
|
||||||
|
void battery_task(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sample battery level.
|
||||||
|
*
|
||||||
|
* \return The battery percentage, in the range 0-100.
|
||||||
|
*/
|
||||||
|
uint8_t battery_get_percent(void);
|
||||||
|
|
||||||
|
/** \} */
|
55
drivers/battery/battery_adc.c
Normal file
55
drivers/battery/battery_adc.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// Copyright 2025 QMK
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "analog.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
#ifndef BATTERY_PIN
|
||||||
|
# error("BATTERY_PIN not configured!")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BATTERY_REF_VOLTAGE_MV
|
||||||
|
# define BATTERY_REF_VOLTAGE_MV 3300
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BATTERY_VOLTAGE_DIVIDER_R1
|
||||||
|
# define BATTERY_VOLTAGE_DIVIDER_R1 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BATTERY_VOLTAGE_DIVIDER_R2
|
||||||
|
# define BATTERY_VOLTAGE_DIVIDER_R2 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: infer from adc config?
|
||||||
|
#ifndef BATTERY_ADC_RESOLUTION
|
||||||
|
# define BATTERY_ADC_RESOLUTION 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void battery_driver_init(void) {
|
||||||
|
gpio_set_pin_input(BATTERY_PIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t battery_driver_get_mv(void) {
|
||||||
|
uint32_t raw = analogReadPin(BATTERY_PIN);
|
||||||
|
|
||||||
|
uint32_t bat_mv = raw * BATTERY_REF_VOLTAGE_MV / (1 << BATTERY_ADC_RESOLUTION);
|
||||||
|
|
||||||
|
#if BATTERY_VOLTAGE_DIVIDER_R1 > 0 && BATTERY_VOLTAGE_DIVIDER_R2 > 0
|
||||||
|
bat_mv = bat_mv * (BATTERY_VOLTAGE_DIVIDER_R1 + BATTERY_VOLTAGE_DIVIDER_R2) / BATTERY_VOLTAGE_DIVIDER_R2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return bat_mv;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t battery_driver_sample_percent(void) {
|
||||||
|
uint16_t bat_mv = battery_driver_get_mv();
|
||||||
|
|
||||||
|
// https://github.com/zmkfirmware/zmk/blob/3f7c9d7cc4f46617faad288421025ea2a6b0bd28/app/module/drivers/sensor/battery/battery_common.c#L33
|
||||||
|
if (bat_mv >= 4200) {
|
||||||
|
return 100;
|
||||||
|
} else if (bat_mv <= 3450) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bat_mv * 2 / 15 - 459;
|
||||||
|
}
|
29
drivers/battery/battery_driver.h
Normal file
29
drivers/battery/battery_driver.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2025 QMK
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* \defgroup battery Battery Driver API
|
||||||
|
*
|
||||||
|
* \brief API to query battery status.
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize the battery driver. This function must be called only once, before any of the below functions can be called.
|
||||||
|
*/
|
||||||
|
void battery_driver_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sample battery level.
|
||||||
|
*
|
||||||
|
* \return The battery percentage, in the range 0-100.
|
||||||
|
*/
|
||||||
|
uint8_t battery_driver_sample_percent(void);
|
||||||
|
|
||||||
|
/** \} */
|
6
keyboards/handwired/onekey/keymaps/battery/config.h
Normal file
6
keyboards/handwired/onekey/keymaps/battery/config.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Copyright 2024 QMK
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define BATTERY_PIN ADC_PIN
|
28
keyboards/handwired/onekey/keymaps/battery/keymap.c
Normal file
28
keyboards/handwired/onekey/keymaps/battery/keymap.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2024 QMK
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
#include "battery.h"
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
LAYOUT_ortho_1x1(KC_A)
|
||||||
|
};
|
||||||
|
|
||||||
|
void keyboard_post_init_user(void) {
|
||||||
|
// Customise these values to desired behaviour
|
||||||
|
debug_enable=true;
|
||||||
|
// debug_matrix=false;
|
||||||
|
// debug_keyboard=true;
|
||||||
|
// debug_mouse=false;
|
||||||
|
|
||||||
|
battery_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void housekeeping_task_user(void) {
|
||||||
|
static uint32_t last = 0;
|
||||||
|
if (timer_elapsed32(last) > 2000) {
|
||||||
|
uprintf("Bat: %d!\n", battery_get_percent());
|
||||||
|
|
||||||
|
last = timer_read32();
|
||||||
|
}
|
||||||
|
}
|
7
keyboards/handwired/onekey/keymaps/battery/keymap.json
Normal file
7
keyboards/handwired/onekey/keymaps/battery/keymap.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"features": {
|
||||||
|
"console": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
keyboards/handwired/onekey/keymaps/battery/rules.mk
Normal file
1
keyboards/handwired/onekey/keymaps/battery/rules.mk
Normal file
@ -0,0 +1 @@
|
|||||||
|
BATTERY_DRIVER_REQUIRED = yes
|
@ -122,6 +122,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#ifdef SPLIT_KEYBOARD
|
#ifdef SPLIT_KEYBOARD
|
||||||
# include "split_util.h"
|
# include "split_util.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BATTERY_DRIVER
|
||||||
|
# include "battery.h"
|
||||||
|
#endif
|
||||||
#ifdef BLUETOOTH_ENABLE
|
#ifdef BLUETOOTH_ENABLE
|
||||||
# include "bluetooth.h"
|
# include "bluetooth.h"
|
||||||
#endif
|
#endif
|
||||||
@ -522,6 +525,9 @@ void keyboard_init(void) {
|
|||||||
// init after split init
|
// init after split init
|
||||||
pointing_device_init();
|
pointing_device_init();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BATTERY_DRIVER
|
||||||
|
battery_init();
|
||||||
|
#endif
|
||||||
#ifdef BLUETOOTH_ENABLE
|
#ifdef BLUETOOTH_ENABLE
|
||||||
bluetooth_init();
|
bluetooth_init();
|
||||||
#endif
|
#endif
|
||||||
@ -782,6 +788,10 @@ void keyboard_task(void) {
|
|||||||
joystick_task();
|
joystick_task();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BATTERY_DRIVER
|
||||||
|
battery_task();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef BLUETOOTH_ENABLE
|
#ifdef BLUETOOTH_ENABLE
|
||||||
bluetooth_task();
|
bluetooth_task();
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user