#ifndef SENS_INA_219 #define SENS_INA_219 /** 1-Channel i2c volt/ampere sensor */ template class INA219 { private: I2C& i2c; static constexpr const uint8_t ADDR = 0b1000000; static constexpr const char* NAME = "INA219"; static constexpr const uint8_t REG_CFG = 0x00; static constexpr const uint8_t REG_VS = 0x01; // shunt voltage static constexpr const uint8_t REG_VB = 0x02; // bus voltage public: struct Voltages { int vShunt; // in uV * 10(!!!) int16_t vBus; // in mV int getMilliAmps(int shunt_milliOhm) const { return (vShunt * 10) / shunt_milliOhm; } }; public: INA219(I2C& i2c) : i2c(i2c) { } /** get the current config */ uint16_t getConfig() { uint8_t buf[2]; i2c.readReg(ADDR, REG_CFG, 2, (uint8_t*)&buf); return getU16(buf); } /** read both voltages (shunt and bus) */ Voltages getVoltages() { uint8_t buf[2]; Voltages res; i2c.readReg(ADDR, REG_VS, sizeof(buf), buf); res.vShunt = getShuntVoltage(buf); i2c.readReg(ADDR, REG_VB, sizeof(buf), buf); res.vBus = getBusVoltage(buf); return res; } /** is an INA219 present on the bus? */ bool isPresent() { return i2c.query(ADDR); } void dumpConfig() { const uint16_t cfg = getConfig(); const uint8_t mode = (cfg & 0b00000000000111) >> 0; const uint8_t sadc = (cfg & 0b00000001111000) >> 3; const uint8_t badc = (cfg & 0b00011110000000) >> 7; const uint8_t pg = (cfg & 0b01100000000000) >> 11; const uint8_t brng = (cfg & 0b10000000000000) >> 13; printf("INA219\n"); printf("- Mode: %d", mode); printf("- SADC: %d", sadc); printf("- BADC: %d", badc); printf("PG (shunt divider) %d", (1<> 3) * 4; // lower 3 bits are status indicators -> remove, the LSB equals 4 mV -> * 4 } /** convert to bytes into a uV reading */ int getShuntVoltage(const uint8_t* buf) { return ((int)((int16_t)getU16(buf))); // NOTE: LSB = 10 uV } uint16_t getU16(const uint8_t* buf) { return ((buf[0] << 8) | (buf[1] << 0)); } }; #endif // SENS_INA_219