From 6f5b35205059e90ee7fa92661b671a1b4e3703fa Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 22 Dec 2024 11:45:00 +1100 Subject: [PATCH] Add INA226 support --- platformio.ini | 3 +- src/Power.cpp | 15 ++++- src/modules/Telemetry/PowerTelemetry.cpp | 6 +- src/modules/Telemetry/Sensor/INA226Sensor.cpp | 58 +++++++++++++++++++ src/modules/Telemetry/Sensor/INA226Sensor.h | 30 ++++++++++ src/power.h | 6 +- 6 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 src/modules/Telemetry/Sensor/INA226Sensor.cpp create mode 100644 src/modules/Telemetry/Sensor/INA226Sensor.h diff --git a/platformio.ini b/platformio.ini index 08d21665f..41f1ca764 100644 --- a/platformio.ini +++ b/platformio.ini @@ -160,4 +160,5 @@ lib_deps = https://github.com/KodinLanewave/INA3221@1.0.1 mprograms/QMC5883LCompass@1.2.3 dfrobot/DFRobot_RTU@1.0.3 - https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d \ No newline at end of file + https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d + robtillaart/INA226@0.6.0 diff --git a/src/Power.cpp b/src/Power.cpp index a4c9ed6f8..ae0908ec6 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -72,8 +72,9 @@ static const uint8_t ext_chrg_detect_value = EXT_CHRG_DETECT_VALUE; #endif #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) -INA260Sensor ina260Sensor; INA219Sensor ina219Sensor; +INA226Sensor ina226Sensor; +INA260Sensor ina260Sensor; INA3221Sensor ina3221Sensor; #endif @@ -463,6 +464,9 @@ class AnalogBatteryLevel : public HasBatteryLevel { if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) { return ina219Sensor.getBusVoltageMv(); + } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA226].first == + config.power.device_battery_ina_address) { + return ina226Sensor.getBusVoltageMv(); } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first == config.power.device_battery_ina_address) { return ina260Sensor.getBusVoltageMv(); @@ -477,6 +481,9 @@ class AnalogBatteryLevel : public HasBatteryLevel { if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) { return ina219Sensor.getCurrentMa(); + } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA226].first == + config.power.device_battery_ina_address) { + return ina226Sensor.getCurrentMa(); } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA3221].first == config.power.device_battery_ina_address) { return ina3221Sensor.getCurrentMa(); @@ -493,6 +500,10 @@ class AnalogBatteryLevel : public HasBatteryLevel if (!ina219Sensor.isInitialized()) return ina219Sensor.runOnce() > 0; return ina219Sensor.isRunning(); + } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA226].first == + config.power.device_battery_ina_address) { + if (!ina226Sensor.isInitialized()) + return ina226Sensor.runOnce() > 0; } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first == config.power.device_battery_ina_address) { if (!ina260Sensor.isInitialized()) @@ -1178,4 +1189,4 @@ bool Power::lipoInit() { return false; } -#endif \ No newline at end of file +#endif diff --git a/src/modules/Telemetry/PowerTelemetry.cpp b/src/modules/Telemetry/PowerTelemetry.cpp index 367643849..10133fca5 100644 --- a/src/modules/Telemetry/PowerTelemetry.cpp +++ b/src/modules/Telemetry/PowerTelemetry.cpp @@ -56,6 +56,8 @@ int32_t PowerTelemetryModule::runOnce() // therefore, we should only enable the sensor loop if measurement is also enabled if (ina219Sensor.hasSensor() && !ina219Sensor.isInitialized()) result = ina219Sensor.runOnce(); + if (ina226Sensor.hasSensor() && !ina226Sensor.isInitialized()) + result = ina226Sensor.runOnce(); if (ina260Sensor.hasSensor() && !ina260Sensor.isInitialized()) result = ina260Sensor.runOnce(); if (ina3221Sensor.hasSensor() && !ina3221Sensor.isInitialized()) @@ -170,6 +172,8 @@ bool PowerTelemetryModule::getPowerTelemetry(meshtastic_Telemetry *m) #if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) if (ina219Sensor.hasSensor()) valid = ina219Sensor.getMetrics(m); + if (ina226Sensor.hasSensor()) + valid = ina226Sensor.getMetrics(m); if (ina260Sensor.hasSensor()) valid = ina260Sensor.getMetrics(m); if (ina3221Sensor.hasSensor()) @@ -253,4 +257,4 @@ bool PowerTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly) return false; } -#endif +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/INA226Sensor.cpp b/src/modules/Telemetry/Sensor/INA226Sensor.cpp new file mode 100644 index 000000000..1ee7cd92e --- /dev/null +++ b/src/modules/Telemetry/Sensor/INA226Sensor.cpp @@ -0,0 +1,58 @@ +#include "configuration.h" + +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "INA226.h" +#include "INA226Sensor.h" +#include "TelemetrySensor.h" + +INA226Sensor::INA226Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_INA226, "INA226") {} + +int32_t INA226Sensor::runOnce() +{ + LOG_INFO("Init sensor: %s", sensorName); + if (!hasSensor()) { + return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; + } + + begin(nodeTelemetrySensorsMap[sensorType].second, nodeTelemetrySensorsMap[sensorType].first); + + if (!status) { + status = ina226.begin(); + } + return initI2CSensor(); +} + +void INA226Sensor::setup() {} + +void INA226Sensor::begin(TwoWire *wire, uint8_t addr) +{ + _wire = wire; + _addr = addr; + ina226 = INA226(_addr, _wire); + _wire->begin(); +} + +bool INA226Sensor::getMetrics(meshtastic_Telemetry *measurement) +{ + measurement->variant.environment_metrics.has_voltage = true; + measurement->variant.environment_metrics.has_current = true; + + // mV conversion to V + measurement->variant.environment_metrics.voltage = ina226.getBusVoltage() / 1000; + measurement->variant.environment_metrics.current = ina226.getCurrent_mA(); + return true; +} + +uint16_t INA226Sensor::getBusVoltageMv() +{ + return lround(ina226.getBusVoltage()); +} + +int16_t INA226Sensor::getCurrentMa() +{ + return lround(ina226.getCurrent_mA()); +} + +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/INA226Sensor.h b/src/modules/Telemetry/Sensor/INA226Sensor.h new file mode 100644 index 000000000..2f71c5b86 --- /dev/null +++ b/src/modules/Telemetry/Sensor/INA226Sensor.h @@ -0,0 +1,30 @@ +#include "configuration.h" + +#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "CurrentSensor.h" +#include "TelemetrySensor.h" +#include "VoltageSensor.h" +#include + +class INA226Sensor : public TelemetrySensor, VoltageSensor, CurrentSensor +{ + private: + uint8_t _addr = INA_ADDR; + TwoWire *_wire = &Wire; + INA226 ina226 = INA226(_addr, _wire); + + protected: + virtual void setup() override; + void begin(TwoWire *wire = &Wire, uint8_t addr = INA_ADDR); + + public: + INA226Sensor(); + virtual int32_t runOnce() override; + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; + virtual uint16_t getBusVoltageMv() override; + virtual int16_t getCurrentMa() override; +}; + +#endif \ No newline at end of file diff --git a/src/power.h b/src/power.h index 63335104b..ab55fc7e1 100644 --- a/src/power.h +++ b/src/power.h @@ -42,10 +42,12 @@ extern RTC_NOINIT_ATTR uint64_t RTC_reg_b; #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) #include "modules/Telemetry/Sensor/INA219Sensor.h" +#include "modules/Telemetry/Sensor/INA226Sensor.h" #include "modules/Telemetry/Sensor/INA260Sensor.h" #include "modules/Telemetry/Sensor/INA3221Sensor.h" -extern INA260Sensor ina260Sensor; extern INA219Sensor ina219Sensor; +extern INA226Sensor ina226Sensor; +extern INA260Sensor ina260Sensor; extern INA3221Sensor ina3221Sensor; #endif @@ -99,4 +101,4 @@ class Power : private concurrency::OSThread #endif }; -extern Power *power; \ No newline at end of file +extern Power *power;