mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-24 09:26:52 +00:00
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
This commit is contained in:
parent
344baf7ffc
commit
cd787232ca
@ -37,12 +37,18 @@ static const adc_atten_t atten = ADC_ATTENUATION;
|
|||||||
#endif
|
#endif
|
||||||
#endif // BATTERY_PIN && ARCH_ESP32
|
#endif // BATTERY_PIN && ARCH_ESP32
|
||||||
|
|
||||||
|
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
|
||||||
|
INA260Sensor ina260Sensor;
|
||||||
|
INA219Sensor ina219Sensor;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_PMU
|
#ifdef HAS_PMU
|
||||||
#include "XPowersAXP192.tpp"
|
#include "XPowersAXP192.tpp"
|
||||||
#include "XPowersAXP2101.tpp"
|
#include "XPowersAXP2101.tpp"
|
||||||
#include "XPowersLibInterface.hpp"
|
#include "XPowersLibInterface.hpp"
|
||||||
XPowersLibInterface *PMU = NULL;
|
XPowersLibInterface *PMU = NULL;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Copy of the base class defined in axp20x.h.
|
// Copy of the base class defined in axp20x.h.
|
||||||
// I'd rather not inlude axp20x.h as it brings Wire dependency.
|
// I'd rather not inlude axp20x.h as it brings Wire dependency.
|
||||||
class HasBatteryLevel
|
class HasBatteryLevel
|
||||||
@ -128,6 +134,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
virtual uint16_t getBattVoltage() override
|
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
|
#ifndef ADC_MULTIPLIER
|
||||||
#define ADC_MULTIPLIER 2.0
|
#define ADC_MULTIPLIER 2.0
|
||||||
#endif
|
#endif
|
||||||
@ -246,6 +259,35 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
const float fullVolt = BAT_FULLVOLT, emptyVolt = BAT_EMPTYVOLT, chargingVolt = BAT_CHARGINGVOLT, noBatVolt = BAT_NOBATVOLT;
|
const float fullVolt = BAT_FULLVOLT, emptyVolt = BAT_EMPTYVOLT, chargingVolt = BAT_CHARGINGVOLT, noBatVolt = BAT_NOBATVOLT;
|
||||||
float last_read_value = 0.0;
|
float last_read_value = 0.0;
|
||||||
uint32_t last_read_time_ms = 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;
|
AnalogBatteryLevel analogLevel;
|
||||||
@ -639,7 +681,6 @@ bool Power::axpChipInit()
|
|||||||
// GNSS VDD 3300mV
|
// GNSS VDD 3300mV
|
||||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
|
||||||
PMU->enablePowerOutput(XPOWERS_ALDO3);
|
PMU->enablePowerOutput(XPOWERS_ALDO3);
|
||||||
|
|
||||||
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
|
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
|
||||||
// t-beam s3 core
|
// t-beam s3 core
|
||||||
/**
|
/**
|
||||||
|
@ -38,8 +38,6 @@ extern bool isUSBPowered;
|
|||||||
extern ATECCX08A atecc;
|
extern ATECCX08A atecc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern uint8_t nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
|
|
||||||
|
|
||||||
extern int TCPPort; // set by Portduino
|
extern int TCPPort; // set by Portduino
|
||||||
|
|
||||||
// Global Screen singleton.
|
// Global Screen singleton.
|
||||||
@ -69,4 +67,4 @@ void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), clearBonds();
|
|||||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||||
|
|
||||||
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
|
// 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;
|
@ -7,6 +7,7 @@
|
|||||||
#include "Router.h"
|
#include "Router.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "power.h"
|
||||||
#include <OLEDDisplay.h>
|
#include <OLEDDisplay.h>
|
||||||
#include <OLEDDisplayUi.h>
|
#include <OLEDDisplayUi.h>
|
||||||
|
|
||||||
@ -14,8 +15,6 @@
|
|||||||
#include "Sensor/BME280Sensor.h"
|
#include "Sensor/BME280Sensor.h"
|
||||||
#include "Sensor/BME680Sensor.h"
|
#include "Sensor/BME680Sensor.h"
|
||||||
#include "Sensor/BMP280Sensor.h"
|
#include "Sensor/BMP280Sensor.h"
|
||||||
#include "Sensor/INA219Sensor.h"
|
|
||||||
#include "Sensor/INA260Sensor.h"
|
|
||||||
#include "Sensor/LPS22HBSensor.h"
|
#include "Sensor/LPS22HBSensor.h"
|
||||||
#include "Sensor/MCP9808Sensor.h"
|
#include "Sensor/MCP9808Sensor.h"
|
||||||
#include "Sensor/SHT31Sensor.h"
|
#include "Sensor/SHT31Sensor.h"
|
||||||
@ -25,8 +24,6 @@ BMP280Sensor bmp280Sensor;
|
|||||||
BME280Sensor bme280Sensor;
|
BME280Sensor bme280Sensor;
|
||||||
BME680Sensor bme680Sensor;
|
BME680Sensor bme680Sensor;
|
||||||
MCP9808Sensor mcp9808Sensor;
|
MCP9808Sensor mcp9808Sensor;
|
||||||
INA260Sensor ina260Sensor;
|
|
||||||
INA219Sensor ina219Sensor;
|
|
||||||
SHTC3Sensor shtc3Sensor;
|
SHTC3Sensor shtc3Sensor;
|
||||||
LPS22HBSensor lps22hbSensor;
|
LPS22HBSensor lps22hbSensor;
|
||||||
SHT31Sensor sht31Sensor;
|
SHT31Sensor sht31Sensor;
|
||||||
@ -83,15 +80,10 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
|||||||
result = bme680Sensor.runOnce();
|
result = bme680Sensor.runOnce();
|
||||||
if (mcp9808Sensor.hasSensor())
|
if (mcp9808Sensor.hasSensor())
|
||||||
result = mcp9808Sensor.runOnce();
|
result = mcp9808Sensor.runOnce();
|
||||||
if (ina260Sensor.hasSensor())
|
|
||||||
result = ina260Sensor.runOnce();
|
|
||||||
if (ina219Sensor.hasSensor())
|
|
||||||
result = ina219Sensor.runOnce();
|
|
||||||
if (shtc3Sensor.hasSensor())
|
if (shtc3Sensor.hasSensor())
|
||||||
result = shtc3Sensor.runOnce();
|
result = shtc3Sensor.runOnce();
|
||||||
if (lps22hbSensor.hasSensor()) {
|
if (lps22hbSensor.hasSensor())
|
||||||
result = lps22hbSensor.runOnce();
|
result = lps22hbSensor.runOnce();
|
||||||
}
|
|
||||||
if (sht31Sensor.hasSensor())
|
if (sht31Sensor.hasSensor())
|
||||||
result = sht31Sensor.runOnce();
|
result = sht31Sensor.runOnce();
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,12 @@ int32_t INA219Sensor::runOnce()
|
|||||||
if (!hasSensor()) {
|
if (!hasSensor()) {
|
||||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||||
}
|
}
|
||||||
ina219 = Adafruit_INA219(nodeTelemetrySensorsMap[sensorType]);
|
if (!ina219.success()) {
|
||||||
status = ina219.begin();
|
ina219 = Adafruit_INA219(nodeTelemetrySensorsMap[sensorType]);
|
||||||
|
status = ina219.begin();
|
||||||
|
} else {
|
||||||
|
status = ina219.success();
|
||||||
|
}
|
||||||
return initI2CSensor();
|
return initI2CSensor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,4 +28,9 @@ bool INA219Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
|||||||
measurement->variant.environment_metrics.voltage = ina219.getBusVoltage_V();
|
measurement->variant.environment_metrics.voltage = ina219.getBusVoltage_V();
|
||||||
measurement->variant.environment_metrics.current = ina219.getCurrent_mA();
|
measurement->variant.environment_metrics.current = ina219.getCurrent_mA();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t INA219Sensor::getBusVoltageMv()
|
||||||
|
{
|
||||||
|
return lround(ina219.getBusVoltage_V() * 1000);
|
||||||
}
|
}
|
@ -1,8 +1,9 @@
|
|||||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
#include "TelemetrySensor.h"
|
#include "TelemetrySensor.h"
|
||||||
|
#include "VoltageSensor.h"
|
||||||
#include <Adafruit_INA219.h>
|
#include <Adafruit_INA219.h>
|
||||||
|
|
||||||
class INA219Sensor : virtual public TelemetrySensor
|
class INA219Sensor : virtual public TelemetrySensor, VoltageSensor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Adafruit_INA219 ina219;
|
Adafruit_INA219 ina219;
|
||||||
@ -14,4 +15,5 @@ class INA219Sensor : virtual public TelemetrySensor
|
|||||||
INA219Sensor();
|
INA219Sensor();
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||||
|
virtual uint16_t getBusVoltageMv() override;
|
||||||
};
|
};
|
@ -12,7 +12,10 @@ int32_t INA260Sensor::runOnce()
|
|||||||
if (!hasSensor()) {
|
if (!hasSensor()) {
|
||||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||||
}
|
}
|
||||||
status = ina260.begin(nodeTelemetrySensorsMap[sensorType]);
|
|
||||||
|
if (!status) {
|
||||||
|
status = ina260.begin(nodeTelemetrySensorsMap[sensorType]);
|
||||||
|
}
|
||||||
return initI2CSensor();
|
return initI2CSensor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,4 +27,9 @@ bool INA260Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
|||||||
measurement->variant.environment_metrics.voltage = ina260.readBusVoltage() / 1000;
|
measurement->variant.environment_metrics.voltage = ina260.readBusVoltage() / 1000;
|
||||||
measurement->variant.environment_metrics.current = ina260.readCurrent();
|
measurement->variant.environment_metrics.current = ina260.readCurrent();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t INA260Sensor::getBusVoltageMv()
|
||||||
|
{
|
||||||
|
return lround(ina260.readBusVoltage());
|
||||||
}
|
}
|
@ -1,8 +1,9 @@
|
|||||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
#include "TelemetrySensor.h"
|
#include "TelemetrySensor.h"
|
||||||
|
#include "VoltageSensor.h"
|
||||||
#include <Adafruit_INA260.h>
|
#include <Adafruit_INA260.h>
|
||||||
|
|
||||||
class INA260Sensor : virtual public TelemetrySensor
|
class INA260Sensor : virtual public TelemetrySensor, VoltageSensor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Adafruit_INA260 ina260 = Adafruit_INA260();
|
Adafruit_INA260 ina260 = Adafruit_INA260();
|
||||||
@ -14,4 +15,5 @@ class INA260Sensor : virtual public TelemetrySensor
|
|||||||
INA260Sensor();
|
INA260Sensor();
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||||
|
virtual uint16_t getBusVoltageMv() override;
|
||||||
};
|
};
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
#define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
#define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
||||||
|
extern uint8_t nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
|
||||||
|
|
||||||
class TelemetrySensor
|
class TelemetrySensor
|
||||||
{
|
{
|
||||||
@ -18,6 +18,7 @@ class TelemetrySensor
|
|||||||
const char *sensorName;
|
const char *sensorName;
|
||||||
meshtastic_TelemetrySensorType sensorType;
|
meshtastic_TelemetrySensorType sensorType;
|
||||||
unsigned status;
|
unsigned status;
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
int32_t initI2CSensor()
|
int32_t initI2CSensor()
|
||||||
{
|
{
|
||||||
@ -28,6 +29,7 @@ class TelemetrySensor
|
|||||||
LOG_INFO("Opened %s sensor on default i2c bus\n", sensorName);
|
LOG_INFO("Opened %s sensor on default i2c bus\n", sensorName);
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
|
initialized = true;
|
||||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||||
}
|
}
|
||||||
virtual void setup();
|
virtual void setup();
|
||||||
@ -36,5 +38,8 @@ class TelemetrySensor
|
|||||||
bool hasSensor() { return sensorType < sizeof(nodeTelemetrySensorsMap) && nodeTelemetrySensorsMap[sensorType] > 0; }
|
bool hasSensor() { return sensorType < sizeof(nodeTelemetrySensorsMap) && nodeTelemetrySensorsMap[sensorType] > 0; }
|
||||||
|
|
||||||
virtual int32_t runOnce() = 0;
|
virtual int32_t runOnce() = 0;
|
||||||
|
virtual bool isInitialized() { return initialized; }
|
||||||
|
virtual bool isRunning() { return status > 0; }
|
||||||
|
|
||||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) = 0;
|
virtual bool getMetrics(meshtastic_Telemetry *measurement) = 0;
|
||||||
};
|
};
|
7
src/modules/Telemetry/Sensor/VoltageSensor.h
Normal file
7
src/modules/Telemetry/Sensor/VoltageSensor.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class VoltageSensor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual uint16_t getBusVoltageMv() = 0;
|
||||||
|
};
|
@ -22,6 +22,13 @@ extern RTC_NOINIT_ATTR uint64_t RTC_reg_b;
|
|||||||
#include "soc/sens_reg.h" // needed for adc pin reset
|
#include "soc/sens_reg.h" // needed for adc pin reset
|
||||||
#endif
|
#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
|
class Power : private concurrency::OSThread
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -41,7 +48,6 @@ class Power : private concurrency::OSThread
|
|||||||
|
|
||||||
/// Setup a xpowers chip axp192/axp2101, return true if found
|
/// Setup a xpowers chip axp192/axp2101, return true if found
|
||||||
bool axpChipInit();
|
bool axpChipInit();
|
||||||
|
|
||||||
/// Setup a simple ADC input based battery sensor
|
/// Setup a simple ADC input based battery sensor
|
||||||
bool analogInit();
|
bool analogInit();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user