aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorPeter Johanson <[email protected]>2024-03-15 21:00:37 +0000
committerPete Johanson <[email protected]>2024-03-24 13:28:55 -0700
commit44358798d3dae71cc1af118e5a5bc5792f9f7761 (patch)
tree8dfea21a2073efa939962793cb28097b56001e1c
parent931a36ff4ad0b30c8165024bbfc0286d05b74b53 (diff)
downloadzmk-44358798d3dae71cc1af118e5a5bc5792f9f7761.tar.gz
zmk-44358798d3dae71cc1af118e5a5bc5792f9f7761.zip
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.
-rw-r--r--app/Kconfig14
-rw-r--r--app/src/battery.c42
2 files changed, 55 insertions, 1 deletions
diff --git a/app/Kconfig b/app/Kconfig
index c430bcb2d3..21e97ac635 100644
--- a/app/Kconfig
+++ b/app/Kconfig
@@ -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
diff --git a/app/src/battery.c b/app/src/battery.c
index 1295f82248..ae79d5f794 100644
--- a/app/src/battery.c
+++ b/app/src/battery.c
@@ -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;