From 5c4b192859b235d71557aab0be638c34aed74557 Mon Sep 17 00:00:00 2001 From: bjackson312006 Date: Thu, 31 Oct 2024 17:51:03 -0400 Subject: [PATCH 1/5] (First draft) Added functions for reading/writing registers and converting to real current, power, and voltage --- general/include/INA226.h | 38 ++++++++++ general/src/INA226.c | 155 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 general/include/INA226.h create mode 100644 general/src/INA226.c diff --git a/general/include/INA226.h b/general/include/INA226.h new file mode 100644 index 0000000..251bd69 --- /dev/null +++ b/general/include/INA226.h @@ -0,0 +1,38 @@ +/* + INA226AQDGSRQ1 Current Sensor I2C Driver + Datasheet: + https://www.ti.com/lit/ds/symlink/ina226-q1.pdf +*/ + +#ifndef INA226_H +#define INA226_H + +// REGISTERS +#define INA226_CONFIGURATION 0x00 +#define INA226_SHUNT_VOLTAGE 0x01 +#define INA226_BUS_VOLTAGE 0x02 +#define INA226_POWER 0x03 +#define INA226_CURRENT 0x04 +#define INA226_CALIBRATION 0x05 +#define INA226_MASK_ENABLE 0x06 +#define INA226_ALERT_LIMIT 0x07 +#define INA226_MANUFACTURER 0xFE +#define INA226_DIE_ID 0xFF + +// CONFIGURATION MASKS +#define INA226_CONFIG_RESET_MASK 0x8000 // Bit 15 +#define INA226_CONFIG_AVERAGE_MASK 0x0E00 // Bits 9-11 +#define INA226_CONFIG_BUSVC_MASK 0x01C0 // Bits 6-8 +#define INA226_CONFIG_SHUNTVC_MASK 0x0038 // Bits 3-5 +#define INA226_CONFIG_MODE_MASK 0x0007 // Bits 0-2 + +// Function Pointers +typedef int (*WritePtr)(uint16_t dev_addr, uint8_t reg, uint16_t *data); +typedef int (*ReadPtr)(uint16_t dev_addr, uint8_t reg, uint16_t *data); + +typedef struct { + uint16_t dev_addr; + WritePtr write; + ReadPtr read; + float current_lsb; +} ina226_t; diff --git a/general/src/INA226.c b/general/src/INA226.c new file mode 100644 index 0000000..d249373 --- /dev/null +++ b/general/src/INA226.c @@ -0,0 +1,155 @@ +/* + INA226AQDGSRQ1 Current Sensor I2C Driver + Datasheet: + https://www.ti.com/lit/ds/symlink/ina226-q1.pdf +*/ + +#include "INA226.h" + +void ina226_init(ina226_t *ina, WritePtr write, ReadPtr read, uint16_t dev_addr) +{ + ina->write = write; + ina->read = read; + ina->dev_addr = dev_addr << 1u; // pretty sure it needs to be shifted + ina->current_lsb = + 0; // temporary value before ina226_calibrate (not sure if i need this?) +} + +int ina226_read_reg(ina226_t *ina, uint8_t reg, uint16_t *data) +{ + return ina->read(ina->dev_addr, reg, data); +} + +int ina226_write_reg(ina226_t *ina, uint8_t reg, uint16_t *data) +{ + return ina->write(ina->dev_addr, reg, data); +} + +// Writes calibration register. r_shunt in ohms, max_current in amps +int ina226_calibrate(ina226_t *ina, float r_shunt, float max_current) +{ + float current_lsb = max_current / 32768; + float cal = 0.00512 / (current_lsb * r_shunt); + uint16_t cal_reg = (uint16_t)floorf(cal); + ina->current_lsb = + 0.00512 / + (cal_reg * + r_shunt); // need to store as an int but not sure how since different current_lsb values might need different scaling factors + + return ina226_write_reg(ina, INA226_CALIBRATION, &cal_reg); +} + +// Reads current in amps +int ina226_read_current(ina226_t *ina, float *data) +{ + uint16_t current_reg; + + int status = ina226_read_reg(ina, INA226_CURRENT, ¤t_reg); + if (status != 0) { + return status; + } + + *data = (float)(int16_t)current_reg * ina->current_lsb; + + return status; +} + +// Reads power in watts +int ina226_read_power(ina226_t *ina, float *data) +{ + uint16_t power_reg; + + int status = ina226_read_reg(ina, INA226_POWER, &power_reg); + if (status != 0) { + return status; + } + + *data = (float)(int16_t)power_reg * (ina->current_lsb * 25); + + return status; +} + +// Reads shunt voltage in volts +int ina226_read_shunt_voltage(ina226_t *ina, float *data) +{ + uint16_t shunt_voltage_reg; + + int status = + ina226_read_reg(ina, INA226_SHUNT_VOLTAGE, &shunt_voltage_reg); + if (status != 0) { + return status; + } + + *data = (float)(int16_t)shunt_voltage_reg * + 2.5e-6; // LSB = 2.5 uV per bit + + return status; +} + +// Reads bus voltage in volts +int ina226_read_bus_voltage(ina226_t *ina, float *data) +{ + uint16_t bus_voltage_reg; + + int status = ina226_read_reg(ina, INA226_BUS_VOLTAGE, &bus_voltage_reg); + if (status != 0) { + return status; + } + + *data = (float)bus_voltage_reg * 1.25e-3; // LSB = 1.25 mV per bit + + return status; +} + +// Sets configuration register bits 0-11 (operating mode, shunt voltage conversion time, bus voltage conversion time, and averaging mode) +// See datasheet for settings +int ina226_configure(ina226_t *ina, uint8_t mode, uint8_t vshct, uint8_t vbusct, + uint8_t avg) +{ + // (probably need to check if params <= 7 but im not sure) + uint16_t configuration; + configuration = (avg << 9) | (vbusct << 6) | (vshct << 3) | mode; + return ina226_write_reg(ina, INA226_CONFIGURATION, &configuration); +} + +// Resets all registers to default values +int ina226_reset(ina226_t ina) +{ + uint16_t reset = INA226_CONFIG_RESET_MASK; + return ina226_write_reg(ina, INA226_CONFIGURATION, &reset); +} + +// Reads manufacturer id register (kinda pointless) +int ina226_read_manufacturer_id(ina226_t ina, uint16_t *data) +{ + uint16_t manufacturer_id; + + int status = + ina226_read_reg(ina, INA226_MANUFACTURER, &manufacturer_id); + if (status != 0) { + return status; + } + + *data = manufacturer_id; + + return status; +} + +// Reads die id (also kinda pointless) +int ina226_read_die_id(ina226_t ina, uint16_t *data) +{ + uint16_t die_id; + + int status = ina226_read_reg(ina, INA226_DIE_ID, &die_id); + if (status != 0) { + return status; + } + + *data = die_id; + + return status; +} + +// still need to do stuff w/ alert register and mask/enable register +// might also want to have functions to set each individual setting in the configuration register +// also not sure if the converted current, power, and voltage should be given as float \ No newline at end of file From 9e0b15a6801f4ec7646e7342e9b82d5937f9cd95 Mon Sep 17 00:00:00 2001 From: bjackson312006 Date: Fri, 1 Nov 2024 22:34:31 -0400 Subject: [PATCH 2/5] Removed some comments --- general/src/INA226.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/general/src/INA226.c b/general/src/INA226.c index d249373..16a98a3 100644 --- a/general/src/INA226.c +++ b/general/src/INA226.c @@ -10,9 +10,8 @@ void ina226_init(ina226_t *ina, WritePtr write, ReadPtr read, uint16_t dev_addr) { ina->write = write; ina->read = read; - ina->dev_addr = dev_addr << 1u; // pretty sure it needs to be shifted - ina->current_lsb = - 0; // temporary value before ina226_calibrate (not sure if i need this?) + ina->dev_addr = dev_addr << 1u; + ina->current_lsb = 0; } int ina226_read_reg(ina226_t *ina, uint8_t reg, uint16_t *data) @@ -31,10 +30,7 @@ int ina226_calibrate(ina226_t *ina, float r_shunt, float max_current) float current_lsb = max_current / 32768; float cal = 0.00512 / (current_lsb * r_shunt); uint16_t cal_reg = (uint16_t)floorf(cal); - ina->current_lsb = - 0.00512 / - (cal_reg * - r_shunt); // need to store as an int but not sure how since different current_lsb values might need different scaling factors + ina->current_lsb = 0.00512 / (cal_reg * r_shunt); return ina226_write_reg(ina, INA226_CALIBRATION, &cal_reg); } @@ -106,7 +102,6 @@ int ina226_read_bus_voltage(ina226_t *ina, float *data) int ina226_configure(ina226_t *ina, uint8_t mode, uint8_t vshct, uint8_t vbusct, uint8_t avg) { - // (probably need to check if params <= 7 but im not sure) uint16_t configuration; configuration = (avg << 9) | (vbusct << 6) | (vshct << 3) | mode; return ina226_write_reg(ina, INA226_CONFIGURATION, &configuration); @@ -119,7 +114,7 @@ int ina226_reset(ina226_t ina) return ina226_write_reg(ina, INA226_CONFIGURATION, &reset); } -// Reads manufacturer id register (kinda pointless) +// Reads manufacturer id register int ina226_read_manufacturer_id(ina226_t ina, uint16_t *data) { uint16_t manufacturer_id; @@ -135,7 +130,7 @@ int ina226_read_manufacturer_id(ina226_t ina, uint16_t *data) return status; } -// Reads die id (also kinda pointless) +// Reads die id int ina226_read_die_id(ina226_t ina, uint16_t *data) { uint16_t die_id; @@ -149,7 +144,3 @@ int ina226_read_die_id(ina226_t ina, uint16_t *data) return status; } - -// still need to do stuff w/ alert register and mask/enable register -// might also want to have functions to set each individual setting in the configuration register -// also not sure if the converted current, power, and voltage should be given as float \ No newline at end of file From b4a1ce17dd488fc59334604520e7bb6ff7e65cb9 Mon Sep 17 00:00:00 2001 From: bjackson312006 Date: Mon, 4 Nov 2024 11:30:29 -0500 Subject: [PATCH 3/5] Added public functions to INA226.h --- general/include/INA226.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/general/include/INA226.h b/general/include/INA226.h index 251bd69..f586d36 100644 --- a/general/include/INA226.h +++ b/general/include/INA226.h @@ -36,3 +36,39 @@ typedef struct { ReadPtr read; float current_lsb; } ina226_t; + +void ina226_init(ina226_t *ina, WritePtr write, ReadPtr read, + uint16_t dev_addr); + +int ina226_read_reg(ina226_t *ina, uint8_t reg, uint16_t *data); + +int ina226_write_reg(ina226_t *ina, uint8_t reg, uint16_t *data); + +// Writes calibration register. r_shunt in ohms, max_current in amps +int ina226_calibrate(ina226_t *ina, float r_shunt, float max_current); + +// Reads current in amps +int ina226_read_current(ina226_t *ina, float *data); + +// Reads power in watts +int ina226_read_power(ina226_t *ina, float *data); + +// Reads shunt voltage in volts +int ina226_read_shunt_voltage(ina226_t *ina, float *data); + +// Reads bus voltage in volts +int ina226_read_bus_voltage(ina226_t *ina, float *data); + +// Sets configuration register bits 0-11 (operating mode, shunt voltage conversion time, bus voltage conversion time, and averaging mode) +// See datasheet for settings +int ina226_configure(ina226_t *ina, uint8_t mode, uint8_t vshct, uint8_t vbusct, + uint8_t avg); + +// Resets all registers to default values +int ina226_reset(ina226_t ina); + +// Reads manufacturer id register +int ina226_read_manufacturer_id(ina226_t ina, uint16_t *data); + +// Reads die id +int ina226_read_die_id(ina226_t ina, uint16_t *data); \ No newline at end of file From d99f8f2342a9311d714ab1bc5a8eb7ed5b1e2bde Mon Sep 17 00:00:00 2001 From: bjackson312006 Date: Wed, 6 Nov 2024 19:51:23 -0500 Subject: [PATCH 4/5] Added missing #endif to INA226.h --- general/include/INA226.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/general/include/INA226.h b/general/include/INA226.h index f586d36..339feb9 100644 --- a/general/include/INA226.h +++ b/general/include/INA226.h @@ -71,4 +71,6 @@ int ina226_reset(ina226_t ina); int ina226_read_manufacturer_id(ina226_t ina, uint16_t *data); // Reads die id -int ina226_read_die_id(ina226_t ina, uint16_t *data); \ No newline at end of file +int ina226_read_die_id(ina226_t ina, uint16_t *data); + +#endif //INA226_H \ No newline at end of file From f88fecfd9ad80d3a8f8f82a215364867d232280e Mon Sep 17 00:00:00 2001 From: bjackson312006 Date: Wed, 6 Nov 2024 20:53:11 -0500 Subject: [PATCH 5/5] Fixed various issues that were preventing building --- general/include/INA226.h | 8 +++++--- general/src/INA226.c | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/general/include/INA226.h b/general/include/INA226.h index 339feb9..59c336d 100644 --- a/general/include/INA226.h +++ b/general/include/INA226.h @@ -6,6 +6,8 @@ #ifndef INA226_H #define INA226_H +#include +#include // REGISTERS #define INA226_CONFIGURATION 0x00 @@ -65,12 +67,12 @@ int ina226_configure(ina226_t *ina, uint8_t mode, uint8_t vshct, uint8_t vbusct, uint8_t avg); // Resets all registers to default values -int ina226_reset(ina226_t ina); +int ina226_reset(ina226_t *ina); // Reads manufacturer id register -int ina226_read_manufacturer_id(ina226_t ina, uint16_t *data); +int ina226_read_manufacturer_id(ina226_t *ina, uint16_t *data); // Reads die id -int ina226_read_die_id(ina226_t ina, uint16_t *data); +int ina226_read_die_id(ina226_t *ina, uint16_t *data); #endif //INA226_H \ No newline at end of file diff --git a/general/src/INA226.c b/general/src/INA226.c index 16a98a3..0a440d1 100644 --- a/general/src/INA226.c +++ b/general/src/INA226.c @@ -108,14 +108,14 @@ int ina226_configure(ina226_t *ina, uint8_t mode, uint8_t vshct, uint8_t vbusct, } // Resets all registers to default values -int ina226_reset(ina226_t ina) +int ina226_reset(ina226_t *ina) { uint16_t reset = INA226_CONFIG_RESET_MASK; return ina226_write_reg(ina, INA226_CONFIGURATION, &reset); } // Reads manufacturer id register -int ina226_read_manufacturer_id(ina226_t ina, uint16_t *data) +int ina226_read_manufacturer_id(ina226_t *ina, uint16_t *data) { uint16_t manufacturer_id; @@ -131,7 +131,7 @@ int ina226_read_manufacturer_id(ina226_t ina, uint16_t *data) } // Reads die id -int ina226_read_die_id(ina226_t ina, uint16_t *data) +int ina226_read_die_id(ina226_t *ina, uint16_t *data) { uint16_t die_id;