Use INA for device battery level (#2536)

* WIP

* Continued wip

* We got em

* Voltage sensor base class

* INA voltage

* Log it

* Stacie's mom has got it going on

* Move declaration up

* Last one

* Sneaky little bugger

* Macro guard to avoid calling methods
pull/2540/head v2.1.15.cd78723
Ben Meadors 2023-06-02 06:32:34 -05:00 zatwierdzone przez GitHub
rodzic 344baf7ffc
commit cd787232ca
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
10 zmienionych plików z 92 dodań i 22 usunięć

Wyświetl plik

@ -37,12 +37,18 @@ static const adc_atten_t atten = ADC_ATTENUATION;
#endif
#endif // BATTERY_PIN && ARCH_ESP32
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor;
#endif
#ifdef HAS_PMU
#include "XPowersAXP192.tpp"
#include "XPowersAXP2101.tpp"
#include "XPowersLibInterface.hpp"
XPowersLibInterface *PMU = NULL;
#else
// Copy of the base class defined in axp20x.h.
// I'd rather not inlude axp20x.h as it brings Wire dependency.
class HasBatteryLevel
@ -128,6 +134,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual uint16_t getBattVoltage() override
{
#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
if (hasINA()) {
LOG_DEBUG("Using INA on I2C addr 0x%x for device battery voltage\n", config.power.device_battery_ina_address);
return getINAVoltage();
}
#endif
#ifndef ADC_MULTIPLIER
#define ADC_MULTIPLIER 2.0
#endif
@ -246,6 +259,35 @@ class AnalogBatteryLevel : public HasBatteryLevel
const float fullVolt = BAT_FULLVOLT, emptyVolt = BAT_EMPTYVOLT, chargingVolt = BAT_CHARGINGVOLT, noBatVolt = BAT_NOBATVOLT;
float last_read_value = 0.0;
uint32_t last_read_time_ms = 0;
#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO)
uint16_t getINAVoltage()
{
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) {
return ina219Sensor.getBusVoltageMv();
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) {
return ina260Sensor.getBusVoltageMv();
}
return 0;
}
bool hasINA()
{
if (!config.power.device_battery_ina_address) {
return false;
}
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) {
if (!ina219Sensor.isInitialized())
return ina219Sensor.runOnce() > 0;
return ina219Sensor.isRunning();
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) {
if (!ina260Sensor.isInitialized())
return ina260Sensor.runOnce() > 0;
return ina260Sensor.isRunning();
}
return false;
}
#endif
};
AnalogBatteryLevel analogLevel;
@ -639,7 +681,6 @@ bool Power::axpChipInit()
// GNSS VDD 3300mV
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3);
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
// t-beam s3 core
/**

Wyświetl plik

@ -38,8 +38,6 @@ extern bool isUSBPowered;
extern ATECCX08A atecc;
#endif
extern uint8_t nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
extern int TCPPort; // set by Portduino
// Global Screen singleton.
@ -69,4 +67,4 @@ void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), clearBonds();
meshtastic_DeviceMetadata getDeviceMetadata();
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
extern SPISettings spiSettings;
extern SPISettings spiSettings;

Wyświetl plik

@ -7,6 +7,7 @@
#include "Router.h"
#include "configuration.h"
#include "main.h"
#include "power.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
@ -14,8 +15,6 @@
#include "Sensor/BME280Sensor.h"
#include "Sensor/BME680Sensor.h"
#include "Sensor/BMP280Sensor.h"
#include "Sensor/INA219Sensor.h"
#include "Sensor/INA260Sensor.h"
#include "Sensor/LPS22HBSensor.h"
#include "Sensor/MCP9808Sensor.h"
#include "Sensor/SHT31Sensor.h"
@ -25,8 +24,6 @@ BMP280Sensor bmp280Sensor;
BME280Sensor bme280Sensor;
BME680Sensor bme680Sensor;
MCP9808Sensor mcp9808Sensor;
INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor;
SHTC3Sensor shtc3Sensor;
LPS22HBSensor lps22hbSensor;
SHT31Sensor sht31Sensor;
@ -83,15 +80,10 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = bme680Sensor.runOnce();
if (mcp9808Sensor.hasSensor())
result = mcp9808Sensor.runOnce();
if (ina260Sensor.hasSensor())
result = ina260Sensor.runOnce();
if (ina219Sensor.hasSensor())
result = ina219Sensor.runOnce();
if (shtc3Sensor.hasSensor())
result = shtc3Sensor.runOnce();
if (lps22hbSensor.hasSensor()) {
if (lps22hbSensor.hasSensor())
result = lps22hbSensor.runOnce();
}
if (sht31Sensor.hasSensor())
result = sht31Sensor.runOnce();
}

Wyświetl plik

@ -12,8 +12,12 @@ int32_t INA219Sensor::runOnce()
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
ina219 = Adafruit_INA219(nodeTelemetrySensorsMap[sensorType]);
status = ina219.begin();
if (!ina219.success()) {
ina219 = Adafruit_INA219(nodeTelemetrySensorsMap[sensorType]);
status = ina219.begin();
} else {
status = ina219.success();
}
return initI2CSensor();
}
@ -24,4 +28,9 @@ bool INA219Sensor::getMetrics(meshtastic_Telemetry *measurement)
measurement->variant.environment_metrics.voltage = ina219.getBusVoltage_V();
measurement->variant.environment_metrics.current = ina219.getCurrent_mA();
return true;
}
uint16_t INA219Sensor::getBusVoltageMv()
{
return lround(ina219.getBusVoltage_V() * 1000);
}

Wyświetl plik

@ -1,8 +1,9 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include "VoltageSensor.h"
#include <Adafruit_INA219.h>
class INA219Sensor : virtual public TelemetrySensor
class INA219Sensor : virtual public TelemetrySensor, VoltageSensor
{
private:
Adafruit_INA219 ina219;
@ -14,4 +15,5 @@ class INA219Sensor : virtual public TelemetrySensor
INA219Sensor();
virtual int32_t runOnce() override;
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
virtual uint16_t getBusVoltageMv() override;
};

Wyświetl plik

@ -12,7 +12,10 @@ int32_t INA260Sensor::runOnce()
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = ina260.begin(nodeTelemetrySensorsMap[sensorType]);
if (!status) {
status = ina260.begin(nodeTelemetrySensorsMap[sensorType]);
}
return initI2CSensor();
}
@ -24,4 +27,9 @@ bool INA260Sensor::getMetrics(meshtastic_Telemetry *measurement)
measurement->variant.environment_metrics.voltage = ina260.readBusVoltage() / 1000;
measurement->variant.environment_metrics.current = ina260.readCurrent();
return true;
}
uint16_t INA260Sensor::getBusVoltageMv()
{
return lround(ina260.readBusVoltage());
}

Wyświetl plik

@ -1,8 +1,9 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include "VoltageSensor.h"
#include <Adafruit_INA260.h>
class INA260Sensor : virtual public TelemetrySensor
class INA260Sensor : virtual public TelemetrySensor, VoltageSensor
{
private:
Adafruit_INA260 ina260 = Adafruit_INA260();
@ -14,4 +15,5 @@ class INA260Sensor : virtual public TelemetrySensor
INA260Sensor();
virtual int32_t runOnce() override;
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
virtual uint16_t getBusVoltageMv() override;
};

Wyświetl plik

@ -1,9 +1,9 @@
#pragma once
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "NodeDB.h"
#include "main.h"
#define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
extern uint8_t nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
class TelemetrySensor
{
@ -18,6 +18,7 @@ class TelemetrySensor
const char *sensorName;
meshtastic_TelemetrySensorType sensorType;
unsigned status;
bool initialized = false;
int32_t initI2CSensor()
{
@ -28,6 +29,7 @@ class TelemetrySensor
LOG_INFO("Opened %s sensor on default i2c bus\n", sensorName);
setup();
}
initialized = true;
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
virtual void setup();
@ -36,5 +38,8 @@ class TelemetrySensor
bool hasSensor() { return sensorType < sizeof(nodeTelemetrySensorsMap) && nodeTelemetrySensorsMap[sensorType] > 0; }
virtual int32_t runOnce() = 0;
virtual bool isInitialized() { return initialized; }
virtual bool isRunning() { return status > 0; }
virtual bool getMetrics(meshtastic_Telemetry *measurement) = 0;
};
};

Wyświetl plik

@ -0,0 +1,7 @@
#pragma once
class VoltageSensor
{
public:
virtual uint16_t getBusVoltageMv() = 0;
};

Wyświetl plik

@ -22,6 +22,13 @@ extern RTC_NOINIT_ATTR uint64_t RTC_reg_b;
#include "soc/sens_reg.h" // needed for adc pin reset
#endif
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
#include "modules/Telemetry/Sensor/INA219Sensor.h"
#include "modules/Telemetry/Sensor/INA260Sensor.h"
extern INA260Sensor ina260Sensor;
extern INA219Sensor ina219Sensor;
#endif
class Power : private concurrency::OSThread
{
@ -41,7 +48,6 @@ class Power : private concurrency::OSThread
/// Setup a xpowers chip axp192/axp2101, return true if found
bool axpChipInit();
/// Setup a simple ADC input based battery sensor
bool analogInit();