/main/battery.c
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_adc_cal.h"
#include "esp_log.h"
#include "battery.h"
#include "gfx.h"
#include "io.h"
#define BATT_ADC_COUNTS 64
battery_info_t batt_info;
SemaphoreHandle_t battery_access_mutex;
void battery_task(void* pvParameters) {
const char TAG[] = "battery_task";
esp_adc_cal_characteristics_t chars;
esp_adc_cal_value_t cal = esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 2450, &chars);
switch (cal) {
case ESP_ADC_CAL_VAL_EFUSE_VREF:
ESP_LOGI(TAG, "ADC calibrated with eFuse Vref");
break;
case ESP_ADC_CAL_VAL_EFUSE_TP:
ESP_LOGI(TAG, "ADC calibrated with two point value");
break;
case ESP_ADC_CAL_VAL_DEFAULT_VREF:
ESP_LOGI(TAG, "ADC calibrated with default Vref");
break;
default:
ESP_LOGI(TAG, "ADC calibrated with unknown method %d", cal);
}
while (1) {
io_batt_enable(true);
int total = 0;
int counts = 0;
for (int i = 0; i < BATT_ADC_COUNTS; i++) {
int v;
esp_err_t ret = adc2_get_raw(ADC2_CHANNEL_5, ADC_WIDTH_BIT_12, &v);
if (ret != ESP_OK) {
continue;
}
total += v;
counts++;
}
int raw_value = total / counts;
int adc_mV = esp_adc_cal_raw_to_voltage(raw_value, &chars);
int batt_mV = (adc_mV * 1657) / 1000 + 294;
int percentage = ((batt_mV - 3000) * 100) / 1150;
bool charging = io_charging();
xSemaphoreTake(battery_access_mutex, portMAX_DELAY);
batt_info.mV = batt_mV;
batt_info.percentage = percentage;
batt_info.charging = charging;
xSemaphoreGive(battery_access_mutex);
gfx_data_t* gd = gfx_acquire_data(SCENE_NO_CHANGE);
gd->battery.mV = batt_mV;
gd->battery.percentage = percentage;
gd->battery.charging = charging;
gfx_release_data();
ESP_LOGI(TAG, "%dmV [raw %d adc %dmV] %d%% %s", batt_mV, raw_value, adc_mV, percentage, charging ? "charging" : "not charging");
io_batt_enable(false);
vTaskDelay(10000 / portTICK_PERIOD_MS);
}
}
int battery_init() {
battery_access_mutex = xSemaphoreCreateMutex();
//xSemaphoreGive(battery_access_mutex);
xTaskCreate(battery_task, "batt", 4096, NULL, 1, NULL);
return 1;
}
battery_info_t battery_get_state() {
xSemaphoreTake(battery_access_mutex, portMAX_DELAY);
battery_info_t batt_info_copy = batt_info;
xSemaphoreGive(battery_access_mutex);
return batt_info_copy;
}