Thu, 06 Apr 2023 20:53:06 +0200
Set the new measured deep sleep current consumption. This is half of the Wemos D1 system.
/* * Copyright (c) 2019 Ruslan V. Uss <unclerus@gmail.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of itscontributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file ina219.c * * ESP-IDF driver for INA219/INA220 Zerø-Drift, Bidirectional * Current/Power Monitor * * Copyright (c) 2019 Ruslan V. Uss <unclerus@gmail.com> * * BSD Licensed as described in the file LICENSE */ #include <esp_log.h> #include <math.h> #include <esp_idf_lib_helpers.h> #include "ina219.h" #define I2C_FREQ_HZ 1000000 // Max 1 MHz for esp-idf, but supports up to 2.56 MHz static const char *TAG = "ina219"; #define REG_CONFIG 0 #define REG_SHUNT_U 1 #define REG_BUS_U 2 #define REG_POWER 3 #define REG_CURRENT 4 #define REG_CALIBRATION 5 #define BIT_RST 15 #define BIT_BRNG 13 #define BIT_PG0 11 #define BIT_BADC0 7 #define BIT_SADC0 3 #define BIT_MODE 0 #define MASK_PG (3 << BIT_PG0) #define MASK_BADC (0xf << BIT_BADC0) #define MASK_SADC (0xf << BIT_SADC0) #define MASK_MODE (7 << BIT_MODE) #define MASK_BRNG (1 << BIT_BRNG) #define DEF_CONFIG 0x399f #define CHECK(x) do { esp_err_t __; if ((__ = x) != ESP_OK) return __; } while (0) #define CHECK_ARG(VAL) do { if (!(VAL)) return ESP_ERR_INVALID_ARG; } while (0) static const float u_shunt_max[] = { [INA219_GAIN_1] = 0.04, [INA219_GAIN_0_5] = 0.08, [INA219_GAIN_0_25] = 0.16, [INA219_GAIN_0_125] = 0.32, }; static esp_err_t read_reg_16(ina219_t *dev, uint8_t reg, uint16_t *val) { CHECK_ARG(val); I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); I2C_DEV_CHECK(&dev->i2c_dev, i2c_dev_read_reg(&dev->i2c_dev, reg, val, 2)); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); *val = (*val >> 8) | (*val << 8); return ESP_OK; } static esp_err_t write_reg_16(ina219_t *dev, uint8_t reg, uint16_t val) { uint16_t v = (val >> 8) | (val << 8); I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); I2C_DEV_CHECK(&dev->i2c_dev, i2c_dev_write_reg(&dev->i2c_dev, reg, &v, 2)); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } static esp_err_t read_conf_bits(ina219_t *dev, uint16_t mask, uint8_t bit, uint16_t *res) { uint16_t raw; CHECK(read_reg_16(dev, REG_CONFIG, &raw)); *res = (raw & mask) >> bit; return ESP_OK; } /////////////////////////////////////////////////////////////////////////////// esp_err_t ina219_init_desc(ina219_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio) { CHECK_ARG(dev); if (addr < INA219_ADDR_GND_GND || addr > INA219_ADDR_SCL_SCL) { ESP_LOGE(TAG, "Invalid I2C address"); return ESP_ERR_INVALID_ARG; } dev->i2c_dev.port = port; dev->i2c_dev.addr = addr; dev->i2c_dev.cfg.sda_io_num = sda_gpio; dev->i2c_dev.cfg.scl_io_num = scl_gpio; #if HELPER_TARGET_IS_ESP32 dev->i2c_dev.cfg.master.clk_speed = I2C_FREQ_HZ; #endif return i2c_dev_create_mutex(&dev->i2c_dev); } esp_err_t ina219_free_desc(ina219_t *dev) { CHECK_ARG(dev); return i2c_dev_delete_mutex(&dev->i2c_dev); } esp_err_t ina219_init(ina219_t *dev) { CHECK_ARG(dev); CHECK(read_reg_16(dev, REG_CONFIG, &dev->config)); ESP_LOGD(TAG, "Initialize, config: 0x%04x", dev->config); return ESP_OK; } esp_err_t ina219_reset(ina219_t *dev) { CHECK_ARG(dev); CHECK(write_reg_16(dev, REG_CONFIG, 1 << BIT_RST)); dev->config = DEF_CONFIG; ESP_LOGD(TAG, "Device reset"); return ESP_OK; } esp_err_t ina219_configure(ina219_t *dev, ina219_bus_voltage_range_t u_range, ina219_gain_t gain, ina219_resolution_t u_res, ina219_resolution_t i_res, ina219_mode_t mode) { CHECK_ARG(dev); CHECK_ARG(u_range <= INA219_BUS_RANGE_32V); CHECK_ARG(gain <= INA219_GAIN_0_125); CHECK_ARG(u_res <= INA219_RES_12BIT_128S); CHECK_ARG(i_res <= INA219_RES_12BIT_128S); CHECK_ARG(mode <= INA219_MODE_CONT_SHUNT_BUS); dev->config = (u_range << BIT_BRNG) | (gain << BIT_PG0) | (u_res << BIT_BADC0) | (i_res << BIT_SADC0) | (mode << BIT_MODE); ESP_LOGD(TAG, "Config: 0x%04x", dev->config); return write_reg_16(dev, REG_CONFIG, dev->config); } esp_err_t ina219_get_bus_voltage_range(ina219_t *dev, ina219_bus_voltage_range_t *range) { CHECK_ARG(dev && range); *range = 0; return read_conf_bits(dev, MASK_BRNG, BIT_BRNG, (uint16_t *)range); } esp_err_t ina219_get_gain(ina219_t *dev, ina219_gain_t *gain) { CHECK_ARG(dev && gain); *gain = 0; return read_conf_bits(dev, MASK_PG, BIT_PG0, (uint16_t *)gain); } esp_err_t ina219_get_bus_voltage_resolution(ina219_t *dev, ina219_resolution_t *res) { CHECK_ARG(dev && res); *res = 0; return read_conf_bits(dev, MASK_BADC, BIT_BADC0, (uint16_t *)res); } esp_err_t ina219_get_shunt_voltage_resolution(ina219_t *dev, ina219_resolution_t *res) { CHECK_ARG(dev && res); *res = 0; return read_conf_bits(dev, MASK_SADC, BIT_SADC0, (uint16_t *)res); } esp_err_t ina219_get_mode(ina219_t *dev, ina219_mode_t *mode) { CHECK_ARG(dev && mode); *mode = 0; return read_conf_bits(dev, MASK_MODE, BIT_MODE, (uint16_t *)mode); } esp_err_t ina219_calibrate(ina219_t *dev, float i_expected_max, float r_shunt) { CHECK_ARG(dev); ina219_gain_t gain; CHECK(ina219_get_gain(dev, &gain)); dev->i_lsb = (uint16_t)(u_shunt_max[gain] / r_shunt / 32767 * 100000000); dev->i_lsb /= 100000000; dev->i_lsb /= 0.0001; dev->i_lsb = ceil(dev->i_lsb); dev->i_lsb *= 0.0001; dev->p_lsb = dev->i_lsb * 20; uint16_t cal = (uint16_t)((0.04096) / (dev->i_lsb * r_shunt)); ESP_LOGD(TAG, "Calibration: %.04f A, %.04f Ohm, 0x%04x", i_expected_max, r_shunt, cal); return write_reg_16(dev, REG_CALIBRATION, cal); } esp_err_t ina219_trigger(ina219_t *dev) { CHECK_ARG(dev); uint16_t mode = (dev->config & MASK_MODE) >> BIT_MODE; if (mode < INA219_MODE_TRIG_SHUNT || mode > INA219_MODE_TRIG_SHUNT_BUS) { ESP_LOGE(TAG, "Could not trigger conversion in this mode: %d", mode); return ESP_ERR_INVALID_STATE; } return write_reg_16(dev, REG_CONFIG, dev->config); } esp_err_t ina219_get_bus_voltage(ina219_t *dev, float *voltage) { CHECK_ARG(dev && voltage); int16_t raw; CHECK(read_reg_16(dev, REG_BUS_U, (uint16_t *)&raw)); *voltage = (raw >> 3) * 0.004; return ESP_OK; } esp_err_t ina219_get_shunt_voltage(ina219_t *dev, float *voltage) { CHECK_ARG(dev && voltage); int16_t raw; CHECK(read_reg_16(dev, REG_SHUNT_U, (uint16_t *)&raw)); *voltage = raw / 100000.0; return ESP_OK; } esp_err_t ina219_get_current(ina219_t *dev, float *current) { CHECK_ARG(dev && current); int16_t raw; CHECK(read_reg_16(dev, REG_CURRENT, (uint16_t *)&raw)); *current = raw * dev->i_lsb; return ESP_OK; } esp_err_t ina219_get_power(ina219_t *dev, float *power) { CHECK_ARG(dev && power); int16_t raw; CHECK(read_reg_16(dev, REG_POWER, (uint16_t *)&raw)); *power = raw * dev->p_lsb; return ESP_OK; }