118
main/ina226/ina226.c
Normal file
118
main/ina226/ina226.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "ina226.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
#define INA226_REG_CONFIG (0x00)
|
||||
#define INA226_REG_SHUNT_VOLTAGE (0x01)
|
||||
#define INA226_REG_BUS_VOLTAGE (0x02)
|
||||
#define INA226_REG_POWER (0x03)
|
||||
#define INA226_REG_CURRENT (0x04)
|
||||
#define INA226_REG_CALIBRATION (0x05)
|
||||
#define INA226_REG_ALERT_MASK (0x06)
|
||||
#define INA226_REG_ALERT_LIMIT (0x07)
|
||||
#define INA226_REG_MANUFACTURER_ID (0xFE)
|
||||
#define INA226_REG_DIE_ID (0xFF)
|
||||
|
||||
#define INA226_CFG_AVERAGING_OFFSET 9
|
||||
#define INA226_CFG_BUS_VOLTAGE_OFFSET 6
|
||||
#define INA226_CFG_SHUNT_VOLTAGE_OFFSET 3
|
||||
|
||||
static esp_err_t ina226_read_reg(ina226_t *handle, uint8_t reg_addr, uint16_t *data, size_t len)
|
||||
{
|
||||
return i2c_master_transmit_receive(handle->dev_handle, ®_addr, 1, (uint8_t *)data, len, handle->timeout_ms);
|
||||
}
|
||||
|
||||
static esp_err_t ina226_write_reg(ina226_t *handle, uint8_t reg_addr, uint16_t value)
|
||||
{
|
||||
uint8_t write_buf[3] = {reg_addr, value >> 8, value & 0xFF};
|
||||
return i2c_master_transmit(handle->dev_handle, write_buf, sizeof(write_buf), handle->timeout_ms);
|
||||
}
|
||||
|
||||
esp_err_t ina226_get_manufacturer_id(ina226_t *device, uint16_t *manufacturer_id)
|
||||
{
|
||||
return ina226_read_reg(device, INA226_REG_MANUFACTURER_ID, manufacturer_id, 2);
|
||||
}
|
||||
|
||||
esp_err_t ina226_get_die_id(ina226_t *device, uint16_t *die_id)
|
||||
{
|
||||
return ina226_read_reg(device, INA226_REG_DIE_ID, die_id, 2);
|
||||
}
|
||||
|
||||
esp_err_t ina226_get_shunt_voltage(ina226_t *device, float *voltage)
|
||||
{
|
||||
uint8_t data[2];
|
||||
esp_err_t err = ina226_read_reg(device, INA226_REG_SHUNT_VOLTAGE, (uint16_t*)data, 2);
|
||||
*voltage = (float) (data[0] << 8 | data[1]) * 2.5e-6f; /* fixed to 2.5 uV */
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t ina226_get_bus_voltage(ina226_t *device, float *voltage)
|
||||
{
|
||||
uint8_t data[2];
|
||||
esp_err_t err = ina226_read_reg(device, INA226_REG_BUS_VOLTAGE, (uint16_t*)data, 2);
|
||||
*voltage = (float) (data[0] << 8 | data[1]) * 0.00125f;
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t ina226_get_current(ina226_t *device, float *current)
|
||||
{
|
||||
uint8_t data[2];
|
||||
esp_err_t err = ina226_read_reg(device, INA226_REG_CURRENT, (uint16_t*)data, 2);
|
||||
*current = ((float) (data[0] << 8 | data[1])) * device->current_lsb;
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t ina226_get_power(ina226_t *device, float *power)
|
||||
{
|
||||
uint8_t data[2];
|
||||
esp_err_t err = ina226_read_reg(device, INA226_REG_POWER, (uint16_t*)data, 2);
|
||||
*power = (float) (data[0] << 8 | data[1]) * device->power_lsb;
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t ina226_init(ina226_t *device, i2c_master_dev_handle_t dev_handle, const ina226_config_t *config)
|
||||
{
|
||||
esp_err_t err;
|
||||
device->timeout_ms = config->timeout_ms;
|
||||
device->dev_handle = dev_handle;
|
||||
uint16_t bitmask = 0;
|
||||
bitmask |= (config->averages << INA226_CFG_AVERAGING_OFFSET);
|
||||
bitmask |= (config->bus_conv_time << INA226_CFG_BUS_VOLTAGE_OFFSET);
|
||||
bitmask |= (config->shunt_conv_time << INA226_CFG_SHUNT_VOLTAGE_OFFSET);
|
||||
bitmask |= config->mode;
|
||||
err = ina226_write_reg(device, INA226_REG_CONFIG, bitmask);
|
||||
if(err != ESP_OK) return err;
|
||||
|
||||
/* write calibration*/
|
||||
float minimum_lsb = config->max_current / 32767;
|
||||
float current_lsb = (uint16_t)(minimum_lsb * 100000000);
|
||||
current_lsb /= 100000000;
|
||||
current_lsb /= 0.0001;
|
||||
current_lsb = ceil(current_lsb);
|
||||
current_lsb *= 0.0001;
|
||||
device->current_lsb = current_lsb;
|
||||
device->power_lsb = current_lsb * 25;
|
||||
uint16_t calibration_value = (uint16_t)((0.00512) / (current_lsb * config->r_shunt));
|
||||
err = ina226_write_reg(device, INA226_REG_CALIBRATION, calibration_value);
|
||||
if(err != ESP_OK) return err;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t ina226_get_alert_mask(ina226_t *device, ina226_alert_t *alert_mask)
|
||||
{
|
||||
return ina226_read_reg(device, INA226_REG_ALERT_MASK, (uint16_t *)alert_mask, 2);
|
||||
}
|
||||
|
||||
esp_err_t ina226_set_alert_mask(ina226_t *device, ina226_alert_t alert_mask)
|
||||
{
|
||||
return ina226_write_reg(device, INA226_REG_ALERT_MASK, (uint16_t)alert_mask);
|
||||
}
|
||||
|
||||
esp_err_t ina226_set_alert_limit(ina226_t *device, float voltage)
|
||||
{
|
||||
return ina226_write_reg(device, INA226_REG_ALERT_LIMIT, (uint16_t)(voltage));
|
||||
}
|
||||
Reference in New Issue
Block a user