mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-06 01:48:13 +00:00
Battery handling and LED for M4
This commit is contained in:
134
src/Power.cpp
134
src/Power.cpp
@@ -692,6 +692,8 @@ bool Power::setup()
|
||||
found = true;
|
||||
} else if (lipoChargerInit()) {
|
||||
found = true;
|
||||
} else if (serialBatteryInit()) {
|
||||
found = true;
|
||||
} else if (meshSolarInit()) {
|
||||
found = true;
|
||||
} else if (analogInit()) {
|
||||
@@ -1566,3 +1568,135 @@ bool Power::meshSolarInit()
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SERIAL_BATTERY_LEVEL
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
/**
|
||||
* SerialBatteryLevel class for pulling battery information from a secondary MCU over serial.
|
||||
*/
|
||||
class SerialBatteryLevel : public HasBatteryLevel
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* Init the I2C meshSolar battery level sensor
|
||||
*/
|
||||
bool runOnce()
|
||||
{
|
||||
BatterySerial.begin(4800);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Battery state of charge, from 0 to 100 or -1 for unknown
|
||||
*/
|
||||
virtual int getBatteryPercent() override { return v_percent; }
|
||||
|
||||
/**
|
||||
* The raw voltage of the battery in millivolts, or NAN if unknown
|
||||
*/
|
||||
virtual uint16_t getBattVoltage() override { return voltage * 1000; }
|
||||
|
||||
/**
|
||||
* return true if there is a battery installed in this unit
|
||||
*/
|
||||
virtual bool isBatteryConnect() override
|
||||
{
|
||||
// definitely need to gobble up more bytes at once
|
||||
if (BatterySerial.available() > 5) {
|
||||
LOG_WARN("SerialBatteryLevel: %u bytes available", BatterySerial.available());
|
||||
while (BatterySerial.available() > 11) {
|
||||
BatterySerial.read(); // flush old data
|
||||
}
|
||||
LOG_WARN("SerialBatteryLevel: %u bytes now available", BatterySerial.available());
|
||||
int tries = 0;
|
||||
while (BatterySerial.read() != 0xFE) {
|
||||
tries++; // wait for start byte
|
||||
if (tries > 10) {
|
||||
LOG_WARN("SerialBatteryLevel: no start byte found");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Data[1] = BatterySerial.read();
|
||||
Data[2] = BatterySerial.read();
|
||||
Data[3] = BatterySerial.read();
|
||||
Data[4] = BatterySerial.read();
|
||||
Data[5] = BatterySerial.read();
|
||||
if (Data[5] != 0xFD) {
|
||||
LOG_WARN("SerialBatteryLevel: invalid end byte %02x", Data[5]);
|
||||
return true;
|
||||
}
|
||||
v_percent = Data[1];
|
||||
voltage = Data[2] + (((float)Data[3]) / 100) + (((float)Data[4]) / 10000);
|
||||
voltage *= 2;
|
||||
LOG_WARN("SerialBatteryLevel: received data %u, %f, %02x", v_percent, voltage, Data[5]);
|
||||
return true;
|
||||
}
|
||||
// This function runs first, so use it to grab the latest data from the secondary MCU
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if there is an external power source detected
|
||||
*/
|
||||
virtual bool isVbusIn() override
|
||||
{
|
||||
#if defined(EXT_CHRG_DETECT)
|
||||
|
||||
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool isCharging() override
|
||||
{
|
||||
#ifdef EXT_CHRG_DETECT
|
||||
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
|
||||
|
||||
#endif
|
||||
// by default, we check the battery voltage only
|
||||
return isVbusIn();
|
||||
}
|
||||
|
||||
private:
|
||||
SoftwareSerial BatterySerial = SoftwareSerial(SERIAL_BATTERY_RX, SERIAL_BATTERY_TX);
|
||||
uint8_t Data[6] = {0};
|
||||
int v_percent = 0;
|
||||
float voltage = 0.0;
|
||||
};
|
||||
|
||||
SerialBatteryLevel serialBatteryLevel;
|
||||
|
||||
/**
|
||||
* Init the serial battery level sensor
|
||||
*/
|
||||
bool Power::serialBatteryInit()
|
||||
{
|
||||
#ifdef EXT_PWR_DETECT
|
||||
pinMode(EXT_PWR_DETECT, INPUT);
|
||||
#endif
|
||||
#ifdef EXT_CHRG_DETECT
|
||||
pinMode(EXT_CHRG_DETECT, ext_chrg_detect_mode);
|
||||
#endif
|
||||
|
||||
bool result = serialBatteryLevel.runOnce();
|
||||
LOG_DEBUG("Power::serialBatteryInit serial battery sensor is %s", result ? "ready" : "not ready yet");
|
||||
if (!result)
|
||||
return false;
|
||||
batteryLevel = &serialBatteryLevel;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
/**
|
||||
* If this device has no serial battery level sensor, don't try to use it.
|
||||
*/
|
||||
bool Power::serialBatteryInit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13,16 +13,18 @@ StatusLEDModule::StatusLEDModule() : concurrency::OSThread("StatusLEDModule")
|
||||
{
|
||||
bluetoothStatusObserver.observe(&bluetoothStatus->onNewStatus);
|
||||
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||
if (inputBroker)
|
||||
inputObserver.observe(inputBroker);
|
||||
}
|
||||
|
||||
int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
{
|
||||
switch (arg->getStatusType()) {
|
||||
case STATUS_TYPE_POWER: {
|
||||
meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg;
|
||||
if (powerStatus->getHasUSB()) {
|
||||
meshtastic::PowerStatus *_powerStatus = (meshtastic::PowerStatus *)arg;
|
||||
if (_powerStatus->getHasUSB()) {
|
||||
power_state = charging;
|
||||
if (powerStatus->getBatteryChargePercent() >= 100) {
|
||||
if (_powerStatus->getBatteryChargePercent() >= 100) {
|
||||
power_state = charged;
|
||||
}
|
||||
} else {
|
||||
@@ -56,6 +58,12 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
return 0;
|
||||
};
|
||||
|
||||
int StatusLEDModule::handleInputEvent(const InputEvent *event)
|
||||
{
|
||||
lastUserbuttonTime = millis();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t StatusLEDModule::runOnce()
|
||||
{
|
||||
|
||||
@@ -82,6 +90,21 @@ int32_t StatusLEDModule::runOnce()
|
||||
PAIRING_LED_state = LED_STATE_ON;
|
||||
}
|
||||
|
||||
bool chargeIndicatorLED1 = LED_STATE_OFF;
|
||||
bool chargeIndicatorLED2 = LED_STATE_OFF;
|
||||
bool chargeIndicatorLED3 = LED_STATE_OFF;
|
||||
bool chargeIndicatorLED4 = LED_STATE_OFF;
|
||||
if (lastUserbuttonTime + 10 * 1000 > millis()) {
|
||||
// should this be off at very low percentages?
|
||||
chargeIndicatorLED1 = LED_STATE_ON;
|
||||
if (powerStatus && powerStatus->getBatteryChargePercent() >= 25)
|
||||
chargeIndicatorLED2 = LED_STATE_ON;
|
||||
if (powerStatus && powerStatus->getBatteryChargePercent() >= 50)
|
||||
chargeIndicatorLED3 = LED_STATE_ON;
|
||||
if (powerStatus && powerStatus->getBatteryChargePercent() >= 75)
|
||||
chargeIndicatorLED4 = LED_STATE_ON;
|
||||
}
|
||||
|
||||
#ifdef LED_CHARGE
|
||||
digitalWrite(LED_CHARGE, CHARGE_LED_state);
|
||||
#endif
|
||||
@@ -90,5 +113,18 @@ int32_t StatusLEDModule::runOnce()
|
||||
digitalWrite(LED_PAIRING, PAIRING_LED_state);
|
||||
#endif
|
||||
|
||||
#ifdef Battery_LED_1
|
||||
digitalWrite(Battery_LED_1, chargeIndicatorLED1);
|
||||
#endif
|
||||
#ifdef Battery_LED_2
|
||||
digitalWrite(Battery_LED_2, chargeIndicatorLED2);
|
||||
#endif
|
||||
#ifdef Battery_LED_3
|
||||
digitalWrite(Battery_LED_3, chargeIndicatorLED3);
|
||||
#endif
|
||||
#ifdef Battery_LED_4
|
||||
digitalWrite(Battery_LED_4, chargeIndicatorLED4);
|
||||
#endif
|
||||
|
||||
return (my_interval);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "PowerStatus.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include "input/InputBroker.h"
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
@@ -17,6 +18,8 @@ class StatusLEDModule : private concurrency::OSThread
|
||||
|
||||
int handleStatusUpdate(const meshtastic::Status *);
|
||||
|
||||
int handleInputEvent(const InputEvent *arg);
|
||||
|
||||
protected:
|
||||
unsigned int my_interval = 1000; // interval in millisconds
|
||||
virtual int32_t runOnce() override;
|
||||
@@ -25,12 +28,15 @@ class StatusLEDModule : private concurrency::OSThread
|
||||
CallbackObserver<StatusLEDModule, const meshtastic::Status *>(this, &StatusLEDModule::handleStatusUpdate);
|
||||
CallbackObserver<StatusLEDModule, const meshtastic::Status *> powerStatusObserver =
|
||||
CallbackObserver<StatusLEDModule, const meshtastic::Status *>(this, &StatusLEDModule::handleStatusUpdate);
|
||||
CallbackObserver<StatusLEDModule, const InputEvent *> inputObserver =
|
||||
CallbackObserver<StatusLEDModule, const InputEvent *>(this, &StatusLEDModule::handleInputEvent);
|
||||
|
||||
private:
|
||||
bool CHARGE_LED_state = LED_STATE_OFF;
|
||||
bool PAIRING_LED_state = LED_STATE_OFF;
|
||||
|
||||
uint32_t PAIRING_LED_starttime = 0;
|
||||
uint32_t lastUserbuttonTime = 0;
|
||||
|
||||
enum PowerState { discharging, charging, charged };
|
||||
|
||||
|
||||
@@ -132,6 +132,8 @@ class Power : private concurrency::OSThread
|
||||
bool lipoChargerInit();
|
||||
/// Setup a meshSolar battery sensor
|
||||
bool meshSolarInit();
|
||||
/// Setup a serial battery sensor
|
||||
bool serialBatteryInit();
|
||||
|
||||
private:
|
||||
void shutdown();
|
||||
|
||||
@@ -37,4 +37,15 @@ void initVariant()
|
||||
|
||||
pinMode(LED_PAIRING, OUTPUT);
|
||||
ledOff(LED_PAIRING);
|
||||
|
||||
pinMode(Battery_LED_1, OUTPUT);
|
||||
ledOff(Battery_LED_1);
|
||||
pinMode(Battery_LED_2, OUTPUT);
|
||||
ledOff(Battery_LED_2);
|
||||
|
||||
pinMode(Battery_LED_3, OUTPUT);
|
||||
ledOff(Battery_LED_3);
|
||||
|
||||
pinMode(Battery_LED_4, OUTPUT);
|
||||
ledOff(Battery_LED_4);
|
||||
}
|
||||
|
||||
@@ -45,10 +45,12 @@ extern "C" {
|
||||
#define LED_CHARGE (32 + 9)
|
||||
#define LED_PAIRING (13)
|
||||
|
||||
#define LED_STATE_ON 1
|
||||
#define Battery_LED_1 (15)
|
||||
#define Battery_LED_2 (17)
|
||||
#define Battery_LED_3 (32 + 2)
|
||||
#define Battery_LED_4 (32 + 4)
|
||||
|
||||
// USB / power detection
|
||||
#define EXT_PWR_DETECT (32 + 3) // P1.03 USB present sense
|
||||
#define LED_STATE_ON 1
|
||||
|
||||
// Button
|
||||
#define PIN_BUTTON1 (4)
|
||||
@@ -65,6 +67,10 @@ extern "C" {
|
||||
#define AREF_VOLTAGE 3.0
|
||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||
|
||||
#define HAS_SERIAL_BATTERY_LEVEL 1
|
||||
#define SERIAL_BATTERY_RX 30
|
||||
#define SERIAL_BATTERY_TX 5
|
||||
|
||||
static const uint8_t A0 = PIN_A0;
|
||||
|
||||
#define PIN_NFC1 (9)
|
||||
@@ -80,7 +86,7 @@ static const uint8_t A0 = PIN_A0;
|
||||
|
||||
// charger status
|
||||
#define EXT_CHRG_DETECT (32 + 6)
|
||||
#define EXT_CHRG_DETECT_VALUE LOW
|
||||
#define EXT_CHRG_DETECT_VALUE HIGH
|
||||
|
||||
// SPI
|
||||
#define SPI_INTERFACES_COUNT 1
|
||||
|
||||
Reference in New Issue
Block a user