Skip to content

Instantly share code, notes, and snippets.

@tom-a tom-a/ina226.ino
Created May 12, 2019

Embed
What would you like to do?
/*
Texas Instruments INA226 Control sample
tomozh@gmail.com
2013.09.03 fix power miscalculation bug
2013.03.16 1st release
https://ore-kb.net/archives/150
がベース。計算部分を単純化したり、ambientにデータを投げたり。
tomoaki@akiyama.nu
*/
#include <esp_wifi.h>
#include <Wire.h>
#include "Ambient.h"
#define NELEMS(arg) (sizeof(arg) / sizeof((arg)[0]))
const unsigned int PERIOD = 58; //
const unsigned int uS_TO_S_FACTOR = 1000000;
const unsigned int channelId = 00000;
const char* writeKey = "xxxxxxxxxxxxxxxx";
const char* ssid = "SSID";
const char* password = "PASSWORD";
const byte GPIO_34 = 34;
const int INA226_PANNEL_ADDR = 0x40;
const int INA226_BATTERY_ADDR = 0x41;
const word INA226_CAL_VALUE = 0x0A00;
// INA226 Registers
#define INA226_REG_CONGIGURATION_REG 0x00 // Configuration Register (R/W)
#define INA226_REG_SHUNT_VOLTAGE 0x01 // Shunt Voltage (R)
#define INA226_REG_BUS_VOLTAGE 0x02 // Bus Voltage (R)
#define INA226_REG_POWER 0x03 // Power (R)
#define INA226_REG_CURRENT 0x04 // Current (R)
#define INA226_REG_CALIBRATION 0x05 // Calibration (R/W)
#define INA226_REG_MASK_ENABLE 0x06 // Mask/Enable (R/W)
#define INA226_REG_ALERT_LIMIT 0x07 // Alert Limit (R/W)
#define INA226_REG_DIE_ID 0xFF // Die ID (R)
// Operating Mode (Mode Settings [2:0])
#define INA226_CONF_MODE_POWER_DOWN (0<<0) // Power-Down
#define INA226_CONF_MODE_TRIG_SHUNT_VOLTAGE (1<<0) // Shunt Voltage, Triggered
#define INA226_CONF_MODE_TRIG_BUS_VOLTAGE (2<<0) // Bus Voltage, Triggered
#define INA226_CONF_MODE_TRIG_SHUNT_AND_BUS (3<<0) // Shunt and Bus, Triggered
#define INA226_CONF_MODE_POWER_DOWN2 (4<<0) // Power-Down
#define INA226_CONF_MODE_CONT_SHUNT_VOLTAGE (5<<0) // Shunt Voltage, Continuous
#define INA226_CONF_MODE_CONT_BUS_VOLTAGE (6<<0) // Bus Voltage, Continuous
#define INA226_CONF_MODE_CONT_SHUNT_AND_BUS (7<<0) // Shunt and Bus, Continuous (default)
// Shunt Voltage Conversion Time (VSH CT Bit Settings [5:3])
#define INA226_CONF_VSH_140uS (0<<3) // 140us
#define INA226_CONF_VSH_204uS (1<<3) // 204us
#define INA226_CONF_VSH_332uS (2<<3) // 332us
#define INA226_CONF_VSH_588uS (3<<3) // 588us
#define INA226_CONF_VSH_1100uS (4<<3) // 1.1ms (default)
#define INA226_CONF_VSH_2116uS (5<<3) // 2.116ms
#define INA226_CONF_VSH_4156uS (6<<3) // 4.156ms
#define INA226_CONF_VSH_8244uS (7<<3) // 8.244ms
// Bus Voltage Conversion Time (VBUS CT Bit Settings [8:6])
#define INA226_CONF_VBUS_140uS (0<<6) // 140us
#define INA226_CONF_VBUS_204uS (1<<6) // 204us
#define INA226_CONF_VBUS_332uS (2<<6) // 332us
#define INA226_CONF_VBUS_588uS (3<<6) // 588us
#define INA226_CONF_VBUS_1100uS (4<<6) // 1.1ms (default)
#define INA226_CONF_VBUS_2116uS (5<<6) // 2.116ms
#define INA226_CONF_VBUS_4156uS (6<<6) // 4.156ms
#define INA226_CONF_VBUS_8244uS (7<<6) // 8.244ms
// Averaging Mode (AVG Bit Settings[11:9])
#define INA226_CONF_AVG_1 (0<<9) // 1 (default)
#define INA226_CONF_AVG_4 (1<<9) // 4
#define INA226_CONF_AVG_16 (2<<9) // 16
#define INA226_CONF_AVG_64 (3<<9) // 64
#define INA226_CONF_AVG_128 (4<<9) // 128
#define INA226_CONF_AVG_256 (5<<9) // 256
#define INA226_CONF_AVG_512 (6<<9) // 512
#define INA226_CONF_AVG_1024 (7<<9) // 1024
// Reset Bit (RST bit [15])
#define INA226_CONF_RESET_ACTIVE (1<<15)
#define INA226_CONF_RESET_INACTIVE (0<<15)
WiFiClient client;
Ambient ambient;
static void writeRegister(byte deviceAddress, byte reg, word value)
{
Wire.beginTransmission(deviceAddress);
Wire.write(reg);
Wire.write((value >> 8) & 0xFF);
Wire.write(value & 0xFF);
Wire.endTransmission();
}
static void setupRegister(byte deviceAddress)
{
writeRegister(deviceAddress,
INA226_REG_CONGIGURATION_REG,
INA226_CONF_RESET_INACTIVE
| INA226_CONF_MODE_CONT_SHUNT_AND_BUS
| INA226_CONF_VSH_1100uS
| INA226_CONF_VBUS_1100uS
| INA226_CONF_AVG_64
);
writeRegister(deviceAddress, INA226_REG_CALIBRATION, INA226_CAL_VALUE);
}
static word readRegister(byte deviceAddress, byte reg)
{
word value = 0x0000;
Wire.beginTransmission(deviceAddress);
Wire.write(reg);
if (Wire.endTransmission() == 0) {
if (Wire.requestFrom(deviceAddress, 2) >= 2) {
value = Wire.read() << 8;
value += Wire.read();
}
}
return value;
}
typedef struct tagREG_INFO {
byte reg;
const char* name;
} REG_INFO;
const static REG_INFO st_aRegs[] = {
{ INA226_REG_CONGIGURATION_REG, "Configuration Register" },
{ INA226_REG_SHUNT_VOLTAGE, "Shunt Voltage" },
{ INA226_REG_BUS_VOLTAGE, "Bus Voltage" },
{ INA226_REG_POWER, "Power" },
{ INA226_REG_CURRENT, "Current" },
{ INA226_REG_CALIBRATION, "Calibration" },
{ INA226_REG_MASK_ENABLE, "Mask/Enable" },
{ INA226_REG_ALERT_LIMIT, "Alert Limit" },
{ INA226_REG_DIE_ID, "Die ID" },
};
static void dumpRegisters(byte deviceAddress)
{
int i;
const REG_INFO* pInfo;
static word REGS[NELEMS(st_aRegs)];
for (i = 0; i < NELEMS(REGS); i++) {
pInfo = &st_aRegs[i];
REGS[i] = readRegister(deviceAddress, pInfo->reg);
}
Serial.printf("---INA226 Registers ---\n");
for (i = 0; i < NELEMS(REGS); i++) {
pInfo = &st_aRegs[i];
Serial.printf("%24s (%02Xh) : %04Xh (%u)\n", pInfo->name, pInfo->reg, REGS[i], REGS[i]);
}
}
int wifiConnect(void)
{
int count = 0;
WiFi.disconnect(true);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (6 < count++) {
Serial.printf("\nWiFi connect faild.\n");
return(false);
}
}
Serial.printf("\nWiFi connected.\n");
Serial.printf("IP address: ");
Serial.println(WiFi.localIP());
return(true);
}
void setup()
{
pinMode(21, INPUT_PULLUP);
pinMode(22, INPUT_PULLUP);
Wire.begin();
Serial.begin(115200);
analogSetPinAttenuation(GPIO_34, ADC_11db);
setupRegister(INA226_PANNEL_ADDR);
setupRegister(INA226_BATTERY_ADDR);
ambient.begin(channelId, writeKey, &client);
float currentPannel = readRegister(INA226_PANNEL_ADDR, INA226_REG_CURRENT) / 1000.0;
while (10.0 < currentPannel) {
currentPannel = readRegister(INA226_PANNEL_ADDR, INA226_REG_CURRENT) / 1000.0;
}
float voltagePannel = 1.25 * readRegister(INA226_PANNEL_ADDR, INA226_REG_BUS_VOLTAGE) / 1000.0;
float powerPannel = 25.0 * readRegister(INA226_PANNEL_ADDR, INA226_REG_POWER) / 1000.0;
int cb = readRegister(INA226_BATTERY_ADDR, INA226_REG_CURRENT);
if (cb & 0x8000) {
cb -= 0x10000;
}
float currentBattery = cb / 1000.0;
while (10.0 < currentBattery) {
currentBattery = readRegister(INA226_BATTERY_ADDR, INA226_REG_CURRENT) / 1000.0;
}
float voltageBattery = 1.25 * readRegister(INA226_BATTERY_ADDR, INA226_REG_BUS_VOLTAGE) / 1000.0;
float powerBattery = 25.0 * readRegister(INA226_BATTERY_ADDR, INA226_REG_POWER) / 1000.0;
if (currentBattery < 0) {
powerBattery = -powerBattery;
}
int sensorValue = analogRead(GPIO_34);
float voltagePower = 3.3 * sensorValue / 4095.0;
Serial.printf("\n%5.2fV, %5.2fA, %5.2fW, %5d %5.2fV\n", voltagePannel, currentPannel, powerPannel, sensorValue, voltagePower);
dumpRegisters(INA226_PANNEL_ADDR);
Serial.printf("\n%5.2fV, %5.2fA, %5.2fW\n", voltageBattery, currentBattery, powerBattery);
dumpRegisters(INA226_BATTERY_ADDR);
if (wifiConnect()) {
ambient.set(1, voltagePannel);
ambient.set(2, currentPannel);
ambient.set(3, powerPannel);
ambient.set(4, voltagePower);
ambient.set(5, voltageBattery);
ambient.set(6, currentBattery);
ambient.set(7, powerBattery);
ambient.send();
}
Serial.println("Setup ESP32 to sleep for every " + String(PERIOD) + " Seconds");
Serial.println("Going to sleep now");
esp_wifi_stop();
esp_deep_sleep(PERIOD * uS_TO_S_FACTOR);
delay(1000);
}
void loop()
{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.