-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(First draft) Added functions for reading/writing registers and conve…
…rting to real current, power, and voltage
- Loading branch information
1 parent
fe86adc
commit 5c4b192
Showing
2 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |