/* Current/Voltage meter with INA226 and I2C LCD 2015.08.01 Toshi Nagata */ #include /* ST7032 library by Ore-Kobo */ /* http://ore-kb.net/archives/195 */ #include ST7032 lcd; #define INA226_ADDRESS 0x40 // INA226 I2C address (A0 = A1 = GND) // INA226 calibration register value // 0.00512 / (current_LSB * R_shunt) // In case of INA226PRC, current_LSB = 0.1 mA, R_shunt = 0.025 ohm #define INA226_CAL_VALUE 2048 // 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 0x00 // Power-Down #define INA226_CONF_MODE_TRIG_SHUNT_VOLTAGE 0x01 // Shunt Voltage, Triggered #define INA226_CONF_MODE_TRIG_BUS_VOLTAGE 0x02 // Bus Voltage, Triggered #define INA226_CONF_MODE_TRIG_SHUNT_AND_BUS 0x03 // Shunt and Bus, Triggered #define INA226_CONF_MODE_POWER_DOWN2 0x04 // Power-Down #define INA226_CONF_MODE_CONT_SHUNT_VOLTAGE 0x05 // Shunt Voltage, Continuous #define INA226_CONF_MODE_CONT_BUS_VOLTAGE 0x06 // Bus Voltage, Continuous #define INA226_CONF_MODE_CONT_SHUNT_AND_BUS 0x07 // Shunt and Bus, Continuous (default) // Shunt Voltage Conversion Time (VSH CT Bit Settings [5:3]) #define INA226_CONF_VSH_140uS (0x00 << 3) // 140us #define INA226_CONF_VSH_204uS (0x01 << 3) // 204us #define INA226_CONF_VSH_332uS (0x02 << 3) // 332us #define INA226_CONF_VSH_588uS (0x03 << 3) // 588us #define INA226_CONF_VSH_1100uS (0x04 << 3) // 1.1ms (default) #define INA226_CONF_VSH_2116uS (0x05 << 3) // 2.116ms #define INA226_CONF_VSH_4156uS (0x06 << 3) // 4.156ms #define INA226_CONF_VSH_8244uS (0x07 << 3) // 8.244ms // Bus Voltage Conversion Time (VBUS CT Bit Settings [8:6]) #define INA226_CONF_VBUS_140uS (0x00 << 6) // 140us #define INA226_CONF_VBUS_204uS (0x01 << 6) // 204us #define INA226_CONF_VBUS_332uS (0x02 << 6) // 332us #define INA226_CONF_VBUS_588uS (0x03 << 6) // 588us #define INA226_CONF_VBUS_1100uS (0x04 << 6) // 1.1ms (default) #define INA226_CONF_VBUS_2116uS (0x05 << 6) // 2.116ms #define INA226_CONF_VBUS_4156uS (0x06 << 6) // 4.156ms #define INA226_CONF_VBUS_8244uS (0x07 << 6) // 8.244ms // Averaging Mode (AVG Bit Settings[11:9]) #define INA226_CONF_AVG_1 (0x00 << 9) // 1 (default) #define INA226_CONF_AVG_4 (0x01 << 9) // 4 #define INA226_CONF_AVG_16 (0x02 << 9) // 16 #define INA226_CONF_AVG_64 (0x03 << 9) // 64 #define INA226_CONF_AVG_128 (0x04 << 9) // 128 #define INA226_CONF_AVG_256 (0x05 << 9) // 256 #define INA226_CONF_AVG_512 (0x06 << 9) // 512 #define INA226_CONF_AVG_1024 (0x07 << 9) // 1024 // Reset Bit (RST bit [15]) #define INA226_CONF_RESET_ACTIVE (1 << 15) #define INA226_CONF_RESET_INACTIVE (0 << 15) static void writeRegister(byte reg, word value) { Wire.beginTransmission(INA226_ADDRESS); Wire.write(reg); Wire.write((value >> 8) & 0xFF); Wire.write(value & 0xFF); Wire.endTransmission(); } static void setupRegister(void) { writeRegister(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(INA226_REG_CALIBRATION, INA226_CAL_VALUE); } static word readRegister(byte reg) { word res = 0x0000; Wire.beginTransmission(INA226_ADDRESS); Wire.write(reg); if (Wire.endTransmission() == 0) { if (Wire.requestFrom(INA226_ADDRESS, 2) >= 2) { res = (word)Wire.read() * 256; res += Wire.read(); } } return res; } void setup() { Wire.begin(); setupRegister(); lcd.begin(8, 2, 0, 1); lcd.setContrast(30); } void loop() { char buf[64]; long voltage; // Bus Voltage (LSB = 1 uV) short current; // Current (LSB = 0.1 mA) voltage = (long)((short)readRegister(INA226_REG_BUS_VOLTAGE)) * 1250L; // LSB=1.25mV current = (short)readRegister(INA226_REG_CURRENT); lcd.setCursor(0, 0); snprintf(buf, sizeof buf, "%5ldmV", (voltage + (1000 / 2)) / 1000); lcd.print(buf); if (current >= 10000) { snprintf(buf, sizeof buf, "%5dmA", current / 10); } else { snprintf(buf, sizeof buf, "%3d.%1dmA", current / 10, current % 10); } lcd.setCursor(0, 1); lcd.print(buf); delay(1000); }