Files
OpenMQTT-Gateway/main/sensorINA226.cpp
Zhaoqi Xu 60aa84841d [INA226] Read the shunt voltage as a signed value (#2410)
The shunt voltage register is a 16-bit two's complement value. The
old conversion tested `shuntvolt && 0x8000` (always true for a
non-zero reading) and then negated the complement of the zero-extended
value, which gives back the raw register value. Positive readings came
out right by accident, but a reverse current was published as a large
positive current (0xFFF0 -> 1.638 A instead of -0.4 mA with the
default 0.1 ohm shunt).

Cast the register to int16_t instead.

Fixes #2395

Signed-off-by: Zhaoqi Xu <lzy00419@outlook.com>
2026-10-15 05:20:38 -05:00

104 lines
3.5 KiB
C++

/*
Theengs OpenMQTTGateway - We Unite Sensors in One Open-Source Interface
Act as a gateway between your 433mhz, infrared IR, BLE, LoRa signal and one interface like an MQTT broker
Send and receiving command by MQTT
INA226 reading Addon
From the orgiginal work of Matthias Busse http://shelvin.de/ein-batteriemonitor-fuer-strom-und-spannung-mit-dem-ina226-und-dem-arduino-uno/
MQTT add - 1technophile
Contributors:
- 1technophile
This file is part of OpenMQTTGateway.
OpenMQTTGateway is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenMQTTGateway is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Pinout
// INA226 - Uno - Mega - NODEMCU
// SCL - A5 - 21 - D1
// SDA - A4 - 20 - D2
//
#include "User_config.h"
#ifdef ZsensorINA226
# include <Wire.h>
# include "TheengsCommon.h"
# include "config_INA226.h"
static void writeRegister(byte reg, word value);
static word readRegister(byte reg);
float rShunt = 0.1; // Shunt Widerstand festlegen, hier 0.1 Ohm
const int INA226_ADDR = 0x40; // A0 und A1 auf GND > Adresse 40 Hex auf Seite 18 im Datenblatt
//Time used to wait for an interval before resending temp and hum
unsigned long timeINA226 = 0;
void setupINA226() {
Wire.begin();
// Configuration Register Standard Einstellung 0x4127, hier aber 16 Werte Mitteln > 0x4427
writeRegister(0x00, 0x4427); // 1.1ms Volt und Strom A/D-Wandlung, Shunt und VBus continous
}
void MeasureINA226() {
if (millis() > (timeINA226 + TimeBetweenReadingINA226)) { //retrieving value of temperature and humidity of the box from DHT every xUL
timeINA226 = millis();
THEENGS_LOG_TRACE(F("Creating INA226 buffer" CR));
StaticJsonDocument<JSON_MSG_BUFFER> INA226dataBuffer;
JsonObject INA226data = INA226dataBuffer.to<JsonObject>();
// Topic on which we will send data
THEENGS_LOG_TRACE(F("Retrieving electrical data" CR));
// Bus Spannung, read-only, 16Bit, 0...40.96V max., LSB 1.25mV
float volt = readRegister(0x02) * 0.00125;
// Seite 24: Shunt Spannung +- 81,92mV mit 16 Bit, LSB 2,5uV
// The register holds a signed two's complement value, so a reverse current reads as negative
int16_t shuntvolt = (int16_t)readRegister(0x01);
float current = shuntvolt * 0.0000025 / rShunt; // * LSB / R
float power = abs(volt * current);
INA226data["volt"] = volt;
INA226data["current"] = current;
INA226data["power"] = power;
INA226data["origin"] = subjectINA226toMQTT;
enqueueJsonObject(INA226data);
}
}
void writeRegister(byte reg, word value) {
Wire.beginTransmission(INA226_ADDR);
Wire.write(reg);
Wire.write((value >> 8) & 0xFF);
Wire.write(value & 0xFF);
Wire.endTransmission();
}
word readRegister(byte reg) {
word res = 0x0000;
Wire.beginTransmission(INA226_ADDR);
Wire.write(reg);
if (Wire.endTransmission() == 0) {
if (Wire.requestFrom(INA226_ADDR, 2) >= 2) {
res = Wire.read() * 256;
res += Wire.read();
}
}
return res;
}
#endif