Add support for measuring battery voltage

This commit is contained in:
Tobias Schramm 2021-02-09 09:57:24 +01:00 committed by Patrick Rathje
parent 1749cc2629
commit a9963c4ca6
6 changed files with 115 additions and 2 deletions

68
src/battery.c Normal file
View File

@ -0,0 +1,68 @@
#include <device.h>
#include <drivers/adc.h>
#include "battery.h"
#define VBATT DT_PATH(vbatt)
#define BATTERY_ADC_GAIN ADC_GAIN_1_6
static struct {
const struct device *adc;
uint32_t output_resistance_ohm;
uint32_t full_resistance_ohm;
struct adc_sequence sequence;
uint16_t raw_value;
uint16_t value_mv;
} battery_adc_config;
int battery_init() {
struct adc_channel_cfg config;
battery_adc_config.adc = device_get_binding(DT_IO_CHANNELS_LABEL(VBATT));
if (!battery_adc_config.adc) {
return -ENODEV;
}
battery_adc_config.output_resistance_ohm = DT_PROP(VBATT, output_ohms);
battery_adc_config.full_resistance_ohm = DT_PROP(VBATT, full_ohms);
battery_adc_config.sequence.channels = BIT(0);
battery_adc_config.sequence.buffer = &battery_adc_config.raw_value;
battery_adc_config.sequence.buffer_size = sizeof(battery_adc_config.raw_value);
battery_adc_config.sequence.oversampling = 4;
battery_adc_config.sequence.calibrate = true;
battery_adc_config.sequence.resolution = 14;
config.gain = BATTERY_ADC_GAIN;
config.reference = ADC_REF_INTERNAL;
config.acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40);
config.channel_id = 0;
config.input_positive = SAADC_CH_PSELP_PSELP_AnalogInput0 + DT_IO_CHANNELS_INPUT(VBATT);
return adc_channel_setup(battery_adc_config.adc, &config);
}
int battery_update() {
int err;
int32_t val_mv;
err = adc_read(battery_adc_config.adc, &battery_adc_config.sequence);
if (err) {
return err;
}
battery_adc_config.sequence.calibrate = false;
val_mv = battery_adc_config.raw_value;
err = dc_raw_to_millivolts(adc_ref_internal(battery_adc_config.adc), BATTERY_ADC_GAIN, battery_adc_config.sequence.resolution, &val_mv);
if (err) {
return err;
}
battery_adc_config.value_mv = val_mv * battery_adc_config.full_resistance_ohm / battery_adc_config.output_resistance_ohm;
return 0;
}
uint16_t battery_get_voltage_mv() {
return battery_adc_config.value_mv;
}

7
src/battery.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
int battery_init();
int battery_update();
uint16_t battery_get_voltage_mv();

View File

@ -4,7 +4,8 @@
#include <stdbool.h>
#define DISPLAY_LINE_CURRENT_IDENTIFIER 0
#define DISPLAY_LINE_LAST_CONTACTS_START 2
#define DISPLAY_LINE_LAST_CONTACTS_START 5
#define DISPLAY_LINE_BATTERY_VOLTAGE 20
#ifdef PLATFORM_PINETIME
#include "display_pinetime.h"

View File

@ -11,6 +11,7 @@
#include <bluetooth/hci.h>
#include <random/rand32.h>
#include "battery.h"
#include "exposure-notification.h"
#include "covid_types.h"
#include "contacts.h"
@ -35,6 +36,20 @@ void main(void)
platform_display_draw_string(0, 0, "Hello World!");
platform_display_draw_string(0, DISPLAY_LINE_LAST_CONTACTS_START, "Seen identifiers:");
err = battery_init();
if (err) {
printk("Failed to initialize battery gauging: %d\n", err);
return;
}
err = battery_update();
if (err) {
printk("Failed to update battery voltage: %d\n", err);
return;
}
platform_display_draw_string(0, DISPLAY_LINE_BATTERY_VOLTAGE, "Battery voltage:");
// first init everything
// Use custom randomization as the mbdet_tls context initialization messes with the Zeyhr BLE stack.
err = en_init(sys_csrand_get);
@ -72,7 +87,16 @@ void main(void)
return;
}
do{
do {
err = battery_update();
if (err) {
printk("Failed to update battery voltage: %d\n", err);
} else {
char voltage_mv[12] = { 0 };
snprintf(voltage_mv, sizeof(voltage_mv), "%04u mV", battery_get_voltage_mv());
platform_display_draw_string(0, DISPLAY_LINE_BATTERY_VOLTAGE + 1, voltage_mv);
}
do_covid();
do_gatt();
} while (1);

View File

@ -0,0 +1,12 @@
&adc {
status = "okay";
};
/ {
vbatt {
compatible = "voltage-divider";
io-channels = <&adc 7>;
output-ohms = <1000000>;
full-ohms = <(1000000 + 1000000)>;
};
};

View File

@ -24,6 +24,7 @@ CONFIG_HEAP_MEM_POOL_SIZE=8192
CONFIG_GPIO=y
CONFIG_LED=y
CONFIG_ADC=y
#CONFIG_LVGL=y
#CONFIG_LVGL_USE_LABEL=y