Init
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include <esp_adc/adc_oneshot.h>
|
||||
#include <esp_adc/adc_cali.h>
|
||||
#include <esp_adc/adc_cali_scheme.h>
|
||||
|
||||
#include "pins.h"
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
static float g_battery_voltage = 0;
|
||||
static int g_battery_percent = 0;
|
||||
|
||||
adc_oneshot_unit_handle_t adc_handle;
|
||||
adc_cali_handle_t adc_cali_handle;
|
||||
|
||||
float getBatteryVoltage() {
|
||||
return g_battery_voltage;
|
||||
}
|
||||
|
||||
int getBatteryPercentage() {
|
||||
return g_battery_percent;
|
||||
}
|
||||
|
||||
void battery_adc_init() {
|
||||
// ADC init
|
||||
adc_oneshot_unit_init_cfg_t init_config = {
|
||||
.unit_id = ADC_UNIT_1,
|
||||
.clk_src = ADC_RTC_CLK_SRC_DEFAULT,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle));
|
||||
|
||||
// Channel config
|
||||
adc_oneshot_chan_cfg_t config = {
|
||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||
.atten = ADC_ATTEN_DB_12,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(
|
||||
adc_oneshot_config_channel(adc_handle, ADC_CHANNEL_9, &config)
|
||||
);
|
||||
|
||||
// Calibration
|
||||
adc_cali_curve_fitting_config_t cali_config = {
|
||||
.unit_id = ADC_UNIT_1,
|
||||
.chan = ADC_CHANNEL_9,
|
||||
.atten = ADC_ATTEN_DB_12,
|
||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(
|
||||
adc_cali_create_scheme_curve_fitting(
|
||||
&cali_config,
|
||||
&adc_cali_handle
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
float voltage;
|
||||
int percentage;
|
||||
} BatteryPoint;
|
||||
|
||||
static const BatteryPoint battery_curve[] = {
|
||||
{4.20, 100},
|
||||
{4.10, 90},
|
||||
{4.00, 80},
|
||||
{3.90, 70},
|
||||
{3.80, 60},
|
||||
{3.70, 45},
|
||||
{3.60, 30},
|
||||
{3.50, 15},
|
||||
{3.40, 8},
|
||||
{3.30, 5},
|
||||
{3.20, 0},
|
||||
};
|
||||
|
||||
int batteryPercentage(float voltage) {
|
||||
int size = sizeof(battery_curve) / sizeof(BatteryPoint);
|
||||
|
||||
// Above max
|
||||
if (voltage >= battery_curve[0].voltage)
|
||||
return 100;
|
||||
|
||||
// Below min
|
||||
if (voltage <= battery_curve[size - 1].voltage)
|
||||
return 0;
|
||||
|
||||
// Find range
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
if (voltage <= battery_curve[i].voltage &&
|
||||
voltage >= battery_curve[i + 1].voltage) {
|
||||
|
||||
float v1 = battery_curve[i].voltage;
|
||||
float v2 = battery_curve[i + 1].voltage;
|
||||
|
||||
int p1 = battery_curve[i].percentage;
|
||||
int p2 = battery_curve[i + 1].percentage;
|
||||
|
||||
// Linear interpolation
|
||||
float t = (voltage - v2) / (v1 - v2);
|
||||
|
||||
return p2 + (int)((p1 - p2) * t);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float readBatteryVoltsSamples(int samples) {
|
||||
uint32_t raw_sum = 0;
|
||||
int raw;
|
||||
int voltage_mv;
|
||||
|
||||
for (int i = 0; i < samples; i++) {
|
||||
ESP_ERROR_CHECK(
|
||||
adc_oneshot_read(adc_handle, ADC_CHANNEL_9, &raw)
|
||||
);
|
||||
raw_sum += raw;
|
||||
|
||||
// only delay for "slow mode"
|
||||
if (samples > 16) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
}
|
||||
|
||||
int raw_avg = raw_sum / samples;
|
||||
|
||||
ESP_ERROR_CHECK(
|
||||
adc_cali_raw_to_voltage(adc_cali_handle, raw_avg, &voltage_mv)
|
||||
);
|
||||
|
||||
return (voltage_mv / 1000.0f) * 2.0f;
|
||||
}
|
||||
|
||||
static void battery_task(void *arg) {
|
||||
battery_adc_init();
|
||||
g_battery_voltage = readBatteryVoltsSamples(1);
|
||||
while (1) {
|
||||
g_battery_voltage = readBatteryVoltsSamples(256);
|
||||
g_battery_percent = batteryPercentage(g_battery_voltage);
|
||||
}
|
||||
}
|
||||
|
||||
void battery_start_task() {
|
||||
xTaskCreate(
|
||||
battery_task,
|
||||
"battery_task",
|
||||
4096,
|
||||
NULL,
|
||||
5,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user