main/task_ina219.c

Mon, 03 Apr 2023 20:11:29 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 03 Apr 2023 20:11:29 +0200
changeset 13
c3b29a1dcf1e
parent 6
bad3414f7bc4
child 14
2a9f67ecbc72
permissions
-rw-r--r--

Changed voltage range to 32 volt. Tried INA219 powersave mode, doesn't work.

/**
 * @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, 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_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.
		 */
//		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_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, &current));
		ESP_ERROR_CHECK(ina219_get_power(&ina219_b_dev, &power));
//		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_POWER_DOWN));
		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 (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;
		}
		ina219_state->Battery.valid = true;
		xSemaphoreGive(xSemaphoreINA219);
	    }

	    if (! ina219_state->Solar.fake) {
//		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_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, &current));
                ESP_ERROR_CHECK(ina219_get_power(&ina219_s_dev, &power));
//		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_POWER_DOWN));
                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);
	    }
	    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;
		} 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);
	}
    }
}

mercurial