Compare commits

...

9 Commits

Author SHA1 Message Date
Winston Lowe
d0986e7c98
Merge 8d52bc413b into ba296db701 2025-06-06 07:13:22 -04:00
Winston Lowe
8d52bc413b
Merge branch 'master' into dev-ina-sensor-fix 2025-06-04 21:06:03 -07:00
Ben Meadors
2082a87771
Merge branch 'master' into dev-ina-sensor-fix 2025-06-02 06:31:43 -05:00
Ben Meadors
983dd95091
Update variants/rp2040-lora/variant.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-02 06:31:26 -05:00
Ben Meadors
7f49c6d2bc
Merge branch 'master' into dev-ina-sensor-fix 2025-06-02 06:17:57 -05:00
Winston Lowe
2388960fb2
Merge branch 'master' into dev-ina-sensor-fix 2025-06-01 23:20:33 -07:00
Winston Lowe
5271582062 Added defines in verient for battery-related
setting for using rp2040-lora with INA voltage sensors.
2025-06-02 01:31:15 +00:00
Winston Lowe
e0a697feb6 For i2c INA sensors I had to move the power initialization after i2c 2025-06-02 01:27:33 +00:00
Winston Lowe
1526781b83 Added proper support for INA sensors in Power class. Added define HAS_BATTERY to enablesbattery-related code. 2025-06-02 01:13:55 +00:00
7 changed files with 60 additions and 22 deletions

View File

@ -214,13 +214,29 @@ static void adcDisable()
#endif #endif
} }
#endif #endif //BATTERY_PIN
/** /**
* A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input * A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input
*/ */
class AnalogBatteryLevel : public HasBatteryLevel class AnalogBatteryLevel : public HasBatteryLevel
{ {
private:
/// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power
/// For heltecs with no battery connected, the measured voltage is 2204, so
// need to be higher than that, in this case is 2500mV (3000-500)
const uint16_t OCV[NUM_OCV_POINTS] = {OCV_ARRAY};
const float chargingVolt = (OCV[0] + 10) * NUM_CELLS;
const float noBatVolt = (OCV[NUM_OCV_POINTS - 1] - 500) * NUM_CELLS;
// Start value from minimum voltage for the filter to not start from 0
// that could trigger some events.
// This value is over-written by the first ADC reading, it the voltage seems reasonable.
bool initial_read_done = false;
float last_read_value = (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS);
uint32_t last_read_time_ms = 0;
public: public:
/** /**
* Battery state of charge, from 0 to 100 or -1 for unknown * Battery state of charge, from 0 to 100 or -1 for unknown
@ -475,22 +491,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
return isVbusIn(); return isVbusIn();
} }
private:
/// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power
/// For heltecs with no battery connected, the measured voltage is 2204, so
// need to be higher than that, in this case is 2500mV (3000-500)
const uint16_t OCV[NUM_OCV_POINTS] = {OCV_ARRAY};
const float chargingVolt = (OCV[0] + 10) * NUM_CELLS;
const float noBatVolt = (OCV[NUM_OCV_POINTS - 1] - 500) * NUM_CELLS;
// Start value from minimum voltage for the filter to not start from 0
// that could trigger some events.
// This value is over-written by the first ADC reading, it the voltage seems reasonable.
bool initial_read_done = false;
float last_read_value = (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS);
uint32_t last_read_time_ms = 0;
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT)
uint16_t getRAKVoltage() { return rak9154Sensor.getBusVoltageMv(); } uint16_t getRAKVoltage() { return rak9154Sensor.getBusVoltageMv(); }
@ -502,7 +502,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
return rak9154Sensor.isRunning(); return rak9154Sensor.isRunning();
} }
#endif #endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL) #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL)
uint16_t getINAVoltage() uint16_t getINAVoltage()
{ {
@ -654,6 +653,23 @@ bool Power::analogInit()
#endif #endif
} }
/**
* Initializes the INA sensor for power monitoring.
*
* @return true if the INA sensor is ready, false otherwise.
*/
bool Power::inaInit()
{
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL)
bool result = analogLevel.hasINA();
batteryLevel = &analogLevel;
LOG_DEBUG("Power::inaInit INA sensor is %s", result ? "ready" : "not ready yet");
return result;
#endif
return false;
}
/** /**
* Initializes the Power class. * Initializes the Power class.
* *
@ -667,6 +683,8 @@ bool Power::setup()
found = lipoInit(); found = lipoInit();
if (!found) if (!found)
found = analogInit(); found = analogInit();
if (!found)
found = inaInit();
#ifdef NRF_APM #ifdef NRF_APM
found = true; found = true;

View File

@ -34,7 +34,7 @@ void PowerFSM_setup(){};
static bool isPowered() static bool isPowered()
{ {
// Circumvent the battery sensing logic and assumes constant power if no battery pin or power mgmt IC // Circumvent the battery sensing logic and assumes constant power if no battery pin or power mgmt IC
#if !defined(BATTERY_PIN) && !defined(HAS_AXP192) && !defined(HAS_AXP2101) && !defined(NRF_APM) #if !defined(HAS_BATTERY) && !defined(BATTERY_PIN) && !defined(HAS_AXP192) && !defined(HAS_AXP2101) && !defined(NRF_APM)
return true; return true;
#endif #endif

View File

@ -61,14 +61,14 @@ class PowerStatus : public Status
/** /**
* Note: for boards with battery pin or PMU, 0% battery means 'unknown/this board doesn't have a battery installed' * Note: for boards with battery pin or PMU, 0% battery means 'unknown/this board doesn't have a battery installed'
*/ */
#if defined(HAS_PMU) || defined(BATTERY_PIN) #if defined(HAS_PMU) || defined(BATTERY_PIN) || defined(HAS_BATTERY)
uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 0; } uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 0; }
#endif #endif
/** /**
* Note: for boards without battery pin and PMU, 101% battery means 'the board is using external power' * Note: for boards without battery pin and PMU, 101% battery means 'the board is using external power'
*/ */
#if !defined(HAS_PMU) && !defined(BATTERY_PIN) #if !defined(HAS_PMU) && !defined(BATTERY_PIN) && !defined(HAS_BATTERY)
uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 101; } uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 101; }
#endif #endif

View File

@ -297,6 +297,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef HAS_BLUETOOTH #ifndef HAS_BLUETOOTH
#define HAS_BLUETOOTH 0 #define HAS_BLUETOOTH 0
#endif #endif
#ifndef HAS_BATTERY
#define HAS_BATTERY 0
#endif
#ifndef HW_VENDOR #ifndef HW_VENDOR
#error HW_VENDOR must be defined #error HW_VENDOR must be defined

View File

@ -530,12 +530,14 @@ void setup()
tftSetup(); tftSetup();
#endif #endif
#if defined(HAS_PMU)
// Currently only the tbeam has a PMU // Currently only the tbeam has a PMU
// PMU initialization needs to be placed before i2c scanning // PMU initialization needs to be placed before i2c scanning
power = new Power(); power = new Power();
power->setStatusHandler(powerStatus); power->setStatusHandler(powerStatus);
powerStatus->observe(&power->newStatus); powerStatus->observe(&power->newStatus);
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
#endif
#if !MESHTASTIC_EXCLUDE_I2C #if !MESHTASTIC_EXCLUDE_I2C
// We need to scan here to decide if we have a screen for nodeDB.init() and because power has been applied to // We need to scan here to decide if we have a screen for nodeDB.init() and because power has been applied to
@ -1276,6 +1278,15 @@ void setup()
1000); 1000);
} }
#if !defined(HAS_PMU)
// Currently only the tbeam has a PMU
// PMU initialization needs to be placed before i2c scanning
power = new Power();
power->setStatusHandler(powerStatus);
powerStatus->observe(&power->newStatus);
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
#endif
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values // This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS
powerFSMthread = new PowerFSMThread(); powerFSMthread = new PowerFSMThread();

View File

@ -122,7 +122,8 @@ class Power : private concurrency::OSThread
bool analogInit(); bool analogInit();
/// Setup a Lipo battery level sensor /// Setup a Lipo battery level sensor
bool lipoInit(); bool lipoInit();
/// Setup INA battery level sensor
bool inaInit();
private: private:
// open circuit voltage lookup table // open circuit voltage lookup table
uint8_t low_voltage_counter; uint8_t low_voltage_counter;

View File

@ -23,6 +23,11 @@
// ratio of voltage divider = 3.0 (R17=200k, R18=100k) // ratio of voltage divider = 3.0 (R17=200k, R18=100k)
// #define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic // #define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
// Enables battery-related code and requires BATTERY_IMMUTABLE to be defined. Voltage divider is picked first.
// Ensure a valid address is configured for the INA sensor from which voltage readings are to be obtained.
// #define HAS_BATTERY
// #define BATTERY_IMMUTABLE
#define HAS_CPU_SHUTDOWN 1 #define HAS_CPU_SHUTDOWN 1
#define USE_SX1262 #define USE_SX1262