feat: Add ability to fetch battery voltage.

* To be able to use the Zephyr `voltage-divider` driver,
  add a mode for fetching raw voltage from the sensor
 and do state of charge calculation outside of the driver.
This commit is contained in:
Peter Johanson 2024-03-15 21:00:37 +00:00 committed by Pete Johanson
parent 931a36ff4a
commit 44358798d3
2 changed files with 55 additions and 1 deletions

View File

@ -383,6 +383,20 @@ config ZMK_BATTERY_REPORTING
select ZMK_LOW_PRIORITY_WORK_QUEUE
imply BT_BAS if ZMK_BLE
if ZMK_BATTERY_REPORTING
choice ZMK_BATTERY_REPORTING_FETCH_MODE
prompt "Battery Reporting Fetch Mode"
config ZMK_BATTERY_REPORTING_FETCH_MODE_STATE_OF_CHARGE
bool "State of charge"
config ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE
bool "Lithium Voltage"
endchoice
endif
config ZMK_IDLE_TIMEOUT
int "Milliseconds of inactivity before entering idle state (OLED shutoff, etc)"
default 30000

View File

@ -34,11 +34,29 @@ static const struct device *const battery = DEVICE_DT_GET(DT_CHOSEN(zmk_battery)
static const struct device *battery;
#endif
#if IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE)
static uint8_t lithium_ion_mv_to_pct(int16_t bat_mv) {
// Simple linear approximation of a battery based off adafruit's discharge graph:
// https://learn.adafruit.com/li-ion-and-lipoly-batteries/voltages
if (bat_mv >= 4200) {
return 100;
} else if (bat_mv <= 3450) {
return 0;
}
return bat_mv * 2 / 15 - 459;
}
#endif // IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE)
static int zmk_battery_update(const struct device *battery) {
struct sensor_value state_of_charge;
int rc;
int rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE);
#if IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_STATE_OF_CHARGE)
rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE);
if (rc != 0) {
LOG_DBG("Failed to fetch battery values: %d", rc);
return rc;
@ -50,6 +68,28 @@ static int zmk_battery_update(const struct device *battery) {
LOG_DBG("Failed to get battery state of charge: %d", rc);
return rc;
}
#elif IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE)
rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_VOLTAGE);
if (rc != 0) {
LOG_DBG("Failed to fetch battery values: %d", rc);
return rc;
}
struct sensor_value voltage;
rc = sensor_channel_get(battery, SENSOR_CHAN_VOLTAGE, &voltage);
if (rc != 0) {
LOG_DBG("Failed to get battery voltage: %d", rc);
return rc;
}
uint16_t mv = voltage.val1 * 1000 + (voltage.val2 / 1000);
state_of_charge.val1 = lithium_ion_mv_to_pct(mv);
LOG_DBG("State of change %d from %d mv", state_of_charge.val1, mv);
#else
#error "Not a supported reporting fetch mode"
#endif
if (last_state_of_charge != state_of_charge.val1) {
last_state_of_charge = state_of_charge.val1;