Add Power Scheduler

This commit is contained in:
2025-02-11 23:33:19 +01:00
parent 893234ed24
commit b44538b473
5 changed files with 425 additions and 180 deletions

View File

@@ -10,41 +10,106 @@
#include "Power.h"
static portMUX_TYPE mux;
void Power::begin()
{
// Check if another instance of us already initialized the power scheduler,
// if not, we will do it.
if (powerScheduler == nullptr)
{
powerScheduler = PowerScheduler::getPowerScheduler();
if (!(powerScheduler->tryAccquirePowerAllowance(CONSUMPTION_ESP_BASE)))
{
Serial.println("Alledgedly not enough power available to reserve the ESP32s base power consumption. Something is wrong.");
return;
}
void Power::begin() {
// Check if another instance of us already initialized the power scheduler,
// if not, we will do it.
if (powerScheduler == nullptr) {
powerScheduler = &PowerScheduler::getPowerScheduler();
if (!(powerScheduler->tryAccquireCurrentAllowance(
PowerParameters::PowerConsumers::ESP,
PowerParameters::CurrentConsumptions::CURRENT_ESP_AVG))) {
Serial.println("Alledgedly not enough power available to reserve the "
"ESP32s base power consumption. Something is wrong.");
return;
}
}
}
uint16_t Power::getFreePowerBudget(void)
{
return powerScheduler->getFreePowerBudget();
uint16_t Power::getFreeCurrentBudget(void) {
return powerScheduler->getFreeCurrentBudget();
}
bool Power::tryAccquirePowerAllowance(uint16_t neededPower)
{
return powerScheduler->tryAccquirePowerAllowance(neededPower);
bool Power::tryAccquireCurrentAllowance(
PowerParameters::PowerConsumers consumer, uint16_t neededCurrent,
uint16_t requestedDurationMs) {
return powerScheduler->tryAccquireCurrentAllowance(consumer, neededCurrent,
requestedDurationMs);
}
bool Power::waitForPowerAllowance(uint16_t neededPower, TickType_t TicksToWait)
{
return powerScheduler->waitForPowerAllowance(neededPower, TicksToWait);
bool Power::waitForCurrentAllowance(PowerParameters::PowerConsumers consumer,
uint16_t neededCurrent,
TickType_t TicksToWait,
uint16_t requestedDurationMs) {
return powerScheduler->waitForCurrentAllowance(
consumer, neededCurrent, TicksToWait, requestedDurationMs);
}
void Power::beginPermanentDeepSleep(void)
{
return powerScheduler->beginPermanentDeepSleep();
void Power::beginPermanentDeepSleep(void) {
return powerScheduler->beginPermanentDeepSleep();
}
void Power::releasePower(uint16_t power)
{
void Power::releaseCurrent(PowerParameters::PowerConsumers consumer) {
powerScheduler->releaseCurrent(consumer);
}
float Power::getBatteryVoltage() {
// Get the battery voltage from the ADC and convert it to a voltage
// using the voltage divider.
portENTER_CRITICAL(&mux);
// Enable voltage divider
digitalWrite(PowerParameters::PinConfig::BAT_ADC_EN, HIGH);
// Returns value between 0 and 4095 mapping to between 0 and 3.3V
uint16_t batteryAdcValue =
analogRead(PowerParameters::PinConfig::BAT_ADC) *
(PowerParameters::Battery::BAT_ADC::VOLTAGE_DIVIDER_FACTOR);
// Disable voltage divider
digitalWrite(PowerParameters::PinConfig::BAT_ADC_EN, LOW);
portEXIT_CRITICAL(&mux);
// Convert ADC value to voltage
float batteryVoltage =
(batteryAdcValue * 3.3 / 4095) *
PowerParameters::Battery::BAT_ADC::VOLTAGE_DIVIDER_FACTOR;
return batteryVoltage;
}
int Power::getBatteryChargePercent() {
// Get the battery voltage and calculate the charge state based on the
// discharge curve.
float batteryVoltage = getBatteryVoltage();
float chargeState = 0;
// Clamp edge cases
if (batteryVoltage >=
PowerParameters::Battery::DISCHARGE_CURVE::VOLTAGES[0]) {
return PowerParameters::Battery::DISCHARGE_CURVE::CHARGE_STATES[0];
}
if (batteryVoltage <=
PowerParameters::Battery::DISCHARGE_CURVE::VOLTAGES
[PowerParameters::Battery::DISCHARGE_CURVE::NUM_POINTS - 1]) {
return PowerParameters::Battery::DISCHARGE_CURVE::CHARGE_STATES
[PowerParameters::Battery::DISCHARGE_CURVE::NUM_POINTS - 1];
}
float p1_x, p1_y, p2_x, p2_y;
for (int i = 0; i < PowerParameters::Battery::DISCHARGE_CURVE::NUM_POINTS;
i++) {
if (batteryVoltage >=
PowerParameters::Battery::DISCHARGE_CURVE::VOLTAGES[i]) {
p1_y = PowerParameters::Battery::DISCHARGE_CURVE::CHARGE_STATES[i];
p1_x = PowerParameters::Battery::DISCHARGE_CURVE::VOLTAGES[i];
p2_y = PowerParameters::Battery::DISCHARGE_CURVE::CHARGE_STATES[i + 1];
p2_x = PowerParameters::Battery::DISCHARGE_CURVE::VOLTAGES[i + 1];
chargeState =
((p2_y - p1_y) / (p2_x - p1_x)) * (batteryVoltage - p1_x) + p1_y;
return chargeState;
}
}
}
PowerScheduler* Power::powerScheduler = nullptr;
Power::Power() {
// Initialize the power scheduler
powerScheduler = &PowerScheduler::getPowerScheduler();
// Initialize the mutex
mux = portMUX_INITIALIZER_UNLOCKED;
}