Wed, 12 Apr 2023 16:23:02 +0200
Reduced I2C master speed from 400 to 100 Khz. Hope to get power-on init for BMP280 more reliable. Added warnings for I2C devices that are missing. Some logmessages reduced to debug log messages. Added extra 10 mSec delays before read shunt voltage in the INA219 task. Removed and reduced log levels in the MQTT task. Show received data events. Remove WiFi total time debug logging, it's ok now.
/** * @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) { float bus_voltage, shunt_voltage, current; 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_32V, 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_32V, 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) { /* * Note, on Arduino power down and resume works, but not on esp-idf. * This could save only 0.5 mA per device. * * We run the ESP32-C3 in Power Save mode, Dynamic Frequency Scaling. * This means a wrong current measurement (too high) unless we let the CPU * rest for a while. The INA219 runs in continuous mode so we get the * results during the vTaskDelay(). */ vTaskDelay(20 / portTICK_PERIOD_MS); ESP_ERROR_CHECK(ina219_get_bus_voltage(&ina219_b_dev, &bus_voltage)); vTaskDelay(10 / portTICK_PERIOD_MS); ESP_ERROR_CHECK(ina219_get_shunt_voltage(&ina219_b_dev, &shunt_voltage)); vTaskDelay(10 / portTICK_PERIOD_MS); ESP_ERROR_CHECK(ina219_get_current(&ina219_b_dev, ¤t)); ESP_LOGI(TAG, "Battery VBUS: %.04f V, VSHUNT: %.04f mV, IBUS: %.04f mA", bus_voltage, shunt_voltage * 1000, current * 1000); } if (xSemaphoreTake(xSemaphoreINA219, 25) == pdTRUE) { if (ina219_state->Battery.fake) { ina219_state->Battery.volts = 13.21; if (ready_WiFi()) { ina219_state->Battery.shunt = 0.00785; ina219_state->Battery.current = 78.5; } else { ina219_state->Battery.shunt = 0.00182; ina219_state->Battery.current = 18.2; } } else { ina219_state->Battery.volts = bus_voltage; ina219_state->Battery.shunt = shunt_voltage; ina219_state->Battery.current = current * 1000; } ina219_state->Battery.valid = true; xSemaphoreGive(xSemaphoreINA219); } if (! ina219_state->Solar.fake) { vTaskDelay(20 / portTICK_PERIOD_MS); ESP_ERROR_CHECK(ina219_get_bus_voltage(&ina219_s_dev, &bus_voltage)); vTaskDelay(10 / portTICK_PERIOD_MS); ESP_ERROR_CHECK(ina219_get_shunt_voltage(&ina219_s_dev, &shunt_voltage)); vTaskDelay(10 / portTICK_PERIOD_MS); ESP_ERROR_CHECK(ina219_get_current(&ina219_s_dev, ¤t)); ESP_LOGI(TAG, " Solar VBUS: %.04f V, VSHUNT: %.04f mV, IBUS: %.04f mA", bus_voltage, shunt_voltage * 1000, current * 1000); } if (xSemaphoreTake(xSemaphoreINA219, 25) == pdTRUE) { if (! ina219_state->Solar.fake && ! ina219_state->Battery.fake) { ina219_state->Solar.volts = bus_voltage; ina219_state->Solar.shunt = shunt_voltage; ina219_state->Solar.current = current * 1000; } else if (ina219_state->Solar.fake && ! ina219_state->Battery.fake) { ina219_state->Solar.volts = ina219_state->Battery.volts + 0.78; ina219_state->Solar.shunt = 0.02341; ina219_state->Solar.current = 234.1; } else { ina219_state->Solar.volts = 13.98; ina219_state->Solar.shunt = 0.02341; ina219_state->Solar.current = 234.1; } ina219_state->Solar.valid = true; /* * Now update the outer state */ ina219_state->valid = (ina219_state->Battery.valid && ina219_state->Solar.valid); ina219_state->fake = (ina219_state->Battery.fake || ina219_state->Solar.fake); ina219_state->error = ina219_state->Battery.error; if (ina219_state->error == 0) ina219_state->error = ina219_state->Solar.error; xSemaphoreGive(xSemaphoreINA219); } xEventGroupClearBits(xEventGroupINA219, TASK_INA219_REQUEST_POWER); xEventGroupSetBits(xEventGroupINA219, TASK_INA219_REQUEST_DONE); } } }