mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-09 06:32:06 +00:00
Add battery sensing (mostly) for TBEAM0.7
However, disabled until someone with suitable hardware can test and report back. @slavino and @tschundler would you be willing to try it with your boards? You'll need to uncomment the following line in configuration.h // #define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
This commit is contained in:
parent
c30b570e16
commit
6a402b13fa
@ -9,7 +9,7 @@
|
|||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
default_envs = tbeam
|
default_envs = tbeam
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
; common is not currently used
|
; common is not currently used
|
||||||
@ -69,7 +69,8 @@ lib_deps =
|
|||||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
||||||
https://github.com/meshtastic/RadioLib.git#d6b12f7eb0a06bd2414c79b437b25d377e3f603f
|
https://github.com/meshtastic/RadioLib.git#d6b12f7eb0a06bd2414c79b437b25d377e3f603f
|
||||||
https://github.com/meshtastic/TinyGPSPlus.git
|
https://github.com/meshtastic/TinyGPSPlus.git
|
||||||
|
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
|
||||||
|
|
||||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||||
[esp32_base]
|
[esp32_base]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@ -99,7 +100,6 @@ extends = esp32_base
|
|||||||
board = ttgo-t-beam
|
board = ttgo-t-beam
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
https://github.com/meshtastic/AXP202X_Library.git
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_base.build_flags} -D TBEAM_V10
|
${esp32_base.build_flags} -D TBEAM_V10
|
||||||
|
|
||||||
|
154
src/Power.cpp
154
src/Power.cpp
@ -1,27 +1,92 @@
|
|||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include "PowerFSM.h"
|
#include "PowerFSM.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
#include "utils.h"
|
||||||
#ifdef TBEAM_V10
|
|
||||||
|
|
||||||
// FIXME. nasty hack cleanup how we load axp192
|
// FIXME. nasty hack cleanup how we load axp192
|
||||||
#undef AXP192_SLAVE_ADDRESS
|
#undef AXP192_SLAVE_ADDRESS
|
||||||
#include "axp20x.h"
|
#include "axp20x.h"
|
||||||
|
|
||||||
|
#ifdef TBEAM_V10
|
||||||
AXP20X_Class axp;
|
AXP20X_Class axp;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool pmu_irq = false;
|
bool pmu_irq = false;
|
||||||
|
|
||||||
Power *power;
|
Power *power;
|
||||||
|
|
||||||
bool Power::setup()
|
/**
|
||||||
|
* If this board has a battery level sensor, set this to a valid implementation
|
||||||
|
*/
|
||||||
|
static HasBatteryLevel *batteryLevel; // Default to NULL for no battery level sensor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input
|
||||||
|
*/
|
||||||
|
class AnalogBatteryLevel : public HasBatteryLevel
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Battery state of charge, from 0 to 100 or -1 for unknown
|
||||||
|
*
|
||||||
|
* FIXME - use a lipo lookup table, the current % full is super wrong
|
||||||
|
*/
|
||||||
|
virtual int getBattPercentage()
|
||||||
|
{
|
||||||
|
float v = getBattVoltage();
|
||||||
|
|
||||||
axp192Init();
|
if (v < 2.1)
|
||||||
concurrency::PeriodicTask::setup(); // We don't start our periodic task unless we actually found the device
|
return -1;
|
||||||
setPeriod(1);
|
|
||||||
|
|
||||||
return axp192_found;
|
return 100 * (getBattVoltage() - 3.27) / (4.2 - 3.27);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The raw voltage of the battery or NAN if unknown
|
||||||
|
*/
|
||||||
|
virtual float getBattVoltage()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
#ifdef BATTERY_PIN
|
||||||
|
analogRead(BATTERY_PIN) * 2.0 * (3.3 / 1024.0);
|
||||||
|
#else
|
||||||
|
NAN;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true if there is a battery installed in this unit
|
||||||
|
*/
|
||||||
|
virtual bool isBatteryConnect() { return true; }
|
||||||
|
} analogLevel;
|
||||||
|
|
||||||
|
bool Power::analogInit()
|
||||||
|
{
|
||||||
|
#ifdef BATTERY_PIN
|
||||||
|
DEBUG_MSG("Using analog input for battery level\n");
|
||||||
|
adcAttachPin(BATTERY_PIN);
|
||||||
|
// adcStart(BATTERY_PIN);
|
||||||
|
analogReadResolution(10); // Default of 12 is not very linear. Recommended to use 10 or 11 depending on needed resolution.
|
||||||
|
batteryLevel = &analogLevel;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Power::setup()
|
||||||
|
{
|
||||||
|
bool found = axp192Init();
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
found = analogInit();
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
concurrency::PeriodicTask::setup(); // We don't start our periodic task unless we actually found the device
|
||||||
|
setPeriod(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads power status to powerStatus singleton.
|
/// Reads power status to powerStatus singleton.
|
||||||
@ -29,42 +94,45 @@ bool Power::setup()
|
|||||||
// TODO(girts): move this and other axp stuff to power.h/power.cpp.
|
// TODO(girts): move this and other axp stuff to power.h/power.cpp.
|
||||||
void Power::readPowerStatus()
|
void Power::readPowerStatus()
|
||||||
{
|
{
|
||||||
bool hasBattery = axp.isBatteryConnect();
|
if (batteryLevel) {
|
||||||
int batteryVoltageMv = 0;
|
bool hasBattery = batteryLevel->isBatteryConnect();
|
||||||
uint8_t batteryChargePercent = 0;
|
int batteryVoltageMv = 0;
|
||||||
if (hasBattery) {
|
uint8_t batteryChargePercent = 0;
|
||||||
batteryVoltageMv = axp.getBattVoltage();
|
if (hasBattery) {
|
||||||
// If the AXP192 returns a valid battery percentage, use it
|
batteryVoltageMv = batteryLevel->getBattVoltage();
|
||||||
if (axp.getBattPercentage() >= 0) {
|
// If the AXP192 returns a valid battery percentage, use it
|
||||||
batteryChargePercent = axp.getBattPercentage();
|
if (batteryLevel->getBattPercentage() >= 0) {
|
||||||
} else {
|
batteryChargePercent = batteryLevel->getBattPercentage();
|
||||||
// If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error
|
} else {
|
||||||
// In that case, we compute an estimate of the charge percent based on maximum and minimum voltages defined in power.h
|
// If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error
|
||||||
batteryChargePercent = clamp((int)(((batteryVoltageMv - BAT_MILLIVOLTS_EMPTY) * 1e2) / (BAT_MILLIVOLTS_FULL - BAT_MILLIVOLTS_EMPTY)), 0, 100);
|
// In that case, we compute an estimate of the charge percent based on maximum and minimum voltages defined in
|
||||||
|
// power.h
|
||||||
|
batteryChargePercent =
|
||||||
|
clamp((int)(((batteryVoltageMv - BAT_MILLIVOLTS_EMPTY) * 1e2) / (BAT_MILLIVOLTS_FULL - BAT_MILLIVOLTS_EMPTY)),
|
||||||
|
0, 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notify any status instances that are observing us
|
||||||
|
const meshtastic::PowerStatus powerStatus = meshtastic::PowerStatus(
|
||||||
|
hasBattery, batteryLevel->isVBUSPlug(), batteryLevel->isChargeing(), batteryVoltageMv, batteryChargePercent);
|
||||||
|
newStatus.notifyObservers(&powerStatus);
|
||||||
|
|
||||||
|
// If we have a battery at all and it is less than 10% full, force deep sleep
|
||||||
|
if (powerStatus.getHasBattery() && !powerStatus.getHasUSB() && batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS)
|
||||||
|
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify any status instances that are observing us
|
|
||||||
const meshtastic::PowerStatus powerStatus = meshtastic::PowerStatus(hasBattery, axp.isVBUSPlug(), axp.isChargeing(), batteryVoltageMv, batteryChargePercent);
|
|
||||||
newStatus.notifyObservers(&powerStatus);
|
|
||||||
|
|
||||||
// If we have a battery at all and it is less than 10% full, force deep sleep
|
|
||||||
if (powerStatus.getHasBattery() && !powerStatus.getHasUSB() &&
|
|
||||||
axp.getBattVoltage() < MIN_BAT_MILLIVOLTS)
|
|
||||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Power::doTask()
|
void Power::doTask()
|
||||||
{
|
{
|
||||||
readPowerStatus();
|
readPowerStatus();
|
||||||
|
|
||||||
// Only read once every 20 seconds once the power status for the app has been initialized
|
// Only read once every 20 seconds once the power status for the app has been initialized
|
||||||
if(statusHandler && statusHandler->isInitialized())
|
if (statusHandler && statusHandler->isInitialized())
|
||||||
setPeriod(1000 * 20);
|
setPeriod(1000 * 20);
|
||||||
}
|
}
|
||||||
#endif // TBEAM_V10
|
|
||||||
|
|
||||||
#ifdef AXP192_SLAVE_ADDRESS
|
|
||||||
/**
|
/**
|
||||||
* Init the power manager chip
|
* Init the power manager chip
|
||||||
*
|
*
|
||||||
@ -74,10 +142,13 @@ void Power::doTask()
|
|||||||
30mA -> charges GPS backup battery // charges the tiny J13 battery by the GPS to power the GPS ram (for a couple of days), can
|
30mA -> charges GPS backup battery // charges the tiny J13 battery by the GPS to power the GPS ram (for a couple of days), can
|
||||||
not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS
|
not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS
|
||||||
*/
|
*/
|
||||||
void Power::axp192Init()
|
bool Power::axp192Init()
|
||||||
{
|
{
|
||||||
|
#ifdef TBEAM_V10
|
||||||
if (axp192_found) {
|
if (axp192_found) {
|
||||||
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
|
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
|
||||||
|
batteryLevel = &axp;
|
||||||
|
|
||||||
DEBUG_MSG("AXP192 Begin PASS\n");
|
DEBUG_MSG("AXP192 Begin PASS\n");
|
||||||
|
|
||||||
// axp.setChgLEDMode(LED_BLINK_4HZ);
|
// axp.setChgLEDMode(LED_BLINK_4HZ);
|
||||||
@ -135,12 +206,16 @@ void Power::axp192Init()
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("AXP192 not found\n");
|
DEBUG_MSG("AXP192 not found\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return axp192_found;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void Power::loop()
|
|
||||||
|
void Power::loop()
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef PMU_IRQ
|
#ifdef PMU_IRQ
|
||||||
if (pmu_irq) {
|
if (pmu_irq) {
|
||||||
pmu_irq = false;
|
pmu_irq = false;
|
||||||
@ -174,6 +249,5 @@ void Power::loop()
|
|||||||
axp.clearIRQ();
|
axp.clearIRQ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // T_BEAM_V10
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
// Leave undefined to disable our PMU IRQ handler
|
// Leave undefined to disable our PMU IRQ handler
|
||||||
#define PMU_IRQ 35
|
#define PMU_IRQ 35
|
||||||
|
|
||||||
#define AXP192_SLAVE_ADDRESS 0x34
|
#define AXP192_SLAVE_ADDRESS 0x34
|
||||||
|
|
||||||
#elif defined(TBEAM_V07)
|
#elif defined(TBEAM_V07)
|
||||||
@ -180,6 +179,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define I2C_SCL 22
|
#define I2C_SCL 22
|
||||||
|
|
||||||
#define BUTTON_PIN 39
|
#define BUTTON_PIN 39
|
||||||
|
// #define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||||
|
|
||||||
#ifndef USE_JTAG
|
#ifndef USE_JTAG
|
||||||
#define RF95_RESET 23
|
#define RF95_RESET 23
|
||||||
@ -278,6 +278,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define GPS_RX_PIN 36
|
#define GPS_RX_PIN 36
|
||||||
#define GPS_TX_PIN 39
|
#define GPS_TX_PIN 39
|
||||||
|
|
||||||
|
// #define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||||
|
|
||||||
#define I2C_SDA 21 // I2C pins for this board
|
#define I2C_SDA 21 // I2C pins for this board
|
||||||
#define I2C_SCL 22
|
#define I2C_SCL 22
|
||||||
|
|
||||||
|
@ -210,13 +210,11 @@ void setup()
|
|||||||
esp32Setup();
|
esp32Setup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TBEAM_V10
|
|
||||||
// Currently only the tbeam has a PMU
|
// Currently only the tbeam has a PMU
|
||||||
power = new Power();
|
power = new Power();
|
||||||
power->setup();
|
power->setup();
|
||||||
power->setStatusHandler(powerStatus);
|
power->setStatusHandler(powerStatus);
|
||||||
powerStatus->observe(&power->newStatus);
|
powerStatus->observe(&power->newStatus);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NRF52_SERIES
|
#ifdef NRF52_SERIES
|
||||||
nrf52Setup();
|
nrf52Setup();
|
||||||
|
22
src/power.h
22
src/power.h
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "concurrency/PeriodicTask.h"
|
|
||||||
#include "PowerStatus.h"
|
#include "PowerStatus.h"
|
||||||
|
#include "concurrency/PeriodicTask.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per @spattinson
|
* Per @spattinson
|
||||||
@ -18,23 +18,23 @@
|
|||||||
class Power : public concurrency::PeriodicTask
|
class Power : public concurrency::PeriodicTask
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Observable<const meshtastic::PowerStatus *> newStatus;
|
Observable<const meshtastic::PowerStatus *> newStatus;
|
||||||
|
|
||||||
void readPowerStatus();
|
void readPowerStatus();
|
||||||
void loop();
|
void loop();
|
||||||
virtual bool setup();
|
virtual bool setup();
|
||||||
virtual void doTask();
|
virtual void doTask();
|
||||||
void setStatusHandler(meshtastic::PowerStatus *handler)
|
void setStatusHandler(meshtastic::PowerStatus *handler) { statusHandler = handler; }
|
||||||
{
|
|
||||||
statusHandler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
meshtastic::PowerStatus *statusHandler;
|
|
||||||
virtual void axp192Init();
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
meshtastic::PowerStatus *statusHandler;
|
||||||
|
|
||||||
|
/// Setup a axp192, return true if found
|
||||||
|
bool axp192Init();
|
||||||
|
|
||||||
|
/// Setup a simple ADC input based battery sensor
|
||||||
|
bool analogInit();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Power *power;
|
extern Power *power;
|
Loading…
Reference in New Issue
Block a user