Сделана настройка мощности передающей оптики

This commit is contained in:
2026-08-23 18:32:47 +03:00
parent 3907cbcf77
commit 8699f8e4eb
7 changed files with 224 additions and 12 deletions

View File

@@ -14,6 +14,8 @@
#include <string.h>
namespace {
constexpr uint8_t MENU_OPTICAL_CALIBRATION_ITEM = 7;
const char *uiFailName(FailReason reason);
const char *appStateName(AppState state) {
@@ -248,6 +250,13 @@ uint8_t cycleIndex(uint8_t value, uint8_t first, uint8_t last, int direction) {
return value <= first ? last : static_cast<uint8_t>(value - 1U);
}
uint8_t nextMenuItem(uint8_t current, TestGroup group) {
if (group == TestGroup::BOARD)
return current == 0U ? MENU_OPTICAL_CALIBRATION_ITEM : 0U;
return current >= MENU_OPTICAL_CALIBRATION_ITEM ? 0U
: static_cast<uint8_t>(current + 1U);
}
bool parseUnsigned(const char *text, uint32_t &value) {
if (!text || !*text || *text == '-') return false;
char *end = nullptr;
@@ -388,18 +397,25 @@ void App::update() {
}
if (state_ == AppState::MENU) {
if (modeEvent == ButtonEvent::SHORT) {
const uint8_t menuCount = static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD ? 1U : 7U;
menuItem_ = (menuItem_ + 1U) % menuCount; Log::printf("ACTION", "menu item selected index=%u", menuItem_); showMenu();
leaveOpticalCalibration();
menuItem_ = nextMenuItem(menuItem_,
static_cast<TestGroup>(settings_.testGroup));
Log::printf("ACTION", "menu item selected index=%u", menuItem_);
showMenu();
}
else if (modeEvent == ButtonEvent::LONG) {
leaveOpticalCalibration();
sanitizeRange(); const bool saved = store_.save(settings_); params_ = store_.params(settings_);
Log::printf("ACTION", "settings menu saved and closed, NVS=%s", saved ? "OK" : "FAILED");
state_ = AppState::IDLE; printConfiguration();
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::OPTICS &&
static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
else showIdle();
} else if (startEvent == ButtonEvent::SHORT) changeMenu(+1);
else if (startEvent == ButtonEvent::LONG || startEvent == ButtonEvent::REPEAT) changeMenu(-1);
} else if (menuItem_ != MENU_OPTICAL_CALIBRATION_ITEM &&
startEvent == ButtonEvent::SHORT) changeMenu(+1);
else if (menuItem_ != MENU_OPTICAL_CALIBRATION_ITEM &&
(startEvent == ButtonEvent::LONG || startEvent == ButtonEvent::REPEAT)) changeMenu(-1);
updateOpticalCalibration(now);
return;
}
if (state_ == AppState::SOLO_MEASURE) {
@@ -544,6 +560,7 @@ bool App::serialSettingsMutable() const {
void App::finishSerialSettingsChange() {
if (state_ == AppState::SLAVE_READY) radio_.end();
leaveOpticalCalibration();
state_ = AppState::IDLE;
sanitizeRange();
params_ = store_.params(settings_);
@@ -589,6 +606,7 @@ void App::handleSerialCommand(char *line) {
Serial.println("OK board test stopped");
stopBoardTest();
} else if (state_ == AppState::MENU) {
leaveOpticalCalibration();
state_ = AppState::IDLE; showIdle(); Serial.println("OK menu closed");
} else if (state_ == AppState::SLAVE_READY) Serial.println("OK slave is armed; no test is running");
else {
@@ -823,6 +841,9 @@ void App::showMenu() {
display_.show(one, total);
return;
}
case MENU_OPTICAL_CALIBRATION_ITEM:
enterOpticalCalibration(millis());
return;
default: return;
}
formatMenuLine(label, value, one, sizeof(one));
@@ -833,6 +854,43 @@ void App::showMenu() {
display_.show(one, total);
}
void App::enterOpticalCalibration(uint32_t now) {
if (opticalCalibrationActive_) return;
optical_current_begin();
pwm_.lightOn();
opticalCalibrationActive_ = true;
opticalCalibrationStartedMs_ = now;
opticalCalibrationUpdatedMs_ = 0;
display_.show("Idiode: --.- mA", "Vcc: --.-- V");
Log::printf("CALIB", "optical LED ON; sense GPIO=%u, VCC GPIO=%u, settling %lums",
GPIO_OPTICAL_CURRENT, GPIO_OPTICAL_VCC, OPTICAL_CURRENT_SETTLE_MS);
}
void App::updateOpticalCalibration(uint32_t now, bool force) {
if (!opticalCalibrationActive_ ||
now - opticalCalibrationStartedMs_ < OPTICAL_CURRENT_SETTLE_MS) return;
(void)force;
OpticalCurrentMeasurement reading = {};
if (!optical_current_poll(reading)) return;
opticalCalibrationUpdatedMs_ = now;
char current[32], vcc[24];
snprintf(current, sizeof(current), "Idiode: %.1f mA", reading.currentMa);
snprintf(vcc, sizeof(vcc), "Vcc: %.2f V", reading.vccVoltage);
display_.show(current, vcc);
Log::printf("CALIB",
"raw sense=%u vcc=%u | ADC sense=%.3fV vcc=%.3fV | Usense=%.3fV Vcc=%.3fV | Idiode=%.1fmA",
reading.senseRaw, reading.vccRaw, reading.senseAdcVoltage,
reading.vccAdcVoltage, reading.senseVoltage, reading.vccVoltage,
reading.currentMa);
}
void App::leaveOpticalCalibration() {
if (!opticalCalibrationActive_) return;
pwm_.stop();
opticalCalibrationActive_ = false;
Log::event("CALIB", "optical LED OFF; calibration menu left");
}
void App::startTest() {
leaveIdlePowerSave();
pwm_.stop();
@@ -1463,12 +1521,9 @@ bool App::usbHostPresent() const {
}
void App::setStandbyOpticalOutput() {
// A gate driver must never be held enabled while the tester is idle or
// showing a result. DRIVER is SOLO-only, so force real light OFF here.
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD ||
static_cast<Role>(settings_.role) == Role::SLAVE ||
static_cast<TestKind>(settings_.testKind) == TestKind::DRIVER) pwm_.stop();
else pwm_.active();
// Calibration and tests may hold the transmitter active. Idle/result
// screens must always detach PWM and restore the physical light-OFF level.
pwm_.stop();
}
void App::setActivePerformance(bool active) {