--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/task_ina219.c Tue Mar 28 22:13:06 2023 +0200 @@ -0,0 +1,153 @@ +/** + * @file task_ina219.c + * @brief The FreeRTOS task to query the INA219 sensors. + */ + + +#include "config.h" + + +static const char *TAG = "task_ina219"; + +SemaphoreHandle_t xSemaphoreINA219 = NULL; ///< Semaphore INA219 task +EventGroupHandle_t xEventGroupINA219; ///< Events INA219 task +INA219_State *ina219_state; ///< Public state for other tasks + +extern ina219_t ina219_b_dev; +extern ina219_t ina219_s_dev; + +const int TASK_INA219_REQUEST_DONE = BIT0; ///< All requests are done. +const int TASK_INA219_REQUEST_POWER = BIT1; ///< Request power readings + + + +void request_ina219(void) +{ + xEventGroupClearBits(xEventGroupINA219, TASK_INA219_REQUEST_DONE); + xEventGroupSetBits(xEventGroupINA219, TASK_INA219_REQUEST_POWER); +} + + + +bool ready_ina219(void) +{ + if (xEventGroupGetBits(xEventGroupINA219) & TASK_INA219_REQUEST_DONE) + return true; + return false; +} + + + +/* + * Task to read INA219 sensors on request. + */ +void task_ina219(void *pvParameter) +{ + int error = 0; + float bus_voltage, shunt_voltage, current, power; + + ESP_LOGI(TAG, "Starting task INA219 sda=%d scl=%d", CONFIG_I2C_MASTER_SDA, CONFIG_I2C_MASTER_SCL); + ina219_state = malloc(sizeof(INA219_State)); + + ina219_state->Battery.valid = false; + ina219_state->Battery.fake = (ina219_b_dev.i2c_dev.addr == 0) ? true:false; + ina219_state->Battery.address = ina219_b_dev.i2c_dev.addr; + ina219_state->Battery.error = INA219_ERR_NONE; + if (ina219_b_dev.i2c_dev.addr) { + ESP_LOGI(TAG, "Configuring INA219 Battery"); + ESP_ERROR_CHECK(ina219_configure(&ina219_b_dev, INA219_BUS_RANGE_16V, INA219_GAIN_0_125, + INA219_RES_12BIT_1S, INA219_RES_12BIT_1S, INA219_MODE_CONT_SHUNT_BUS)); + ESP_LOGI(TAG, "Calibrating INA219 Battery"); + ESP_ERROR_CHECK(ina219_calibrate(&ina219_b_dev, (float)I_MAX_CURRENT, (float)I_SHUNT_RESISTOR_MILLI_OHM / 1000.0f)); + } + + ina219_state->Solar.valid = false; + ina219_state->Solar.fake = (ina219_s_dev.i2c_dev.addr == 0) ? true:false; + ina219_state->Solar.address = ina219_s_dev.i2c_dev.addr; + ina219_state->Solar.error = INA219_ERR_NONE; + if (ina219_s_dev.i2c_dev.addr) { + ESP_LOGI(TAG, "Configuring INA219 Solar"); + ESP_ERROR_CHECK(ina219_configure(&ina219_s_dev, INA219_BUS_RANGE_16V, INA219_GAIN_0_125, + INA219_RES_12BIT_1S, INA219_RES_12BIT_1S, INA219_MODE_CONT_SHUNT_BUS)); + ESP_LOGI(TAG, "Calibrating INA219 Solar"); + ESP_ERROR_CHECK(ina219_calibrate(&ina219_s_dev, (float)I_MAX_CURRENT, (float)I_SHUNT_RESISTOR_MILLI_OHM / 1000.0f)); + } + + /* event handler and event group for this task */ + xEventGroupINA219 = xEventGroupCreate(); + EventBits_t uxBits; + + /* + * Task loop forever. + */ + ESP_LOGI(TAG, "Starting loop INA219 sensors 0x%02x %d, 0x%02x %d", + ina219_state->Battery.address, ina219_state->Battery.fake, ina219_state->Solar.address, ina219_state->Solar.fake); + while (1) { + + uxBits = xEventGroupWaitBits(xEventGroupINA219, TASK_INA219_REQUEST_POWER, pdFALSE, pdFALSE, portMAX_DELAY ); + + if (uxBits & TASK_INA219_REQUEST_POWER) { + + /* + * Four scenario's: + * 1. Both sensors present, just use them. + * 2. Only battery sensor (test environment). Use it and fake + * the solar chip as if it is charging. + * 3. Only solar sensor. Use scenario 4, but show measured values. + * 4. Fake everything. + */ + if (! ina219_state->Battery.fake) { + ESP_ERROR_CHECK(ina219_get_bus_voltage(&ina219_b_dev, &bus_voltage)); + ESP_ERROR_CHECK(ina219_get_shunt_voltage(&ina219_b_dev, &shunt_voltage)); + ESP_ERROR_CHECK(ina219_get_current(&ina219_b_dev, ¤t)); + ESP_ERROR_CHECK(ina219_get_power(&ina219_b_dev, &power)); + ESP_LOGI(TAG, "Battery VBUS: %.04f V, VSHUNT: %.04f mV, IBUS: %.04f mA, PBUS: %.04f mW", + bus_voltage, shunt_voltage * 1000, current * 1000, power * 1000); + } + if (! ina219_state->Solar.fake) { + ESP_ERROR_CHECK(ina219_get_bus_voltage(&ina219_s_dev, &bus_voltage)); + ESP_ERROR_CHECK(ina219_get_shunt_voltage(&ina219_s_dev, &shunt_voltage)); + ESP_ERROR_CHECK(ina219_get_current(&ina219_s_dev, ¤t)); + ESP_ERROR_CHECK(ina219_get_power(&ina219_s_dev, &power)); + ESP_LOGI(TAG, " Solar VBUS: %.04f V, VSHUNT: %.04f mV, IBUS: %.04f mA, PBUS: %.04f mW", + bus_voltage, shunt_voltage * 1000, current * 1000, power * 1000); + } + + /* + error = ina219_read_float(&ina219_dev, &temperature, &pressure, &humidity); + if (xSemaphoreTake(xSemaphoreINA219, 25) == pdTRUE) { + if (error == ESP_OK) { + ina219_state->error = INA219_ERR_NONE; + ina219_state->valid = true; + ina219_state->temperature = temperature; + ina219_state->pressure = pressure; + ina219_state->humidity = humidity; + } else { + ina219_state->error = INA219_ERR_READ; + ina219_state->valid = false; + ina219_state->temperature = 0; + ina219_state->pressure = 0; + ina219_state->humidity = 0; + } + xSemaphoreGive(xSemaphoreINA219); + } + } else { + if (xSemaphoreTake(xSemaphoreINA219, 25) == pdTRUE) { + ina219_state->error = INA219_ERR_NONE; + ina219_state->valid = true; + ina219_state->temperature = 21.23; + ina219_state->pressure = 101360; + ina219_state->humidity = 0; + xSemaphoreGive(xSemaphoreINA219); + } + } + + */ + xEventGroupClearBits(xEventGroupINA219, TASK_INA219_REQUEST_POWER); + xEventGroupSetBits(xEventGroupINA219, TASK_INA219_REQUEST_DONE); +#if 0 + ESP_LOGI(TAG, " TB: %.3f C, %.1f hPa, error: %d", ina219_state->temperature, ina219_state->pressure / 100, ina219_state->error); +#endif + } + } +}