Merge d3434bbf2b
into 4dfc45d4ab
This commit is contained in:
commit
88d359f2b1
8 changed files with 75 additions and 69 deletions
12
app/Kconfig
12
app/Kconfig
|
@ -388,11 +388,17 @@ 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"
|
||||
help
|
||||
Estimate the battery level by reading the voltage of a Lithium battery.
|
||||
zmk,battery chosen node should be a sensor driver that implements SENSOR_CHAN_VOLTAGE.
|
||||
|
||||
config ZMK_BATTERY_REPORTING_FETCH_MODE_STATE_OF_CHARGE
|
||||
bool "State of charge"
|
||||
help
|
||||
Read the battery level from a fuel gauge sensor.
|
||||
zmk,battery chosen node should be a sensor driver that implements SENSOR_CHAN_GAUGE_STATE_OF_CHARGE.
|
||||
|
||||
endchoice
|
||||
endif
|
||||
|
|
|
@ -85,4 +85,8 @@ if BOARD_CORNEISH_ZEN_V1_LEFT || BOARD_CORNEISH_ZEN_V1_RIGHT
|
|||
config BQ274XX
|
||||
default y
|
||||
|
||||
choice ZMK_BATTERY_REPORTING_FETCH_MODE
|
||||
default ZMK_BATTERY_REPORTING_FETCH_MODE_STATE_OF_CHARGE
|
||||
endchoice
|
||||
|
||||
endif # BOARD_CORNEISH_ZEN_V1_LEFT || BOARD_CORNEISH_ZEN_V1_RIGHT
|
||||
|
|
|
@ -12,32 +12,14 @@
|
|||
int battery_channel_get(const struct battery_value *value, enum sensor_channel chan,
|
||||
struct sensor_value *val_out) {
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_GAUGE_VOLTAGE:
|
||||
case SENSOR_CHAN_VOLTAGE:
|
||||
val_out->val1 = value->millivolts / 1000;
|
||||
val_out->val2 = (value->millivolts % 1000) * 1000U;
|
||||
break;
|
||||
|
||||
case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE:
|
||||
val_out->val1 = value->state_of_charge;
|
||||
val_out->val2 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -12,10 +12,7 @@
|
|||
struct battery_value {
|
||||
uint16_t adc_raw;
|
||||
uint16_t millivolts;
|
||||
uint8_t state_of_charge;
|
||||
};
|
||||
|
||||
int battery_channel_get(const struct battery_value *value, enum sensor_channel chan,
|
||||
struct sensor_value *val_out);
|
||||
|
||||
uint8_t lithium_ion_mv_to_pct(int16_t bat_mv);
|
||||
|
|
|
@ -31,8 +31,7 @@ struct vddh_data {
|
|||
|
||||
static int vddh_sample_fetch(const struct device *dev, enum sensor_channel chan) {
|
||||
// Make sure selected channel is supported
|
||||
if (chan != SENSOR_CHAN_GAUGE_VOLTAGE && chan != SENSOR_CHAN_GAUGE_STATE_OF_CHARGE &&
|
||||
chan != SENSOR_CHAN_ALL) {
|
||||
if (chan != SENSOR_CHAN_VOLTAGE && chan != SENSOR_CHAN_ALL) {
|
||||
LOG_DBG("Selected channel is not supported: %d.", chan);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -56,10 +55,8 @@ static int vddh_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
|||
}
|
||||
|
||||
drv_data->value.millivolts = val * VDDHDIV;
|
||||
drv_data->value.state_of_charge = lithium_ion_mv_to_pct(drv_data->value.millivolts);
|
||||
|
||||
LOG_DBG("ADC raw %d ~ %d mV => %d%%", drv_data->value.adc_raw, drv_data->value.millivolts,
|
||||
drv_data->value.state_of_charge);
|
||||
LOG_DBG("ADC raw %u ~ %u mV", drv_data->value.adc_raw, drv_data->value.millivolts);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -41,8 +41,7 @@ static int bvd_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
|||
struct adc_sequence *as = &drv_data->as;
|
||||
|
||||
// Make sure selected channel is supported
|
||||
if (chan != SENSOR_CHAN_GAUGE_VOLTAGE && chan != SENSOR_CHAN_GAUGE_STATE_OF_CHARGE &&
|
||||
chan != SENSOR_CHAN_ALL) {
|
||||
if (chan != SENSOR_CHAN_VOLTAGE && chan != SENSOR_CHAN_ALL) {
|
||||
LOG_DBG("Selected channel is not supported: %d.", chan);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -74,11 +73,8 @@ static int bvd_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
|||
|
||||
uint16_t millivolts = val * (uint64_t)drv_cfg->full_ohm / drv_cfg->output_ohm;
|
||||
LOG_DBG("ADC raw %d ~ %d mV => %d mV", drv_data->value.adc_raw, val, millivolts);
|
||||
uint8_t percent = lithium_ion_mv_to_pct(millivolts);
|
||||
LOG_DBG("Percent: %d", percent);
|
||||
|
||||
drv_data->value.millivolts = millivolts;
|
||||
drv_data->value.state_of_charge = percent;
|
||||
} else {
|
||||
LOG_DBG("Failed to read ADC: %d", rc);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ 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) {
|
||||
static uint8_t lithium_ion_mv_to_pct(int bat_mv) {
|
||||
// Simple linear approximation of a battery based off adafruit's discharge graph:
|
||||
// https://learn.adafruit.com/li-ion-and-lipoly-batteries/voltages
|
||||
|
||||
|
@ -48,51 +48,60 @@ static uint8_t lithium_ion_mv_to_pct(int16_t bat_mv) {
|
|||
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;
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_STATE_OF_CHARGE)
|
||||
|
||||
rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE);
|
||||
static int get_state_of_charge(uint8_t *result) {
|
||||
int rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_VOLTAGE);
|
||||
if (rc != 0) {
|
||||
LOG_DBG("Failed to fetch battery values: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = sensor_channel_get(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE, &state_of_charge);
|
||||
|
||||
if (rc != 0) {
|
||||
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);
|
||||
LOG_DBG("Failed to fetch sensor value: %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);
|
||||
int millivolts = voltage.val1 * 1000 + (voltage.val2 / 1000);
|
||||
*result = lithium_ion_mv_to_pct(millivolts);
|
||||
|
||||
LOG_DBG("Battery voltage = %d mv -> %u%%", millivolts, *result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif IS_ENABLED(CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_STATE_OF_CHARGE)
|
||||
|
||||
static int get_state_of_charge(uint8_t *result) {
|
||||
struct sensor_value state_of_charge;
|
||||
int rc = sensor_sample_fetch_chan(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE);
|
||||
if (rc != 0) {
|
||||
LOG_DBG("Failed to fetch sensor value: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = sensor_channel_get(battery, SENSOR_CHAN_GAUGE_STATE_OF_CHARGE, &state_of_charge);
|
||||
if (rc != 0) {
|
||||
LOG_DBG("Failed to get battery state of charge: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
*result = state_of_charge.val1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DBG("State of change %d from %d mv", state_of_charge.val1, mv);
|
||||
#else
|
||||
#error "Not a supported reporting fetch mode"
|
||||
#error "Unsupported reporting fetch mode"
|
||||
#endif
|
||||
|
||||
if (last_state_of_charge != state_of_charge.val1) {
|
||||
last_state_of_charge = state_of_charge.val1;
|
||||
static int zmk_battery_update(const struct device *battery) {
|
||||
uint8_t new_state_of_charge = 0;
|
||||
int rc = get_state_of_charge(&new_state_of_charge);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (new_state_of_charge != last_state_of_charge) {
|
||||
last_state_of_charge = new_state_of_charge;
|
||||
#if IS_ENABLED(CONFIG_BT_BAS)
|
||||
LOG_DBG("Setting BAS GATT battery level to %d.", last_state_of_charge);
|
||||
|
||||
|
|
|
@ -16,9 +16,18 @@ Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/
|
|||
| `CONFIG_ZMK_BATTERY_REPORTING` | bool | Enables/disables all battery level detection/reporting | n |
|
||||
| `CONFIG_ZMK_BATTERY_REPORT_INTERVAL` | int | Battery level report interval in seconds | 60 |
|
||||
|
||||
If `CONFIG_ZMK_BATTERY_REPORTING` is enabled, exactly zero or one of the following options may be set to `y`. The first is used if none are set. This should be set to match the type of sensor that is selected for the `zmk,battery` chosen node.
|
||||
|
||||
| Config | Description |
|
||||
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE` | Read a sensor that supports `SENSOR_CHAN_VOLTAGE` and estimate state of charge for a Li-Ion or LiPo battery. |
|
||||
| `CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_STATE_OF_CHARGE` | Read a sensor that supports `SENSOR_CHAN_GAUGE_STATE_OF_CHARGE`. |
|
||||
|
||||
ZMK does not yet support Zephyr's recently added fuel gauge API.
|
||||
|
||||
:::note[Default setting]
|
||||
|
||||
While `CONFIG_ZMK_BATTERY_REPORTING` is disabled by default it is implied by `CONFIG_ZMK_BLE`, thus any board with BLE enabled will have this automatically enabled unless explicitly overriden.
|
||||
While `CONFIG_ZMK_BATTERY_REPORTING` is disabled by default, it is implied by `CONFIG_ZMK_BLE`, thus any board with BLE enabled will have this automatically enabled unless explicitly overriden.
|
||||
|
||||
:::
|
||||
|
||||
|
@ -47,20 +56,26 @@ Applies to: [`/chosen` node](https://docs.zephyrproject.org/3.5.0/build/dts/intr
|
|||
| ------------- | ---- | --------------------------------------------- |
|
||||
| `zmk,battery` | path | The node for the battery sensor driver to use |
|
||||
|
||||
## Battery Voltage Divider Sensor
|
||||
## Voltage Divider Sensor
|
||||
|
||||
Driver for reading the voltage of a battery using an ADC connected to a voltage divider.
|
||||
|
||||
Set `CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE=y` when using this driver.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,battery-voltage-divider"`
|
||||
Applies to: `compatible = "voltage-divider"`
|
||||
|
||||
See [Zephyr's voltage divider documentation](https://docs.zephyrproject.org/3.5.0/build/dts/api/bindings/iio/afe/voltage-divider.html).
|
||||
|
||||
ZMK also provides a `compatible = "zmk,battery-voltage-divider"` driver, which is deprecated. Use the improved driver from Zephyr instead.
|
||||
|
||||
## nRF VDDH Battery Sensor
|
||||
|
||||
Driver for reading the voltage of a battery using a Nordic nRF52's VDDH pin.
|
||||
|
||||
Set `CONFIG_ZMK_BATTERY_REPORTING_FETCH_MODE_LITHIUM_VOLTAGE=y` when using this driver.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,battery-nrf-vddh"`
|
||||
|
|
Loading…
Add table
Reference in a new issue