diff --git a/examples/ina3221_test/Makefile b/examples/ina3221_test/Makefile new file mode 100644 index 0000000..328435a --- /dev/null +++ b/examples/ina3221_test/Makefile @@ -0,0 +1,3 @@ +PROGRAM=ina3221_test +EXTRA_COMPONENTS = extras/i2c extras/mcp4725 +include ../../common.mk diff --git a/examples/ina3221_test/main.c b/examples/ina3221_test/main.c new file mode 100644 index 0000000..174acdd --- /dev/null +++ b/examples/ina3221_test/main.c @@ -0,0 +1,106 @@ +/* + * Example of using INA3221 + * + * Part of esp-open-rtos + * Copyright (C) 2016 Zaltora + * MIT Licensed as described in the file LICENSE + */ + +#include "espressif/esp_common.h" +#include "FreeRTOS.h" +#include "task.h" +#include +#include +#include "ina3221/ina3221.h" + +#define PIN_SCL 4 +#define PIN_SDA 2 +#define ADDR INA3221_ADDR_0 + +//#define STRUCT_SETTING 1 + +void loop(void *pvParameters) +{ + uint32_t measure_number = 0; + float bus_voltage; + float shunt_voltage; + float shunt_current; + + // Create ina3221 device + ina3221_t dev = { + .addr = ADDR, + .shunt = { 100 ,100 ,100 }, // shunt values are 100 mOhm for each channel + .mask.mask_register = INA3221_DEFAULT_MASK, // Init + .config.config_register = INA3221_DEFAULT_CONFIG, // Init + }; + +#ifndef STRUCT_SETTING + if(ina3221_setting(&dev ,false, true, true)) // trigger mode, bus and shunt activated + goto error_loop; + if(ina3221_enableChannel(&dev , true, true, true)) // Enable all channels + goto error_loop; + if(ina3221_setAverage(&dev, INA3221_AVG_64)) // 64 samples average + goto error_loop; + if(ina3221_setBusConversionTime(&dev, INA3221_CT_2116)) // 2ms by channel + goto error_loop; + if(ina3221_setShuntConversionTime(&dev, INA3221_CT_2116)) // 2ms by channel + goto error_loop; +#else + dev.config.mode = false; // trigger mode + dev.config.esht = true; // shunt enable + dev.config.ebus = true; // bus enable + dev.config.ch1 = true; // channel 1 enable + dev.config.ch2 = true; // channel 2 enable + dev.config.ch3 = true; // channel 3 enable + dev.config.avg = INA3221_AVG_64; // 64 samples average + dev.config.vbus = INA3221_CT_2116; // 2ms by channel (bus) + dev.config.vsht = INA3221_CT_2116; // 2ms by channel (shunt) + if(ina3221_sync(&dev)) + goto error_loop; +#endif + + while(1) + { + measure_number++; + do + { + if (ina3221_trigger(&dev)) // Start a measure & get mask + goto error_loop; + } while(!(dev.mask.cvrf)); // check if measure done + + for (uint8_t i = 0 ; i < BUS_NUMBER ; i++) { + + if(ina3221_getBusVoltage(&dev, i, &bus_voltage)) // Get voltage in V + goto error_loop; + if(ina3221_getShuntValue(&dev, i, &shunt_voltage, &shunt_current)) // Get voltage in mV and currant in mA + goto error_loop; + + printf("Measure number %u\n", measure_number); + printf("Bus voltage: %.02f V\n", bus_voltage ); + printf("Shunt voltage: %.02f mV\n", shunt_voltage ); + printf("Shunt current: %.02f mA\n\n", shunt_current ); + + } + vTaskDelay(5000/portTICK_PERIOD_MS); + } + + error_loop: + printf("%s: error while com with INA3221\n", __func__); + for(;;){ + vTaskDelay(2000 / portTICK_PERIOD_MS); + printf("%s: error loop\n", __FUNCTION__); + } + +} + + + +void user_init(void) +{ + uart_set_baud(0, 115200); + printf("SDK version:%s\n", sdk_system_get_sdk_version()); + + i2c_init(PIN_SCL,PIN_SDA); + + xTaskCreate(loop, "tsk1", 512, NULL, 2, NULL); +} diff --git a/extras/ina3221/ina3221.c b/extras/ina3221/ina3221.c index eb0cf93..23b39ec 100644 --- a/extras/ina3221/ina3221.c +++ b/extras/ina3221/ina3221.c @@ -13,8 +13,6 @@ #define debug(fmt, ...) #endif -#define sign(x) ((x > 0) - (x < 0)) - static int _wireWriteRegister (uint8_t addr, uint8_t reg, uint16_t value) { i2c_start(); @@ -31,7 +29,7 @@ static int _wireWriteRegister (uint8_t addr, uint8_t reg, uint16_t value) return 0 ; error: - debug("Error while xmitting I2C slave INA3221\n"); + debug("Error while xmitting I2C slave\n"); i2c_stop(); return -EIO; } @@ -55,7 +53,7 @@ static int _wireReadRegister(uint8_t addr, uint8_t reg, uint16_t *value) return 0; error: - debug("Error while xmitting I2C slave INA3221\n"); + debug("Error while xmitting I2C slave\n"); i2c_stop(); return -EIO; } @@ -131,87 +129,82 @@ int ina3221_reset(ina3221_t *dev) { dev->config.config_register = INA3221_DEFAULT_CONFIG ; //dev reset dev->mask.mask_register = INA3221_DEFAULT_CONFIG ; //dev reset - dev->config.reset = 1 ; + dev->config.rst = 1 ; return _wireWriteRegister(dev->addr, INA3221_REG_CONFIG, dev->config.config_register); // send reset to device } -int ina3221_getBusVoltage(ina3221_t *dev, ina3221_channel_t channel, int32_t *voltage) +int ina3221_getBusVoltage(ina3221_t *dev, ina3221_channel_t channel, float *voltage) { int16_t raw_value; int err = 0; if ((err = _wireReadRegister(dev->addr,INA3221_REG_BUSVOLTAGE_1+channel*2, (uint16_t*)&raw_value))) return err; - *voltage = (raw_value>>3)*8; //mV 8mV step + *voltage = raw_value*0.001 ; //V 8mV step return 0; } -int ina3221_getShuntValue(ina3221_t *dev, ina3221_channel_t channel, int32_t *voltage, int32_t *current) +int ina3221_getShuntValue(ina3221_t *dev, ina3221_channel_t channel, float *voltage, float *current) { int16_t raw_value; int err = 0; if ((err = _wireReadRegister(dev->addr,INA3221_REG_SHUNTVOLTAGE_1+channel*2, (uint16_t*)&raw_value))) return err; - *voltage = (raw_value>>3)*40 ; //uV 40uV step + *voltage = raw_value*0.005; //mV 40uV step if(!dev->shunt[channel]) { - debug("No shunt configured for channel %u. Dev:%X INA3221\n",channel+1, dev->addr); + debug("No shunt configured for channel %u. Dev:%X\n",channel+1, dev->addr); return -EINVAL; } - *current = *voltage/dev->shunt[channel] ; //mA = uV / mOhm + *current = (*voltage*1000.0)/dev->shunt[channel] ; //mA return 0; } -int ina3221_getSumShuntValue(ina3221_t *dev, int32_t *voltage) +int ina3221_getSumShuntValue(ina3221_t *dev, float *voltage) { int16_t raw_value; int err = 0; if ((err = _wireReadRegister(dev->addr,INA3221_REG_SHUNT_VOLTAGE_SUM, (uint16_t*)&raw_value))) return err; - *voltage = (raw_value>>1)*40; //uV 40uV step + *voltage = raw_value*0.02; //uV 40uV step return 0; } -int ina3221_setCriticalAlert(ina3221_t *dev, ina3221_channel_t channel, int32_t current) +int ina3221_setCriticalAlert(ina3221_t *dev, ina3221_channel_t channel, float current) { - int16_t raw_value = ((current*dev->shunt[channel]+20*sign(current))/40)<<3; // round and format - uint16_t* ptr_value = (uint16_t*)&raw_value; // FIXME: Need this to convert int to uint without change data ? - return _wireWriteRegister(dev->addr,INA3221_REG_CRITICAL_ALERT_1+channel*2, *ptr_value); + int16_t raw_value = current*dev->shunt[channel]*0.2; // format + return _wireWriteRegister(dev->addr,INA3221_REG_CRITICAL_ALERT_1+channel*2, *(uint16_t*)&raw_value); } -int ina3221_setWarningAlert(ina3221_t *dev, ina3221_channel_t channel, int32_t current) +int ina3221_setWarningAlert(ina3221_t *dev, ina3221_channel_t channel, float current) { - int16_t raw_value = ((current*dev->shunt[channel]+ 20*sign(current))/40)<<3; // round and format - uint16_t* ptr_value = (uint16_t*)&raw_value; // FIXME: Need this to convert int to uint without change data ? - return _wireWriteRegister(dev->addr,INA3221_REG_WARNING_ALERT_1+channel*2, *ptr_value); + int16_t raw_value = current*dev->shunt[channel]*0.2 ; // format + return _wireWriteRegister(dev->addr,INA3221_REG_WARNING_ALERT_1+channel*2, *(uint16_t*)&raw_value); } -int ina3221_setSumWarningAlert(ina3221_t *dev, int32_t voltage) +int ina3221_setSumWarningAlert(ina3221_t *dev, float voltage) { - int16_t raw_value = ((voltage + 20*sign(voltage))/40)<<1; // round and format - uint16_t* ptr_value = (uint16_t*)&raw_value; // FIXME: Need this to convert int to uint without change data ? - return _wireWriteRegister(dev->addr,INA3221_REG_SHUNT_VOLTAGE_SUM_LIMIT, *ptr_value); + int16_t raw_value = voltage*50.0 ; // format + return _wireWriteRegister(dev->addr,INA3221_REG_SHUNT_VOLTAGE_SUM_LIMIT, *(uint16_t*)&raw_value); } -int ina3221_setPowerValidUpperLimit(ina3221_t *dev, int32_t voltage) +int ina3221_setPowerValidUpperLimit(ina3221_t *dev, float voltage) { if(!dev->config.ebus) { - debug("Bus not enable. Dev:%X INA3221\n", dev->addr); + debug("Bus not enable. Dev:%X\n", dev->addr); return -ENOTSUP; } - int16_t raw_value = ((voltage+4*sign(voltage))/8)<<3; // round and format - uint16_t* ptr_value = (uint16_t*)&raw_value; // FIXME: Need this to convert int to uint without change data ? - return _wireWriteRegister(dev->addr,INA3221_REG_VALID_POWER_UPPER_LIMIT, *ptr_value); + int16_t raw_value = voltage*1000.0; //format + return _wireWriteRegister(dev->addr,INA3221_REG_VALID_POWER_UPPER_LIMIT, *(uint16_t*)&raw_value); } -int ina3221_setPowerValidLowerLimit(ina3221_t *dev, int32_t voltage) +int ina3221_setPowerValidLowerLimit(ina3221_t *dev, float voltage) { if(!dev->config.ebus) { - debug("Bus not enable. Dev:%X INA3221\n", dev->addr); + debug("Bus not enable. Dev:%X\n", dev->addr); return -ENOTSUP; } - int16_t raw_value = ((voltage+4*sign(voltage))/8)<<3; // round and format - uint16_t* ptr_value = (uint16_t*)&raw_value; // FIXME: Need this to convert int to uint without change data ? - return _wireWriteRegister(dev->addr,INA3221_REG_VALID_POWER_LOWER_LIMIT, *ptr_value); + int16_t raw_value = voltage*1000.0; // round and format + return _wireWriteRegister(dev->addr,INA3221_REG_VALID_POWER_LOWER_LIMIT, *(uint16_t*)&raw_value); } diff --git a/extras/ina3221/ina3221.h b/extras/ina3221/ina3221.h index ed7057b..667a913 100644 --- a/extras/ina3221/ina3221.h +++ b/extras/ina3221/ina3221.h @@ -85,19 +85,19 @@ typedef enum { typedef union { struct { - uint16_t esht : 1 ; // Enable/Disable shunt measure // LSB - uint16_t ebus : 1 ; // Enable/Disable bus measure - uint16_t mode : 1 ; // Single shot measure or continious mode - uint16_t vsht : 3 ; // Shunt voltage conversion time - uint16_t vbus : 3 ; // Bus voltage conversion time - uint16_t avg : 3 ; // number of sample collected and averaged together - uint16_t ch3 : 1 ; // Enable/Disable channel 3 - uint16_t ch2 : 1 ; // Enable/Disable channel 2 - uint16_t ch1 : 1 ; // Enable/Disable channel 1 - uint16_t reset : 1 ; //Set this bit to 1 to reset device // MSB + uint16_t esht : 1; // Enable/Disable shunt measure // LSB + uint16_t ebus : 1; // Enable/Disable bus measure + uint16_t mode : 1; // Single shot measure or continious mode + uint16_t vsht : 3; // Shunt voltage conversion time + uint16_t vbus : 3; // Bus voltage conversion time + uint16_t avg : 3; // number of sample collected and averaged together + uint16_t ch3 : 1; // Enable/Disable channel 3 + uint16_t ch2 : 1; // Enable/Disable channel 2 + uint16_t ch1 : 1; // Enable/Disable channel 1 + uint16_t rst : 1; //Set this bit to 1 to reset device // MSB }; - uint16_t config_register ; -} ina3221_config_t ; + uint16_t config_register; +} ina3221_config_t; /* @@ -123,17 +123,17 @@ typedef union uint16_t scc1 : 1 ; // channel 1 sum (1:enable) uint16_t : 1 ; //Reserved //MSB }; - uint16_t mask_register ; -} ina3221_mask_t ; + uint16_t mask_register; +} ina3221_mask_t; /* * Device description */ typedef struct { - uint8_t addr ; // ina3221 I2C address - ina3221_config_t config ; //Memory of ina3221 config - ina3221_mask_t mask ; //Memory of mask_config - uint16_t shunt[BUS_NUMBER] ; //Memory of shunt value (mOhm) + const uint8_t addr; // ina3221 I2C address + const uint16_t shunt[BUS_NUMBER]; //Memory of shunt value (mOhm) + ina3221_config_t config; //Memory of ina3221 config + ina3221_mask_t mask; //Memory of mask_config } ina3221_t; /** @@ -221,76 +221,76 @@ int ina3221_setShuntConversionTime(ina3221_t *dev,ina3221_ct_t ct); int ina3221_reset(ina3221_t *dev); /** - * Get Bus voltage (mV) + * Get Bus voltage (V) * @param dev Pointer to device descriptor * @param channel Select channel value to get - * @param voltage Data pointer to get bus voltage (mV) + * @param voltage Data pointer to get bus voltage (V) * @return Non-zero if error occured */ -int ina3221_getBusVoltage(ina3221_t *dev, ina3221_channel_t channel, int32_t *voltage); +int ina3221_getBusVoltage(ina3221_t *dev, ina3221_channel_t channel, float *voltage); /** - * Get Shunt voltage (uV) and current (mA) + * Get Shunt voltage (mV) and current (mA) * @param dev Pointer to device descriptor * @param channel Select channel value to get - * @param voltage Data pointer to get shunt voltage (uV) + * @param voltage Data pointer to get shunt voltage (mV) * @param current Data pointer to get shunt voltage (mA) * @return Non-zero if error occured */ -int ina3221_getShuntValue(ina3221_t *dev, ina3221_channel_t channel, int32_t *voltage, int32_t *current); +int ina3221_getShuntValue(ina3221_t *dev, ina3221_channel_t channel, float *voltage, float *current); /** - * Get Shunt-voltage (uV) sum value of selected channels + * Get Shunt-voltage (mV) sum value of selected channels * @param dev Pointer to device descriptor * @param channel Select channel value to get - * @param voltage Data pointer to get shunt voltage (uV) + * @param voltage Data pointer to get shunt voltage (mV) * @return Non-zero if error occured */ -int ina3221_getSumShuntValue(ina3221_t *dev, int32_t *voltage); +int ina3221_getSumShuntValue(ina3221_t *dev, float *voltage); /** * Set Critical alert (when measurement(s) is greater that value set ) * @param dev Pointer to device descriptor * @param channel Select channel value to set - * @param current Value to set (mA) + * @param current Value to set (mA) // max : 163800/shunt (mOhm) * @return Non-zero if error occured */ -int ina3221_setCriticalAlert(ina3221_t *dev, ina3221_channel_t channel, int32_t current); +int ina3221_setCriticalAlert(ina3221_t *dev, ina3221_channel_t channel, float current); /** * Set Warning alert (when average measurement(s) is greater that value set ) * @param dev Pointer to device descriptor * @param channel Select channel value to set - * @param current Value to set (mA) + * @param current Value to set (mA) // max : 163800/shunt (mOhm) * @return Non-zero if error occured */ -int ina3221_setWarningAlert(ina3221_t *dev, ina3221_channel_t channel, int32_t current); +int ina3221_setWarningAlert(ina3221_t *dev, ina3221_channel_t channel, float current); /** * Set Sum Warning alert (Compared to each completed cycle of all selected channels : Sum register ) * @param dev Pointer to device descriptor - * @param voltage voltage to set (uV) : 40uV step + * @param voltage voltage to set (mV) // max : 655.32 * @return Non-zero if error occured */ -int ina3221_setSumWarningAlert(ina3221_t *dev, int32_t voltage); +int ina3221_setSumWarningAlert(ina3221_t *dev, float voltage); /** * Set Power-valid upper-limit ( To determine if power conditions are met.)( bus need enable ) * If bus voltage exceed the value set, PV pin is high * @param dev Pointer to device descriptor - * @param voltage voltage to set (mV) : 8mV step + * @param voltage voltage to set (V) * @return Non-zero if error occured */ -int ina3221_setPowerValidUpperLimit(ina3221_t *dev, int32_t voltage); +int ina3221_setPowerValidUpperLimit(ina3221_t *dev, float voltage); /** * Set Power-valid lower-limit ( To determine if power conditions are met.)( bus need enable ) * If bus voltage drops below the value set, PV pin is low * @param dev Pointer to device descriptor - * @param voltage voltage to set (mV) : 8mV step + * @param voltage voltage to set (V) * @return Non-zero if error occured */ -int ina3221_setPowerValidLowerLimit(ina3221_t *dev, int32_t voltage); +int ina3221_setPowerValidLowerLimit(ina3221_t *dev, float voltage); #ifdef __cplusplus }