Добавлено энергосбережение для увеличения работы от аккума:
- через 60 сек экран выключается и есп уходит в сон - слейв в ожидании мастера прослушивает не постоянно 20мс/100мс
This commit is contained in:
@@ -3,7 +3,10 @@
|
||||
#include "Log.h"
|
||||
#include <WiFi.h>
|
||||
#include <esp_mac.h>
|
||||
#include <esp_sleep.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp32-hal-cpu.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -74,12 +77,15 @@ void App::finishInitialization(bool factoryReset) {
|
||||
initialized_ = true;
|
||||
if (!receiver_.begin()) { Log::event("BOOT", "FATAL: capture peripheral init failed"); finish(false, FailReason::UNSUPPORTED); return; }
|
||||
Log::printf("BOOT", "capture initialized: %s", receiver_.highRateBackend() ? "RMT DMA" : "RMT ping-pong");
|
||||
lastUserActivityMs_ = millis();
|
||||
setActivePerformance(false);
|
||||
printConfiguration();
|
||||
if (static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
|
||||
else showIdle();
|
||||
}
|
||||
|
||||
void App::update() {
|
||||
serviceIdlePowerSave();
|
||||
const uint32_t now = millis();
|
||||
const ButtonEvent startEvent = startButton_.update(now);
|
||||
const ButtonEvent modeEvent = modeButton_.update(now);
|
||||
@@ -87,6 +93,10 @@ void App::update() {
|
||||
Log::printf("INPUT", "START %s state=%s", buttonEventName(startEvent), appStateName(state_));
|
||||
if (modeEvent != ButtonEvent::NONE)
|
||||
Log::printf("INPUT", "MODE %s state=%s", buttonEventName(modeEvent), appStateName(state_));
|
||||
if (startEvent != ButtonEvent::NONE || modeEvent != ButtonEvent::NONE) {
|
||||
lastUserActivityMs_ = now;
|
||||
leaveIdlePowerSave();
|
||||
}
|
||||
if (!initialized_) {
|
||||
if (!startButton_.pressed() || !modeButton_.pressed()) finishInitialization(false);
|
||||
else if (now - bootCheckStartedMs_ >= FACTORY_RESET_HOLD_MS) finishInitialization(true);
|
||||
@@ -161,6 +171,8 @@ void App::update() {
|
||||
}
|
||||
|
||||
void App::showIdle() {
|
||||
setActivePerformance(false);
|
||||
lastUserActivityMs_ = millis();
|
||||
char one[24]; snprintf(one, sizeof(one), "MODE: %s", roleName(static_cast<Role>(settings_.role)));
|
||||
display_.show(one, "START=RUN");
|
||||
}
|
||||
@@ -219,6 +231,8 @@ void App::showMenu() {
|
||||
}
|
||||
|
||||
void App::startTest() {
|
||||
leaveIdlePowerSave();
|
||||
setActivePerformance(true);
|
||||
params_ = store_.params(settings_); stageCount_ = frequencyPointCount(params_.startHz, params_.endHz);
|
||||
stageIndex_ = 0; requestedHz_ = 0; pendingReason_ = FailReason::NONE;
|
||||
havePeer_ = false; lastHeartbeatMs_ = 0; lastPeerSeenMs_ = 0;
|
||||
@@ -243,6 +257,8 @@ void App::startTest() {
|
||||
}
|
||||
|
||||
bool App::armSlave(bool preserveDisplay) {
|
||||
setActivePerformance(false);
|
||||
lastUserActivityMs_ = millis();
|
||||
params_ = store_.params(settings_);
|
||||
stageIndex_ = 0; stageCount_ = frequencyPointCount(params_.startHz, params_.endHz);
|
||||
requestedHz_ = 0; session_ = 0; sequence_ = 0; havePeer_ = false;
|
||||
@@ -253,6 +269,7 @@ bool App::armSlave(bool preserveDisplay) {
|
||||
display_.show("LINK FAILED", "RADIO ERROR");
|
||||
return false;
|
||||
}
|
||||
radio_.setWindowedReceive(true);
|
||||
radio_.flush(); state_ = AppState::SLAVE_READY;
|
||||
Log::event("TEST", "Slave automatically armed and waiting for Master");
|
||||
if (!preserveDisplay) display_.show("SLAVE READY", "WAIT MASTER");
|
||||
@@ -377,6 +394,9 @@ void App::handleRadio() {
|
||||
messageName(type), r.packet.session, r.packet.stage, r.packet.sequence);
|
||||
if ((state_ == AppState::SLAVE_READY || state_ == AppState::SLAVE_WAIT_START) &&
|
||||
type == MessageType::DISCOVER && (!havePeer_ || !memcmp(peer_, r.mac, 6))) {
|
||||
leaveIdlePowerSave();
|
||||
setActivePerformance(true);
|
||||
radio_.setWindowedReceive(false);
|
||||
memcpy(peer_, r.mac, 6); havePeer_ = true; session_ = r.packet.session; stageIndex_ = 0; sequence_ = r.packet.sequence;
|
||||
lastPeerSeenMs_ = millis();
|
||||
ProtocolPacket ack = makePacket(MessageType::DISCOVER_ACK); ack.sequence = r.packet.sequence; sendLinked(ack);
|
||||
@@ -491,8 +511,9 @@ void App::handleRadio() {
|
||||
void App::updateMaster() {
|
||||
const uint32_t now = millis();
|
||||
if (state_ == AppState::MASTER_DISCOVER) {
|
||||
if (now - lastSendMs_ >= LINK_RETRY_INTERVAL_MS) {
|
||||
Log::event("ESP-NOW", "DISCOVER retry"); radio_.sendBroadcast(pendingPacket_);
|
||||
if (now - lastSendMs_ >= DISCOVERY_RETRY_INTERVAL_MS) {
|
||||
if (++retries_ % 50U == 0U) Log::event("ESP-NOW", "DISCOVER burst continues");
|
||||
radio_.sendBroadcast(pendingPacket_);
|
||||
lastSendMs_ = now;
|
||||
}
|
||||
return;
|
||||
@@ -590,6 +611,8 @@ void App::finish(bool pass, FailReason reason, bool preserveDisplay) {
|
||||
if (!pass && masterActive && havePeer_ && reason != FailReason::ABORTED) sendAbort(reason);
|
||||
if (state_ != AppState::IDLE && state_ != AppState::MENU) radio_.end();
|
||||
state_ = AppState::FINISHED; pendingReason_ = reason;
|
||||
setActivePerformance(false);
|
||||
lastUserActivityMs_ = millis();
|
||||
if (slaveLinkLost) {
|
||||
char target[12], one[24];
|
||||
Display::formatTestFrequency(actual_.actualHz ? actual_.actualHz : requestedHz_, target, sizeof(target));
|
||||
@@ -618,6 +641,67 @@ void App::finish(bool pass, FailReason reason, bool preserveDisplay) {
|
||||
}
|
||||
}
|
||||
|
||||
bool App::idlePowerSaveAllowed() const {
|
||||
return initialized_ && (state_ == AppState::IDLE || state_ == AppState::MENU ||
|
||||
state_ == AppState::FINISHED || state_ == AppState::SLAVE_READY);
|
||||
}
|
||||
|
||||
void App::setActivePerformance(bool active) {
|
||||
const uint32_t targetMhz = active ? 160U : 80U;
|
||||
if (getCpuFrequencyMhz() != targetMhz && !setCpuFrequencyMhz(targetMhz))
|
||||
Log::printf("POWER", "CPU frequency change to %luMHz FAILED", targetMhz);
|
||||
}
|
||||
|
||||
void App::leaveIdlePowerSave(bool wakeDisplay) {
|
||||
if (!idlePowerSave_) {
|
||||
if (wakeDisplay) display_.setPower(true);
|
||||
return;
|
||||
}
|
||||
idlePowerSave_ = false;
|
||||
lastUserActivityMs_ = millis();
|
||||
if (wakeDisplay) display_.setPower(true);
|
||||
Log::event("POWER", "idle light sleep ended");
|
||||
}
|
||||
|
||||
void App::serviceIdlePowerSave() {
|
||||
if (!idlePowerSaveAllowed()) {
|
||||
leaveIdlePowerSave(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t now = millis();
|
||||
if (!idlePowerSave_) {
|
||||
if (now - lastUserActivityMs_ < IDLE_POWER_SAVE_TIMEOUT_MS) {
|
||||
delay(1); // allow the FreeRTOS idle task to halt the CPU between UI polls
|
||||
return;
|
||||
}
|
||||
idlePowerSave_ = true;
|
||||
display_.setPower(false);
|
||||
Log::event("POWER", "idle timeout; OLED off and light sleep started");
|
||||
}
|
||||
|
||||
gpio_wakeup_enable(static_cast<gpio_num_t>(GPIO_BUTTON_START),
|
||||
BUTTON_ACTIVE_LEVEL == LOW ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
||||
gpio_wakeup_enable(static_cast<gpio_num_t>(GPIO_BUTTON_MODE),
|
||||
BUTTON_ACTIVE_LEVEL == LOW ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
||||
esp_sleep_enable_gpio_wakeup();
|
||||
esp_sleep_enable_timer_wakeup(IDLE_LIGHT_SLEEP_SLICE_US);
|
||||
const esp_err_t result = esp_light_sleep_start();
|
||||
if (result != ESP_OK) {
|
||||
delay(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_GPIO) {
|
||||
// The wake-up press is deliberately consumed. Holding or releasing it
|
||||
// must not later turn into a SHORT, LONG, or REPEAT event.
|
||||
startButton_.suppressUntilRelease();
|
||||
modeButton_.suppressUntilRelease();
|
||||
leaveIdlePowerSave();
|
||||
Log::event("POWER", "button wake consumed; next press will perform the action");
|
||||
}
|
||||
}
|
||||
|
||||
void App::printConfiguration() {
|
||||
if (SERIAL_MINIMAL_LOG) return;
|
||||
const char *board = TARGET_IS_C3 ? "ESP32-C3" : "ESP32-S3";
|
||||
|
||||
Reference in New Issue
Block a user