From f1c102b111199ed4dbb8690e684ad2fac43db3e3 Mon Sep 17 00:00:00 2001 From: Arnd Date: Tue, 19 Sep 2017 08:04:40 +0200 Subject: [PATCH 1/6] Added structure Changed class instantiation to count the number of INA226s found --- INA226.cpp | 45 ++++++++++++++++++++++++++++++++++++++------- INA226.h | 21 +++++++++++++++++++-- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/INA226.cpp b/INA226.cpp index 9f4358e..dcebb60 100644 --- a/INA226.cpp +++ b/INA226.cpp @@ -14,13 +14,43 @@ *******************************************************************************************************************/ #include "INA226.h" // Include the header definition // #include // I2C Library definition // -INA226_Class::INA226_Class() {} // Unused class constructor // +/******************************************************************************************************************* +** Class constructor takes no parameters, but searches the I2C bus to see how many of the 16 possible INA226s are ** +** found and allocates sufficient memory to store all data about them. ** +*******************************************************************************************************************/ +INA226_Class::INA226_Class() { // Class constructor // + Wire.begin(); // Start the I2C wire subsystem // + for(uint8_t deviceAddress = 1;deviceAddress<127;deviceAddress++) { // Loop for each possible address // + Wire.beginTransmission(deviceAddress); // See if something is at address // + if (Wire.endTransmission() == 0) { // by checking the return error // + writeWord(INA_CONFIGURATION_REGISTER,INA_RESET_DEVICE); // Force INAs to reset // + delay(I2C_DELAY); // Wait for INA to finish resetting // + if (readWord(INA_CONFIGURATION_REGISTER)==INA_DEFAULT_CONFIGURATION) // Yes, we've found an INA226! // + inaCount++; // Increment the counter // + } // of if-then we have found a live device // // + } // for-next each possible I2C address // // + if (inaCount) ina = new inaDet [inaCount]; else return; // Dynamically allocate space // + uint8_t currentIndex = 0; + for(uint8_t deviceAddress = 1;deviceAddress<127;deviceAddress++) { // Loop for each possible address // + Wire.beginTransmission(deviceAddress); // See if something is at address // + if (Wire.endTransmission() == 0) { // by checking the return error // + writeWord(INA_CONFIGURATION_REGISTER,INA_RESET_DEVICE); // Force INAs to reset // + delay(I2C_DELAY); // Wait for INA to finish resetting // + if (readWord(INA_CONFIGURATION_REGISTER)==INA_DEFAULT_CONFIGURATION) { // Yes, we've found an INA226! // + ina[currentIndex].address = deviceAddress; // Store address of this device // + ina[currentIndex].operatingMode = B111; // Default continuous mode operation// + } // of if-then we've found an INA226 // // + } // of if-then we have found a live device // // + } // for-next each possible I2C address // // +} // of class constructor // // INA226_Class::~INA226_Class() {} // Unused class destructor // /******************************************************************************************************************* -** Method begin() does all of the initialization work ** +** Method begin() does all of the initialization work. The number of INA226s found is determined as part of the ** +** the class constructor and is store in "inaCount". The INA226 device number is the optional 3rd parameter to ** +** allow backward compatibility to the original library ** *******************************************************************************************************************/ void INA226_Class::begin(const uint8_t maxBusAmps, const uint32_t microOhmR){ // Class initializer // - Wire.begin(); // Start the I2C wire subsystem // + uint8_t currentDevice = 0; // Internal array address // for(_DeviceAddress = 1;_DeviceAddress<127;_DeviceAddress++) { // Loop for each possible address // Wire.beginTransmission(_DeviceAddress); // See if something is at address // if (Wire.endTransmission() == 0) { // by checking the return error // @@ -32,10 +62,11 @@ void INA226_Class::begin(const uint8_t maxBusAmps, const uint32_t microOhmR){ // (uint64_t)microOhmR / (uint64_t)100000); // using 64 bit numbers throughout // _Power_LSB = (uint32_t)25*_Current_LSB; // Fixed multiplier for INA219 // writeWord(INA_CALIBRATION_REGISTER,_Calibration); // Write the calibration value // - break; // Stop searching // - } // of if-then we've found an INA226 // // - } // of if-then we have found a live device // // - } // for-next each possible I2C address // // + break; // Stop searching // + } // of if-then we've found an INA226 // // + } // of if-then we have found a live device // // + } // for-next each possible I2C address // // + return inaCount; // Return number of devices foudn // } // of method begin() // // /******************************************************************************************************************* ** Method readByte reads 1 byte from the specified address ** diff --git a/INA226.h b/INA226.h index 52db66e..45e60b8 100644 --- a/INA226.h +++ b/INA226.h @@ -33,6 +33,7 @@ ** ** ** Vers. Date Developer Comments ** ** ====== ========== ============================= ============================================================== ** +** 1.0.5a 2017-09-18 https://github.com/SV-Zanshin https://github.com/SV-Zanshin/INA226/issues/6. Multiple Devices** ** 1.0.4 2017-08-13 https://github.com/SV-Zanshin Enhancement #5, removed while() loop after Wire.requestFrom() ** ** 1.0.3 2017-08-09 https://github.com/SV-Zanshin Fix https://github.com/SV-Zanshin/INA226/issues/4. Overflows ** ** in computations of begin() and getShuntMicroVolts() functions. ** @@ -47,10 +48,24 @@ #include "Arduino.h" // Arduino data type definitions // #ifndef INA226_Class_h // Guard code definition // #define INA226__Class_h // Define the name inside guard code// + /***************************************************************************************************************** + ** Declare structures used in the class ** + *****************************************************************************************************************/ + typedef struct { // Structure of values per device // + uint8_t address; // I2C Address of device // + uint8_t transmissionStatus; // Return code for I2C transmission // + uint16_t calibration; // Calibration register value // + uint16_t configuration; // Configuration register value // + uint32_t current_LSB; // Amperage LSB // + uint32_t power_LSB; // Wattage LSB // + uint8_t operatingMode; // Default continuous mode operation// + } inaDet; // of structure // // + /***************************************************************************************************************** ** Declare constants used in the class ** *****************************************************************************************************************/ const uint8_t I2C_DELAY = 10; // Microsecond delay on write // + const uint8_t INA_MAX_DEVICES = 16; // Maximum number of INA226 devices // const uint8_t INA_CONFIGURATION_REGISTER = 0; // Registers common to all INAs // const uint8_t INA_SHUNT_VOLTAGE_REGISTER = 1; // // const uint8_t INA_BUS_VOLTAGE_REGISTER = 2; // // @@ -81,7 +96,7 @@ public: // Publicly visible methods // INA226_Class(); // Class constructor // ~INA226_Class(); // Class destructor // - void begin(const uint8_t maxBusAmps, const uint32_t micoOhmR); // Class initializer // + void begin(const uint8_t maxBusAmps, const uint32_t microOhmR); // Class initializer // uint16_t getBusMilliVolts(const bool waitSwitch=false); // Retrieve Bus voltage in mV // int16_t getShuntMicroVolts(const bool waitSwitch=false); // Retrieve Shunt voltage in uV // int32_t getBusMicroAmps(); // Retrieve micro-amps // @@ -105,5 +120,7 @@ uint32_t _Current_LSB = 0; // Amperage LSB // uint32_t _Power_LSB = 0; // Wattage LSB // uint8_t _OperatingMode = B111; // Default continuous mode operation// - }; // of MicrochipSRAM class definition // // + inaDet* ina = 0; // INA226 array with zero elements // + uint8_t inaCount = 0; // Array of INA226 details at size 0// + }; // of INA226_Class definition // // #endif //----------------------------------// From 088bf8b5e3c9ec69bcc21ef18dcd5f0682fca0e0 Mon Sep 17 00:00:00 2001 From: Arnd Date: Tue, 19 Sep 2017 10:19:19 +0200 Subject: [PATCH 2/6] Added multiple devices --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7637e95..9db761d 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ different and require the functions and methods in this library to access. ## Hardware layout The [datasheet](http://www.ti.com/lit/ds/symlink/ina226.pdf) has examples of how to hook up INA226. The package is a small VSSOP and I used a blank breakout board, some solder paste, a frying pan, desoldering braid, a magnifying glass and quite a bit of time to set up the first breadboard example. I've since seen breakout boards available on the web but since only a few external components are necessary apart from connecting the 10 pins of the INA226 I'll remain with self-build. ## Library description -The library will locate the INA226 on the I2C chain and with 4 setup parameters describing the expected voltage, shunt / resistor values the internal configuration registers will be set and the library is ready to begin very accurate measurements. The details of how to setup the library along with all of the publicly available methods can be found on the [INA226 wiki pages](https://github.com/SV-Zanshin/INA226/wiki). -Great lengths have been gone to avoid the use of floating point in the library. To keep the original level of precision without loss but to allow the full range of voltages and amperes to be returned the amperage results are returned as 32-bit integers. +The library locates all INA226 devices on the I2C chain. Each unit can be individually configured with 4 setup parameters describing the expected voltage, shunt / resistor values which then set the internal configuration registers is ready to begin accurate measurements. The details of how to setup the library along with all of the publicly available methods can be found on the [INA226 wiki pages](https://github.com/SV-Zanshin/INA226/wiki). +Great lengths have been taken to avoid the use of floating point in the library. To keep the original level of precision without loss but to allow the full range of voltages and amperes to be returned the amperage results are returned as 32-bit integers. The INA226 has a dedicated interrupt pin which can be used to trigger pin-change interrupts on the Arduino and the examples show a program that measures readings using this output pin so that the Arduino can perform other concurrent tasks while still retrieving measurements. From 4305a68d9af0e5729c14fc1b4fffeccfc92dd374 Mon Sep 17 00:00:00 2001 From: Arnd Date: Tue, 19 Sep 2017 12:54:32 +0200 Subject: [PATCH 3/6] Initial EEPROM coding --- INA226.cpp | 75 +++++++++++++++++++++++++++--------------------------- INA226.h | 12 ++++----- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/INA226.cpp b/INA226.cpp index dcebb60..6607746 100644 --- a/INA226.cpp +++ b/INA226.cpp @@ -14,59 +14,60 @@ *******************************************************************************************************************/ #include "INA226.h" // Include the header definition // #include // I2C Library definition // +#include // Include the EEPROM library // + /******************************************************************************************************************* ** Class constructor takes no parameters, but searches the I2C bus to see how many of the 16 possible INA226s are ** ** found and allocates sufficient memory to store all data about them. ** *******************************************************************************************************************/ INA226_Class::INA226_Class() { // Class constructor // + inaDet ina; // Hold device details in structure // Wire.begin(); // Start the I2C wire subsystem // for(uint8_t deviceAddress = 1;deviceAddress<127;deviceAddress++) { // Loop for each possible address // Wire.beginTransmission(deviceAddress); // See if something is at address // if (Wire.endTransmission() == 0) { // by checking the return error // writeWord(INA_CONFIGURATION_REGISTER,INA_RESET_DEVICE); // Force INAs to reset // delay(I2C_DELAY); // Wait for INA to finish resetting // - if (readWord(INA_CONFIGURATION_REGISTER)==INA_DEFAULT_CONFIGURATION) // Yes, we've found an INA226! // - inaCount++; // Increment the counter // + if (readWord(INA_CONFIGURATION_REGISTER)==INA_DEFAULT_CONFIGURATION) { // Yes, we've found an INA226! // + ina.address = deviceAddress; // Store device address // + ina.operatingMode = B111; // Default to continuous mode // + if (_DeviceCount*sizeof(ina) Date: Tue, 19 Sep 2017 18:31:25 +0200 Subject: [PATCH 4/6] Continued coding for multiple INA226s --- INA226.cpp | 64 +++++++++++++++++++++++++++++------------------------- INA226.h | 20 ++++++++++------- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/INA226.cpp b/INA226.cpp index 6607746..7259f5b 100644 --- a/INA226.cpp +++ b/INA226.cpp @@ -49,47 +49,43 @@ void INA226_Class::begin(const uint8_t maxBusAmps, // const uint32_t microOhmR, // // const uint8_t deviceNumber ) { // // inaDet ina; // Hold device details in structure // + EEPROM.get((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Read EEPROM values // ina.current_LSB = (uint64_t)maxBusAmps*1000000000/32767; // Get the best possible LSB in nA // ina.calibration = (uint64_t)51200000 / ((uint64_t)_Current_LSB * // Compute calibration register // (uint64_t)microOhmR / (uint64_t)100000); // using 64 bit numbers throughout // ina.power_LSB = (uint32_t)25*_Current_LSB; // Fixed multiplier for INA219 // if (deviceNumber==UINT8_MAX) { // If default value, then set all // - for(uint8_t i=0;i<_DeviceCount;i++) EEPROM.put(i*sizeof(ina),ina); // Write value to address // - -// writeWord(INA_CALIBRATION_REGISTER,_Calibration); // Write the calibration value // - - + for(uint8_t i=0;i<_DeviceCount;i++) { // For each device write data // + EEPROM.put(i*sizeof(ina),ina); // Write value to address // + writeWord(INA_CALIBRATION_REGISTER,ina.calibration,ina.address); // Write the calibration value // + } // of for each device // // } else { // // EEPROM.put((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Write struct, cater for overflow // -// writeWord(INA_CALIBRATION_REGISTER,_Calibration); // Write the calibration value // + writeWord(INA_CALIBRATION_REGISTER,ina.calibration,ina.address); // Write the calibration value // } // of if-then-else set one or all devices // // - - - - return; // Return number of devices found // } // of method begin() // // /******************************************************************************************************************* ** Method readByte reads 1 byte from the specified address ** *******************************************************************************************************************/ -uint8_t INA226_Class::readByte(const uint8_t addr) { // // - Wire.beginTransmission(_DeviceAddress); // Address the I2C device // +uint8_t INA226_Class::readByte(const uint8_t addr,const uint8_t deviceAddr){ // // + Wire.beginTransmission(deviceAddr); // Address the I2C device // Wire.write(addr); // Send the register address to read// _TransmissionStatus = Wire.endTransmission(); // Close transmission // delayMicroseconds(I2C_DELAY); // delay required for sync // - Wire.requestFrom(_DeviceAddress, (uint8_t)1); // Request 1 byte of data // + Wire.requestFrom(deviceAddr, (uint8_t)1); // Request 1 byte of data // return Wire.read(); // read it and return it // } // of method readByte() // // /******************************************************************************************************************* ** Method readWord reads 2 bytes from the specified address ** *******************************************************************************************************************/ -int16_t INA226_Class::readWord(const uint8_t addr) { // // +int16_t INA226_Class::readWord(const uint8_t addr,const uint8_t deviceAddr){ // // int16_t returnData; // Store return value // - Wire.beginTransmission(_DeviceAddress); // Address the I2C device // + Wire.beginTransmission(deviceAddr); // Address the I2C device // Wire.write(addr); // Send the register address to read// _TransmissionStatus = Wire.endTransmission(); // Close transmission // delayMicroseconds(I2C_DELAY); // delay required for sync // - Wire.requestFrom(_DeviceAddress, (uint8_t)2); // Request 2 consecutive bytes // + Wire.requestFrom(deviceAddr, (uint8_t)2); // Request 2 consecutive bytes // returnData = Wire.read(); // Read the msb // returnData = returnData<<8; // shift the data over // returnData|= Wire.read(); // Read the lsb // @@ -98,8 +94,9 @@ int16_t INA226_Class::readWord(const uint8_t addr) { // /******************************************************************************************************************* ** Method writeByte write 1 byte to the specified address ** *******************************************************************************************************************/ -void INA226_Class::writeByte(const uint8_t addr, const uint8_t data) { // // - Wire.beginTransmission(_DeviceAddress); // Address the I2C device // +void INA226_Class::writeByte(const uint8_t addr, const uint8_t data, // // + const uint8_t deviceAddr) { // // + Wire.beginTransmission(deviceAddr); // Address the I2C device // Wire.write(addr); // Send register address to write // Wire.write(data); // Send the data to write // _TransmissionStatus = Wire.endTransmission(); // Close transmission // @@ -107,8 +104,9 @@ void INA226_Class::writeByte(const uint8_t addr, const uint8_t data) { // /******************************************************************************************************************* ** Method writeWord writes 2 byte to the specified address ** *******************************************************************************************************************/ -void INA226_Class::writeWord(const uint8_t addr, const uint16_t data) { // // - Wire.beginTransmission(_DeviceAddress); // Address the I2C device // +void INA226_Class::writeWord(const uint8_t addr, const uint16_t data, // // + const uint8_t deviceAddr) { // // + Wire.beginTransmission(deviceAddr); // Address the I2C device // Wire.write(addr); // Send register address to write // Wire.write((uint8_t)(data>>8)); // Write the first byte // Wire.write((uint8_t)data); // and then the second // @@ -117,26 +115,32 @@ void INA226_Class::writeWord(const uint8_t addr, const uint16_t data) { // /******************************************************************************************************************* ** Method getBusMilliVolts retrieves the bus voltage measurement ** *******************************************************************************************************************/ -uint16_t INA226_Class::getBusMilliVolts(const bool waitSwitch) { // // +uint16_t INA226_Class::getBusMilliVolts(const bool waitSwitch, // // + const uint8_t deviceNumber) { // // + inaDet ina; // Hold device details in structure // + EEPROM.get((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Read EEPROM values // if (waitSwitch) waitForConversion(); // wait for conversion to complete // - uint16_t busVoltage = readWord(INA_BUS_VOLTAGE_REGISTER); // Get the raw value and apply // + uint16_t busVoltage = readWord(INA_BUS_VOLTAGE_REGISTER,ina.address); // Get the raw value and apply // busVoltage = (uint32_t)busVoltage*INA_BUS_VOLTAGE_LSB/100; // conversion to get milliVolts // - if (!bitRead(_OperatingMode,2) && bitRead(_OperatingMode,1)) { // If triggered mode and bus active // - int16_t configRegister = readWord(INA_CONFIGURATION_REGISTER); // Get the current register // - writeWord(INA_CONFIGURATION_REGISTER,configRegister); // Write back to trigger next // + if (!bitRead(ina.operatingMode,2) && bitRead(ina.operatingMode,1)) { // If triggered mode and bus active // + int16_t configRegister = readWord(INA_CONFIGURATION_REGISTER,ina.address);// Get the current register // + writeWord(INA_CONFIGURATION_REGISTER,configRegister,ina.address); // Write back to trigger next // } // of if-then triggered mode enabled // // return(busVoltage); // return computed milliVolts // } // of method getBusMilliVolts() // // /******************************************************************************************************************* ** Method getShuntMicroVolts retrieves the shunt voltage measurement ** *******************************************************************************************************************/ -int16_t INA226_Class::getShuntMicroVolts(const bool waitSwitch) { // // +int16_t INA226_Class::getShuntMicroVolts(const bool waitSwitch, // // + const uint8_t deviceNumber) { // // + inaDet ina; // Hold device details in structure // + EEPROM.get((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Read EEPROM values // if (waitSwitch) waitForConversion(); // wait for conversion to complete // - int32_t shuntVoltage = readWord(INA_SHUNT_VOLTAGE_REGISTER); // Get the raw value // + int32_t shuntVoltage = readWord(INA_SHUNT_VOLTAGE_REGISTER,ina.address); // Get the raw value // shuntVoltage = shuntVoltage*INA_SHUNT_VOLTAGE_LSB/10; // Convert to microvolts // - if (!bitRead(_OperatingMode,2) && bitRead(_OperatingMode,0)) { // If triggered and shunt active // - int16_t configRegister = readWord(INA_CONFIGURATION_REGISTER); // Get the current register // - writeWord(INA_CONFIGURATION_REGISTER,configRegister); // Write back to trigger next // + if (!bitRead(ina.operatingMode,2) && bitRead(ina.operatingMode,0)) { // If triggered and shunt active // + int16_t configRegister = readWord(INA_CONFIGURATION_REGISTER,ina.address);// Get the current register // + writeWord(INA_CONFIGURATION_REGISTER,configRegister,ina.address); // Write back to trigger next // } // of if-then triggered mode enabled // // return((int16_t)shuntVoltage); // return computed microvolts // } // of method getShuntMicroVolts() // // diff --git a/INA226.h b/INA226.h index 18cc0a0..f3a3bd3 100644 --- a/INA226.h +++ b/INA226.h @@ -96,9 +96,11 @@ ~INA226_Class(); // Class destructor // void begin(const uint8_t maxBusAmps, // Class initializer // const uint32_t microOhmR, // // - const uint8_t deviceNumber = UINT8_MAX ); // // - uint16_t getBusMilliVolts(const bool waitSwitch=false); // Retrieve Bus voltage in mV // - int16_t getShuntMicroVolts(const bool waitSwitch=false); // Retrieve Shunt voltage in uV // + const uint8_t deviceNumber = UINT8_MAX ); // // + uint16_t getBusMilliVolts(const bool waitSwitch=false, // Retrieve Bus voltage in mV // + const uint8_t deviceNumber=0); // // + int16_t getShuntMicroVolts(const bool waitSwitch=false, // Retrieve Shunt voltage in uV // + const uint8_t deviceNumber=0); // // int32_t getBusMicroAmps(); // Retrieve micro-amps // int32_t getBusMicroWatts(); // Retrieve micro-watts // void reset(); // Reset the device // @@ -109,16 +111,18 @@ void setAlertPinOnConversion(const bool alertState); // Enable pin change on conversion // void waitForConversion(); // wait for conversion to complete // private: // Private variables and methods // - uint8_t readByte(const uint8_t addr); // Read a byte from an I2C address // - int16_t readWord(const uint8_t addr); // Read a word from an I2C address // - void writeByte(const uint8_t addr, const uint8_t data); // Write a byte to an I2C address // - void writeWord(const uint8_t addr, const uint16_t data); // Write two bytes to an I2C address// + uint8_t readByte(const uint8_t addr,const uint8_t deviceAddress=0); // Read a byte from an I2C address // + int16_t readWord(const uint8_t addr,const uint8_t deviceAddress=0); // Read a word from an I2C address // + void writeByte(const uint8_t addr, const uint8_t data, // Write a byte to an I2C address // + const uint8_t deviceAddress=0); // // + void writeWord(const uint8_t addr, const uint16_t data, // Write two bytes to an I2C address// + const uint8_t deviceAddress=0); // // uint8_t _DeviceAddress = 0; // First I2C address found // uint8_t _TransmissionStatus = 0; // Return code for I2C transmission // uint16_t _Calibration = 0; // Calibration register value // uint32_t _Current_LSB = 0; // Amperage LSB // uint32_t _Power_LSB = 0; // Wattage LSB // - uint8_t _OperatingMode = B111; // Default continuous mode operation// +// uint8_t _OperatingMode = B111; // Default continuous mode operation// uint8_t _DeviceCount = 0; // Number of INA226s detected // }; // of INA226_Class definition // // #endif //----------------------------------// From 43e8d61a86169a54aad3e51c92721b82a1ab0257 Mon Sep 17 00:00:00 2001 From: Arnd Date: Thu, 21 Sep 2017 16:50:05 +0200 Subject: [PATCH 5/6] Finished adding device to all functions --- Examples/DisplayReadings/DisplayReadings.ino | 12 +- INA226.cpp | 183 ++++++++++++------- INA226.h | 29 ++- 3 files changed, 140 insertions(+), 84 deletions(-) diff --git a/Examples/DisplayReadings/DisplayReadings.ino b/Examples/DisplayReadings/DisplayReadings.ino index d6b42c0..fe5378a 100644 --- a/Examples/DisplayReadings/DisplayReadings.ino +++ b/Examples/DisplayReadings/DisplayReadings.ino @@ -41,6 +41,7 @@ const uint32_t SERIAL_SPEED = 115200; // ** Declare global variables and instantiate classes ** *******************************************************************************************************************/ INA226_Class INA226; // INA class instantiation // +uint8_t devicesFound = 0; // Number of INA226s found // /******************************************************************************************************************* ** Declare prototypes for all functions used ** *******************************************************************************************************************/ @@ -58,10 +59,13 @@ void setup() { // #endif // interface to initialize // Serial.print(F("\n\nDisplay INA226 Readings V1.0.1\n")); // Display program information // // The begin initialized the calibration for an expected ±1 Amps maximum current and for a 0.1Ohm resistor // - INA226.begin(1,100000); // // + devicesFound = INA226.begin(1,100000); // All devices set to same values // + Serial.print(F("Detected ")); // // + Serial.print(devicesFound); // // + Serial.println(F(" INA226 devices on I2C bus")); // // INA226.setAveraging(4); // Average each reading n-times // - INA226.setBusConversion(); // Maximum conversion time 8.244ms // - INA226.setShuntConversion(); // Maximum conversion time 8.244ms // + INA226.setBusConversion(7); // Maximum conversion time 8.244ms // + INA226.setShuntConversion(7); // Maximum conversion time 8.244ms // INA226.setMode(INA_MODE_CONTINUOUS_BOTH); // Bus/shunt measured continuously // } // of method setup() // // /******************************************************************************************************************* @@ -76,7 +80,7 @@ void loop() { // Serial.print((float)INA226.getShuntMicroVolts()/1000.0,3); // Convert to millivolts // Serial.println(F("mV")); // // Serial.print(F("Bus amperage: ")); // // - Serial.print((float)INA226.getBusMicroAmps()/1000.0,3); // Convert to milliamps // + Serial.print((float)INA226.getBusMicroAmps()/1000.0,3); // Convert to milliamp // Serial.println(F("mA")); // // Serial.print(F("Bus wattage: ")); // // Serial.print((float)INA226.getBusMicroWatts()/1000.0,3); // Convert to milliwatts // diff --git a/INA226.cpp b/INA226.cpp index 7259f5b..2f2bc8e 100644 --- a/INA226.cpp +++ b/INA226.cpp @@ -45,15 +45,15 @@ INA226_Class::~INA226_Class() {} // ** is called without the option deviceNumber parameter then the settings are applied to all devices, otherwise ** ** just that specific device is targeted. ** *******************************************************************************************************************/ -void INA226_Class::begin(const uint8_t maxBusAmps, // Class initializer // - const uint32_t microOhmR, // // - const uint8_t deviceNumber ) { // // +uint8_t INA226_Class::begin(const uint8_t maxBusAmps, // Class initializer // + const uint32_t microOhmR, // // + const uint8_t deviceNumber ) { // // inaDet ina; // Hold device details in structure // EEPROM.get((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Read EEPROM values // ina.current_LSB = (uint64_t)maxBusAmps*1000000000/32767; // Get the best possible LSB in nA // - ina.calibration = (uint64_t)51200000 / ((uint64_t)_Current_LSB * // Compute calibration register // + ina.calibration = (uint64_t)51200000 / ((uint64_t)ina.current_LSB * // Compute calibration register // (uint64_t)microOhmR / (uint64_t)100000); // using 64 bit numbers throughout // - ina.power_LSB = (uint32_t)25*_Current_LSB; // Fixed multiplier for INA219 // + ina.power_LSB = (uint32_t)25*ina.current_LSB; // Fixed multiplier for INA219 // if (deviceNumber==UINT8_MAX) { // If default value, then set all // for(uint8_t i=0;i<_DeviceCount;i++) { // For each device write data // EEPROM.put(i*sizeof(ina),ina); // Write value to address // @@ -63,7 +63,7 @@ void INA226_Class::begin(const uint8_t maxBusAmps, // EEPROM.put((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Write struct, cater for overflow // writeWord(INA_CALIBRATION_REGISTER,ina.calibration,ina.address); // Write the calibration value // } // of if-then-else set one or all devices // // - return; // Return number of devices found // + return _DeviceCount; // Return number of devices found // } // of method begin() // // /******************************************************************************************************************* ** Method readByte reads 1 byte from the specified address ** @@ -147,92 +147,145 @@ int16_t INA226_Class::getShuntMicroVolts(const bool waitSwitch, // /******************************************************************************************************************* ** Method getBusMicroAmps retrieves the computed current in microamps. ** *******************************************************************************************************************/ -int32_t INA226_Class::getBusMicroAmps() { // // - int32_t microAmps = readWord(INA_CURRENT_REGISTER); // Get the raw value // - microAmps = (int64_t)microAmps*_Current_LSB/1000; // Convert to microamps // +int32_t INA226_Class::getBusMicroAmps(const uint8_t deviceNumber) { // // + inaDet ina; // Hold device details in structure // + EEPROM.get((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Read EEPROM values // + int32_t microAmps = readWord(INA_CURRENT_REGISTER,ina.address); // Get the raw value // + microAmps = (int64_t)microAmps*ina.current_LSB/1000; // Convert to microamps // return(microAmps); // return computed microamps // } // of method getBusMicroAmps() // // /******************************************************************************************************************* ** Method getBusMicroWatts retrieves the computed power in milliwatts ** *******************************************************************************************************************/ -int32_t INA226_Class::getBusMicroWatts() { // // - int32_t microWatts = readWord(INA_POWER_REGISTER); // Get the raw value // - microWatts = (int64_t)microWatts*_Power_LSB/1000; // Convert to milliwatts // +int32_t INA226_Class::getBusMicroWatts(const uint8_t deviceNumber) { // // + inaDet ina; // Hold device details in structure // + EEPROM.get((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Read EEPROM values // + int32_t microWatts = readWord(INA_POWER_REGISTER,ina.address); // Get the raw value // + microWatts = (int64_t)microWatts*ina.power_LSB/1000; // Convert to milliwatts // return(microWatts); // return computed milliwatts // } // of method getBusMicroWatts() // // /******************************************************************************************************************* +** Method reset resets the INA226 using the first bit in the configuration register ** +*******************************************************************************************************************/ +void INA226_Class::reset(const uint8_t deviceNumber) { // Reset the INA226 // + inaDet ina; // Hold device details in structure // + int16_t configRegister; // Hold configuration register // + for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // + if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + EEPROM.get(i*sizeof(ina),ina); // Read EEPROM values // + writeWord(INA_CONFIGURATION_REGISTER,0x8000,ina.address); // Set most significant bit // + delay(I2C_DELAY); // Let the INA226 reboot // + } // of if this device needs to be set // // + } // for-next each device loop // // +} // of method reset // // +/******************************************************************************************************************* +** Method setMode allows the various mode combinations to be set. If no parameter is given the system goes back ** +** to the default startup mode. ** +*******************************************************************************************************************/ +void INA226_Class::setMode(const uint8_t mode,const uint8_t deviceNumber ) { // Set the monitoring mode // + inaDet ina; // Hold device details in structure // + int16_t configRegister; // Hold configuration register // + for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // + if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + EEPROM.get(i*sizeof(ina),ina); // Read EEPROM values // + configRegister = readWord(INA_CONFIGURATION_REGISTER,ina.address); // Get the current register // + configRegister &= ~INA_CONFIG_MODE_MASK; // zero out the mode bits // + ina.operatingMode = B00001111 & mode; // Mask off unused bits // + EEPROM.put((deviceNumber%INA_MAX_DEVICES)*sizeof(ina),ina); // Write new EEPROM values // + configRegister |= ina.operatingMode; // shift in the mode settings // + writeWord(INA_CONFIGURATION_REGISTER,configRegister,ina.address); // Save new value // + } // of if this device needs to be set // // + } // for-next each device loop // // +} // of method setMode() // // +/******************************************************************************************************************* ** Method setAveraging sets the hardware averaging for the different devices ** *******************************************************************************************************************/ -void INA226_Class::setAveraging(const uint16_t averages ) { // Set the number of averages taken // +void INA226_Class::setAveraging(const uint16_t averages, // Set the number of averages taken // + const uint8_t deviceNumber ) { // // uint8_t averageIndex; // Store indexed value for register // - int16_t configRegister = readWord(INA_CONFIGURATION_REGISTER); // Get the current register // - if (averages>=1024) averageIndex = 7; // setting depending upon range // - else if (averages>= 512) averageIndex = 6; // // - else if (averages>= 256) averageIndex = 5; // // - else if (averages>= 128) averageIndex = 4; // // - else if (averages>= 64) averageIndex = 3; // // - else if (averages>= 16) averageIndex = 2; // // - else if (averages>= 4) averageIndex = 1; // // - else averageIndex = 0; // // - configRegister &= ~INA_CONFIG_AVG_MASK; // zero out the averages part // - configRegister |= (uint16_t)averageIndex << 9; // shift in the averages to register// - writeWord(INA_CONFIGURATION_REGISTER,configRegister); // Save new value // + int16_t configRegister; // Configuration register contents // + inaDet ina; // Hold device details in structure // + for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // + if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + configRegister = readWord(INA_CONFIGURATION_REGISTER,ina.address); // Get the current register // + if (averages>=1024) averageIndex = 7; // setting depending upon range // + else if (averages>= 512) averageIndex = 6; // // + else if (averages>= 256) averageIndex = 5; // // + else if (averages>= 128) averageIndex = 4; // // + else if (averages>= 64) averageIndex = 3; // // + else if (averages>= 16) averageIndex = 2; // // + else if (averages>= 4) averageIndex = 1; // // + else averageIndex = 0; // // + configRegister &= ~INA_CONFIG_AVG_MASK; // zero out the averages part // + configRegister |= (uint16_t)averageIndex << 9; // shift in the averages to register// + writeWord(INA_CONFIGURATION_REGISTER,configRegister,ina.address); // Save new value // + } // of if this device needs to be set // // + } // for-next each device loop // // } // of method setAveraging() // // /******************************************************************************************************************* ** Method setBusConversion specifies the conversion rate (see datasheet for 8 distinct values) for the bus ** *******************************************************************************************************************/ -void INA226_Class::setBusConversion(uint8_t convTime ) { // Set timing for Bus conversions // - if (convTime>7) convTime=7; // Use maximum value allowed // - int16_t configRegister = readWord(INA_CONFIGURATION_REGISTER); // Get the current register // - configRegister &= ~INA_CONFIG_BUS_TIME_MASK; // zero out the Bus conversion part // - configRegister |= (uint16_t)convTime << 6; // shift in the averages to register// - writeWord(INA_CONFIGURATION_REGISTER,configRegister); // Save new value // +void INA226_Class::setBusConversion(uint8_t convTime, // Set timing for Bus conversions // + const uint8_t deviceNumber ) { // // + inaDet ina; // Hold device details in structure // + int16_t configRegister; // Store configuration register // + for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // + if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + if (convTime>7) convTime=7; // Use maximum value allowed // + configRegister = readWord(INA_CONFIGURATION_REGISTER,ina.address); // Get the current register // + configRegister &= ~INA_CONFIG_BUS_TIME_MASK; // zero out the Bus conversion part // + configRegister |= (uint16_t)convTime << 6; // shift in the averages to register// + writeWord(INA_CONFIGURATION_REGISTER,configRegister,ina.address); // Save new value // + } // of if this device needs to be set // // + } // for-next each device loop // // } // of method setBusConversion() // // /******************************************************************************************************************* ** Method setShuntConversion specifies the conversion rate (see datasheet for 8 distinct values) for the shunt ** *******************************************************************************************************************/ -void INA226_Class::setShuntConversion(uint8_t convTime ) { // Set timing for Bus conversions // - if (convTime>7) convTime=7; // Use maximum value allowed // - int16_t configRegister = readWord(INA_CONFIGURATION_REGISTER); // Get the current register // - configRegister &= ~INA_CONFIG_SHUNT_TIME_MASK; // zero out the Bus conversion part // - configRegister |= (uint16_t)convTime << 3; // shift in the averages to register// - writeWord(INA_CONFIGURATION_REGISTER,configRegister); // Save new value // +void INA226_Class::setShuntConversion(uint8_t convTime, // Set timing for Bus conversions // + const uint8_t deviceNumber ) { // // + inaDet ina; // Hold device details in structure // + int16_t configRegister; // Store configuration register // + for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // + if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + if (convTime>7) convTime=7; // Use maximum value allowed // + configRegister = readWord(INA_CONFIGURATION_REGISTER,ina.address); // Get the current register // + configRegister &= ~INA_CONFIG_SHUNT_TIME_MASK; // zero out the Bus conversion part // + configRegister |= (uint16_t)convTime << 3; // shift in the averages to register// + writeWord(INA_CONFIGURATION_REGISTER,configRegister,ina.address); // Save new value // + } // of if this device needs to be set // // + } // for-next each device loop // // } // of method setShuntConversion() // // /******************************************************************************************************************* ** Method waitForConversion loops until the current conversion is marked as finished. If the conversion has ** ** completed already then the flag (and interrupt pin, if activated) is also reset. ** *******************************************************************************************************************/ -void INA226_Class::waitForConversion() { // Wait for current conversion // +void INA226_Class::waitForConversion(const uint8_t deviceNumber) { // Wait for current conversion // uint16_t conversionBits = 0; // // - while(conversionBits==0) { // // - conversionBits = readWord(INA_MASK_ENABLE_REGISTER)&(uint16_t)8; // // - } // of while the conversion hasn't finished // // + inaDet ina; // Hold device details in structure // + for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // + if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + conversionBits = 0; // // + while(conversionBits==0) { // // + conversionBits = readWord(INA_MASK_ENABLE_REGISTER,ina.address) // // + &(uint16_t)8; // // + } // of while the conversion hasn't finished // // + } // of if this device needs to be set // // + } // for-next each device loop // // } // of method waitForConversion() // // /******************************************************************************************************************* ** Method setAlertPinOnConversion configure the INA226 to pull the ALERT pin low when a conversion is complete ** *******************************************************************************************************************/ -void INA226_Class::setAlertPinOnConversion(const bool alertState) { // Enable pin change on conversion // - uint16_t alertRegister = readWord(INA_MASK_ENABLE_REGISTER); // Get the current register // - if (!alertState) alertRegister &= ~((uint16_t)1<<10); // zero out the alert bit // - else alertRegister |= (uint16_t)(1<<10); // turn on the alert bit // - writeWord(INA_MASK_ENABLE_REGISTER,alertRegister); // Write register back to device // +void INA226_Class::setAlertPinOnConversion(const bool alertState, // Enable pin change on conversion // + const uint8_t deviceNumber ) { // // + inaDet ina; // Hold device details in structure // + uint16_t alertRegister; // Hold the alert register // + for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // + if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + alertRegister = readWord(INA_MASK_ENABLE_REGISTER,ina.address); // Get the current register // + if (!alertState) alertRegister &= ~((uint16_t)1<<10); // zero out the alert bit // + else alertRegister |= (uint16_t)(1<<10); // turn on the alert bit // + writeWord(INA_MASK_ENABLE_REGISTER,alertRegister,ina.address); // Write register back to device // + } // of if this device needs to be set // // + } // for-next each device loop // // } // of method setAlertPinOnConversion // // -/******************************************************************************************************************* -** Method reset resets the INA226 using the first bit in the configuration register ** -*******************************************************************************************************************/ -void INA226_Class::reset() { // Reset the INA226 // - writeWord(INA_CONFIGURATION_REGISTER,0x8000); // Set most significant bit // - delay(I2C_DELAY); // Let the INA226 reboot // -} // of method reset // // -/******************************************************************************************************************* -** Method setMode allows the various mode combinations to be set. If no parameter is given the system goes back ** -** to the default startup mode. ** -*******************************************************************************************************************/ -void INA226_Class::setMode(uint8_t mode ) { // Set the monitoring mode // - int16_t configRegister = readWord(INA_CONFIGURATION_REGISTER); // Get the current register // - configRegister &= ~INA_CONFIG_MODE_MASK; // zero out the mode bits // - mode = B00001111 & mode; // Mask off unused bits // - configRegister |= mode; // shift in the mode settings // - writeWord(INA_CONFIGURATION_REGISTER,configRegister); // Save new value // - _OperatingMode = mode; // Save the operating mode // -} // of method setMode() // // \ No newline at end of file diff --git a/INA226.h b/INA226.h index f3a3bd3..2ac1ae3 100644 --- a/INA226.h +++ b/INA226.h @@ -94,22 +94,26 @@ public: // Publicly visible methods // INA226_Class(); // Class constructor // ~INA226_Class(); // Class destructor // - void begin(const uint8_t maxBusAmps, // Class initializer // + uint8_t begin(const uint8_t maxBusAmps, // Class initializer // const uint32_t microOhmR, // // const uint8_t deviceNumber = UINT8_MAX ); // // uint16_t getBusMilliVolts(const bool waitSwitch=false, // Retrieve Bus voltage in mV // const uint8_t deviceNumber=0); // // int16_t getShuntMicroVolts(const bool waitSwitch=false, // Retrieve Shunt voltage in uV // const uint8_t deviceNumber=0); // // - int32_t getBusMicroAmps(); // Retrieve micro-amps // - int32_t getBusMicroWatts(); // Retrieve micro-watts // - void reset(); // Reset the device // - void setMode(uint8_t mode = 7); // Set the monitoring mode // - void setAveraging(const uint16_t averages = UINT16_MAX); // Set the number of averages taken // - void setBusConversion(uint8_t convTime = UINT8_MAX); // Set timing for Bus conversions // - void setShuntConversion(uint8_t convTime = UINT8_MAX); // Set timing for Shunt conversions // - void setAlertPinOnConversion(const bool alertState); // Enable pin change on conversion // - void waitForConversion(); // wait for conversion to complete // + int32_t getBusMicroAmps(const uint8_t deviceNumber=0); // Retrieve micro-amps // + int32_t getBusMicroWatts(const uint8_t deviceNumber=0); // Retrieve micro-watts // + void reset(const uint8_t deviceNumber=0); // Reset the device // + void setMode(const uint8_t mode,const uint8_t devNumber=UINT8_MAX); // Set the monitoring mode // + void setAveraging(const uint16_t averages, // Set the number of averages taken // + const uint8_t deviceNumber=UINT8_MAX); // // + void setBusConversion(uint8_t convTime, // Set timing for Bus conversions // + const uint8_t deviceNumber=UINT8_MAX); // // + void setShuntConversion(uint8_t convTime, // Set timing for Shunt conversions // + const uint8_t deviceNumber=UINT8_MAX); // // + void waitForConversion(const uint8_t deviceNumber=UINT8_MAX); // wait for conversion to complete // + void setAlertPinOnConversion(const bool alertState, // Enable pin change on conversion // + const uint8_t deviceNumber=UINT8_MAX); // // private: // Private variables and methods // uint8_t readByte(const uint8_t addr,const uint8_t deviceAddress=0); // Read a byte from an I2C address // int16_t readWord(const uint8_t addr,const uint8_t deviceAddress=0); // Read a word from an I2C address // @@ -117,12 +121,7 @@ const uint8_t deviceAddress=0); // // void writeWord(const uint8_t addr, const uint16_t data, // Write two bytes to an I2C address// const uint8_t deviceAddress=0); // // - uint8_t _DeviceAddress = 0; // First I2C address found // uint8_t _TransmissionStatus = 0; // Return code for I2C transmission // - uint16_t _Calibration = 0; // Calibration register value // - uint32_t _Current_LSB = 0; // Amperage LSB // - uint32_t _Power_LSB = 0; // Wattage LSB // -// uint8_t _OperatingMode = B111; // Default continuous mode operation// uint8_t _DeviceCount = 0; // Number of INA226s detected // }; // of INA226_Class definition // // #endif //----------------------------------// From 65872cd4f79731fafd96f3d60a1501d15798e437 Mon Sep 17 00:00:00 2001 From: Arnd Date: Sat, 23 Sep 2017 10:02:54 +0200 Subject: [PATCH 6/6] Updated for multiple devices Initial tested code for 1 device with support for multiple devies --- Examples/DisplayReadings/DisplayReadings.ino | 54 +++++++++----- INA226.cpp | 74 +++++++++----------- INA226.h | 11 ++- 3 files changed, 75 insertions(+), 64 deletions(-) diff --git a/Examples/DisplayReadings/DisplayReadings.ino b/Examples/DisplayReadings/DisplayReadings.ino index fe5378a..c9e8178 100644 --- a/Examples/DisplayReadings/DisplayReadings.ino +++ b/Examples/DisplayReadings/DisplayReadings.ino @@ -11,6 +11,13 @@ ** only to convert and display the data conveniently. The INA226 uses 15 bits of precision, and even though the ** ** current and watt information is returned using 32-bit integers the precision remains the same. ** ** ** +** As of version 1.0.3 the library supports multiple INA226 devices. The Atmel's EEPROM is used to store the 96 ** +** bytes of static information per device using https://www.arduino.cc/en/Reference/EEPROM function calls. ** +** Although up to 16 devices could theoretically be present on the I2C bus the actual limit is determined by the ** +** available EEPROM - ATmega328 UNO has 1024k so can support up to 10 devices but the ATmega168 only has 512 bytes** +** which limits it to supporting at most 5 INA226s. The library has been modified to be backwards compatible and ** +** the device number (from 0 to number of devices found) is passed as the last parameter. ** +** ** ** The datasheet for the INA226 can be found at http://www.ti.com/lit/ds/symlink/ina226.pdf and it contains the ** ** information required in order to hook up the device. Unfortunately it comes as a VSSOP package but it can be ** ** soldered onto a breakout board for breadboard use. The INA226 is quite similar to the INA219 mentioned above, ** @@ -27,9 +34,10 @@ ** ** ** Vers. Date Developer Comments ** ** ====== ========== ============================= ============================================================== ** -** 1.0.2 2017-08-09 https://github.com/SV-Zanshin Cosmetic changes ** -** 1.0.1 2017-01-12 https://github.com/SV-Zanshin Minor code cleanup and added more comments ** -** 1.0.0 2017-01-09 https://github.com/SV-Zanshin Cloned example from test program suite ** +** 1.0.3 2017-09-18 https://github.com/SV-Zanshin https://github.com/SV-Zanshin/INA226/issues/6 Multiple INA226s ** +** 1.0.2 2017-08-09 https://github.com/SV-Zanshin Cosmetic changes ** +** 1.0.1 2017-01-12 https://github.com/SV-Zanshin Minor code cleanup and added more comments ** +** 1.0.0 2017-01-09 https://github.com/SV-Zanshin Cloned example from test program suite ** ** ** *******************************************************************************************************************/ #include // INA226 Library // @@ -57,9 +65,10 @@ void setup() { // #ifdef __AVR_ATmega32U4__ // If we are a 32U4 processor, then // delay(2000); // wait 2 seconds for the serial // #endif // interface to initialize // - Serial.print(F("\n\nDisplay INA226 Readings V1.0.1\n")); // Display program information // - // The begin initialized the calibration for an expected ±1 Amps maximum current and for a 0.1Ohm resistor // - devicesFound = INA226.begin(1,100000); // All devices set to same values // + Serial.print(F("\n\nDisplay INA226 Readings V1.0.3\n")); // Display program information // + // The begin initializes the calibration for an expected ±1 Amps maximum current and for a 0.1Ohm resistor, and // + // since no specific device is given as the 3rd parameter all devices are initially set to these values // + devicesFound = INA226.begin(1,100000); // Set expected Amps and resistor // Serial.print(F("Detected ")); // // Serial.print(devicesFound); // // Serial.println(F(" INA226 devices on I2C bus")); // // @@ -73,18 +82,25 @@ void setup() { // ** run in a simple infinite loop ** *******************************************************************************************************************/ void loop() { // Main program loop // - Serial.print(F("Bus voltage: ")); // // - Serial.print((float)INA226.getBusMilliVolts()/1000.0,4); // Convert to millivolts // - Serial.println(F("V")); // // - Serial.print(F("Shunt voltage: ")); // // - Serial.print((float)INA226.getShuntMicroVolts()/1000.0,3); // Convert to millivolts // - Serial.println(F("mV")); // // - Serial.print(F("Bus amperage: ")); // // - Serial.print((float)INA226.getBusMicroAmps()/1000.0,3); // Convert to milliamp // - Serial.println(F("mA")); // // - Serial.print(F("Bus wattage: ")); // // - Serial.print((float)INA226.getBusMicroWatts()/1000.0,3); // Convert to milliwatts // - Serial.println(F("mW")); // // - Serial.println(); // // + for (uint8_t i=0;i // I2C Library definition // #include // Include the EEPROM library // - -/******************************************************************************************************************* -** Class constructor takes no parameters, but searches the I2C bus to see how many of the 16 possible INA226s are ** -** found and allocates sufficient memory to store all data about them. ** -*******************************************************************************************************************/ -INA226_Class::INA226_Class() { // Class constructor // - inaDet ina; // Hold device details in structure // - Wire.begin(); // Start the I2C wire subsystem // - for(uint8_t deviceAddress = 1;deviceAddress<127;deviceAddress++) { // Loop for each possible address // - Wire.beginTransmission(deviceAddress); // See if something is at address // - if (Wire.endTransmission() == 0) { // by checking the return error // - writeWord(INA_CONFIGURATION_REGISTER,INA_RESET_DEVICE); // Force INAs to reset // - delay(I2C_DELAY); // Wait for INA to finish resetting // - if (readWord(INA_CONFIGURATION_REGISTER)==INA_DEFAULT_CONFIGURATION) { // Yes, we've found an INA226! // - ina.address = deviceAddress; // Store device address // - ina.operatingMode = B111; // Default to continuous mode // - if (_DeviceCount*sizeof(ina)=1024) averageIndex = 7; // setting depending upon range // else if (averages>= 512) averageIndex = 6; // // @@ -230,7 +226,7 @@ void INA226_Class::setBusConversion(uint8_t convTime, // inaDet ina; // Hold device details in structure // int16_t configRegister; // Store configuration register // for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // - if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + if(deviceNumber==UINT8_MAX || deviceNumber%_DeviceCount==i ) { // If this device needs setting // if (convTime>7) convTime=7; // Use maximum value allowed // configRegister = readWord(INA_CONFIGURATION_REGISTER,ina.address); // Get the current register // configRegister &= ~INA_CONFIG_BUS_TIME_MASK; // zero out the Bus conversion part // @@ -247,7 +243,7 @@ void INA226_Class::setShuntConversion(uint8_t convTime, // inaDet ina; // Hold device details in structure // int16_t configRegister; // Store configuration register // for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // - if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + if(deviceNumber==UINT8_MAX || deviceNumber%_DeviceCount==i ) { // If this device needs setting // if (convTime>7) convTime=7; // Use maximum value allowed // configRegister = readWord(INA_CONFIGURATION_REGISTER,ina.address); // Get the current register // configRegister &= ~INA_CONFIG_SHUNT_TIME_MASK; // zero out the Bus conversion part // @@ -264,7 +260,7 @@ void INA226_Class::waitForConversion(const uint8_t deviceNumber) { // uint16_t conversionBits = 0; // // inaDet ina; // Hold device details in structure // for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // - if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + if(deviceNumber==UINT8_MAX || deviceNumber%_DeviceCount==i ) { // If this device needs setting // conversionBits = 0; // // while(conversionBits==0) { // // conversionBits = readWord(INA_MASK_ENABLE_REGISTER,ina.address) // // @@ -281,7 +277,7 @@ void INA226_Class::setAlertPinOnConversion(const bool alertState, // inaDet ina; // Hold device details in structure // uint16_t alertRegister; // Hold the alert register // for(uint8_t i=0;i<_DeviceCount;i++) { // Loop for each device found // - if(deviceNumber==UINT8_MAX || deviceNumber%INA_MAX_DEVICES==i ) { // If this device needs setting // + if(deviceNumber==UINT8_MAX || deviceNumber%_DeviceCount==i ) { // If this device needs setting // alertRegister = readWord(INA_MASK_ENABLE_REGISTER,ina.address); // Get the current register // if (!alertState) alertRegister &= ~((uint16_t)1<<10); // zero out the alert bit // else alertRegister |= (uint16_t)(1<<10); // turn on the alert bit // diff --git a/INA226.h b/INA226.h index 2ac1ae3..34ed0c3 100644 --- a/INA226.h +++ b/INA226.h @@ -33,6 +33,7 @@ ** ** ** Vers. Date Developer Comments ** ** ====== ========== ============================= ============================================================== ** +** 1.0.5b 2017-09-23 https://github.com/SV-Zanshin https://github.com/SV-Zanshin/INA226/issues/6. Multiple INA226 ** ** 1.0.5a 2017-09-18 https://github.com/SV-Zanshin https://github.com/SV-Zanshin/INA226/issues/6. Multiple INA226 ** ** 1.0.4 2017-08-13 https://github.com/SV-Zanshin Enhancement #5, removed while() loop after Wire.requestFrom() ** ** 1.0.3 2017-08-09 https://github.com/SV-Zanshin Fix https://github.com/SV-Zanshin/INA226/issues/4. Overflows ** @@ -58,12 +59,10 @@ uint32_t power_LSB; // Wattage LSB // uint8_t operatingMode; // Default continuous mode operation// } inaDet; // of structure // // - /***************************************************************************************************************** ** Declare constants used in the class ** *****************************************************************************************************************/ const uint8_t I2C_DELAY = 10; // Microsecond delay on write // - const uint8_t INA_MAX_DEVICES = 16; // Maximum number of INA226 devices // const uint8_t INA_CONFIGURATION_REGISTER = 0; // Registers common to all INAs // const uint8_t INA_SHUNT_VOLTAGE_REGISTER = 1; // // const uint8_t INA_BUS_VOLTAGE_REGISTER = 2; // // @@ -115,12 +114,12 @@ void setAlertPinOnConversion(const bool alertState, // Enable pin change on conversion // const uint8_t deviceNumber=UINT8_MAX); // // private: // Private variables and methods // - uint8_t readByte(const uint8_t addr,const uint8_t deviceAddress=0); // Read a byte from an I2C address // - int16_t readWord(const uint8_t addr,const uint8_t deviceAddress=0); // Read a word from an I2C address // + uint8_t readByte(const uint8_t addr, const uint8_t deviceAddress); // Read a byte from an I2C address // + int16_t readWord(const uint8_t addr, const uint8_t deviceAddress); // Read a word from an I2C address // void writeByte(const uint8_t addr, const uint8_t data, // Write a byte to an I2C address // - const uint8_t deviceAddress=0); // // + const uint8_t deviceAddress); // // void writeWord(const uint8_t addr, const uint16_t data, // Write two bytes to an I2C address// - const uint8_t deviceAddress=0); // // + const uint8_t deviceAddress); // // uint8_t _TransmissionStatus = 0; // Return code for I2C transmission // uint8_t _DeviceCount = 0; // Number of INA226s detected // }; // of INA226_Class definition // //