Сделана настройка мощности передающей оптики
This commit is contained in:
@@ -14,6 +14,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
constexpr uint8_t MENU_OPTICAL_CALIBRATION_ITEM = 7;
|
||||||
|
|
||||||
const char *uiFailName(FailReason reason);
|
const char *uiFailName(FailReason reason);
|
||||||
|
|
||||||
const char *appStateName(AppState state) {
|
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);
|
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) {
|
bool parseUnsigned(const char *text, uint32_t &value) {
|
||||||
if (!text || !*text || *text == '-') return false;
|
if (!text || !*text || *text == '-') return false;
|
||||||
char *end = nullptr;
|
char *end = nullptr;
|
||||||
@@ -388,18 +397,25 @@ void App::update() {
|
|||||||
}
|
}
|
||||||
if (state_ == AppState::MENU) {
|
if (state_ == AppState::MENU) {
|
||||||
if (modeEvent == ButtonEvent::SHORT) {
|
if (modeEvent == ButtonEvent::SHORT) {
|
||||||
const uint8_t menuCount = static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD ? 1U : 7U;
|
leaveOpticalCalibration();
|
||||||
menuItem_ = (menuItem_ + 1U) % menuCount; Log::printf("ACTION", "menu item selected index=%u", menuItem_); showMenu();
|
menuItem_ = nextMenuItem(menuItem_,
|
||||||
|
static_cast<TestGroup>(settings_.testGroup));
|
||||||
|
Log::printf("ACTION", "menu item selected index=%u", menuItem_);
|
||||||
|
showMenu();
|
||||||
}
|
}
|
||||||
else if (modeEvent == ButtonEvent::LONG) {
|
else if (modeEvent == ButtonEvent::LONG) {
|
||||||
|
leaveOpticalCalibration();
|
||||||
sanitizeRange(); const bool saved = store_.save(settings_); params_ = store_.params(settings_);
|
sanitizeRange(); const bool saved = store_.save(settings_); params_ = store_.params(settings_);
|
||||||
Log::printf("ACTION", "settings menu saved and closed, NVS=%s", saved ? "OK" : "FAILED");
|
Log::printf("ACTION", "settings menu saved and closed, NVS=%s", saved ? "OK" : "FAILED");
|
||||||
state_ = AppState::IDLE; printConfiguration();
|
state_ = AppState::IDLE; printConfiguration();
|
||||||
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::OPTICS &&
|
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::OPTICS &&
|
||||||
static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
|
static_cast<Role>(settings_.role) == Role::SLAVE) armSlave();
|
||||||
else showIdle();
|
else showIdle();
|
||||||
} else if (startEvent == ButtonEvent::SHORT) changeMenu(+1);
|
} else if (menuItem_ != MENU_OPTICAL_CALIBRATION_ITEM &&
|
||||||
else if (startEvent == ButtonEvent::LONG || startEvent == ButtonEvent::REPEAT) changeMenu(-1);
|
startEvent == ButtonEvent::SHORT) changeMenu(+1);
|
||||||
|
else if (menuItem_ != MENU_OPTICAL_CALIBRATION_ITEM &&
|
||||||
|
(startEvent == ButtonEvent::LONG || startEvent == ButtonEvent::REPEAT)) changeMenu(-1);
|
||||||
|
updateOpticalCalibration(now);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (state_ == AppState::SOLO_MEASURE) {
|
if (state_ == AppState::SOLO_MEASURE) {
|
||||||
@@ -544,6 +560,7 @@ bool App::serialSettingsMutable() const {
|
|||||||
|
|
||||||
void App::finishSerialSettingsChange() {
|
void App::finishSerialSettingsChange() {
|
||||||
if (state_ == AppState::SLAVE_READY) radio_.end();
|
if (state_ == AppState::SLAVE_READY) radio_.end();
|
||||||
|
leaveOpticalCalibration();
|
||||||
state_ = AppState::IDLE;
|
state_ = AppState::IDLE;
|
||||||
sanitizeRange();
|
sanitizeRange();
|
||||||
params_ = store_.params(settings_);
|
params_ = store_.params(settings_);
|
||||||
@@ -589,6 +606,7 @@ void App::handleSerialCommand(char *line) {
|
|||||||
Serial.println("OK board test stopped");
|
Serial.println("OK board test stopped");
|
||||||
stopBoardTest();
|
stopBoardTest();
|
||||||
} else if (state_ == AppState::MENU) {
|
} else if (state_ == AppState::MENU) {
|
||||||
|
leaveOpticalCalibration();
|
||||||
state_ = AppState::IDLE; showIdle(); Serial.println("OK menu closed");
|
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 if (state_ == AppState::SLAVE_READY) Serial.println("OK slave is armed; no test is running");
|
||||||
else {
|
else {
|
||||||
@@ -823,6 +841,9 @@ void App::showMenu() {
|
|||||||
display_.show(one, total);
|
display_.show(one, total);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case MENU_OPTICAL_CALIBRATION_ITEM:
|
||||||
|
enterOpticalCalibration(millis());
|
||||||
|
return;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
formatMenuLine(label, value, one, sizeof(one));
|
formatMenuLine(label, value, one, sizeof(one));
|
||||||
@@ -833,6 +854,43 @@ void App::showMenu() {
|
|||||||
display_.show(one, total);
|
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() {
|
void App::startTest() {
|
||||||
leaveIdlePowerSave();
|
leaveIdlePowerSave();
|
||||||
pwm_.stop();
|
pwm_.stop();
|
||||||
@@ -1463,12 +1521,9 @@ bool App::usbHostPresent() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void App::setStandbyOpticalOutput() {
|
void App::setStandbyOpticalOutput() {
|
||||||
// A gate driver must never be held enabled while the tester is idle or
|
// Calibration and tests may hold the transmitter active. Idle/result
|
||||||
// showing a result. DRIVER is SOLO-only, so force real light OFF here.
|
// screens must always detach PWM and restore the physical light-OFF level.
|
||||||
if (static_cast<TestGroup>(settings_.testGroup) == TestGroup::BOARD ||
|
pwm_.stop();
|
||||||
static_cast<Role>(settings_.role) == Role::SLAVE ||
|
|
||||||
static_cast<TestKind>(settings_.testKind) == TestKind::DRIVER) pwm_.stop();
|
|
||||||
else pwm_.active();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::setActivePerformance(bool active) {
|
void App::setActivePerformance(bool active) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "Display.h"
|
#include "Display.h"
|
||||||
#include "DriverTest.h"
|
#include "DriverTest.h"
|
||||||
#include "Measurement.h"
|
#include "Measurement.h"
|
||||||
|
#include "OpticalCurrent.h"
|
||||||
#include "Pwm.h"
|
#include "Pwm.h"
|
||||||
#include "Radio.h"
|
#include "Radio.h"
|
||||||
#include "SettingsStore.h"
|
#include "SettingsStore.h"
|
||||||
@@ -23,6 +24,9 @@ class App {
|
|||||||
void finishInitialization(bool factoryReset);
|
void finishInitialization(bool factoryReset);
|
||||||
void showMenu();
|
void showMenu();
|
||||||
void changeMenu(int direction);
|
void changeMenu(int direction);
|
||||||
|
void enterOpticalCalibration(uint32_t now);
|
||||||
|
void updateOpticalCalibration(uint32_t now, bool force = false);
|
||||||
|
void leaveOpticalCalibration();
|
||||||
void cycleRunMode();
|
void cycleRunMode();
|
||||||
void sanitizeRange();
|
void sanitizeRange();
|
||||||
void startTest();
|
void startTest();
|
||||||
@@ -105,6 +109,9 @@ class App {
|
|||||||
uint32_t boardTestUpdatedMs_ = 0;
|
uint32_t boardTestUpdatedMs_ = 0;
|
||||||
uint32_t boardDisplayUpdatedMs_ = 0;
|
uint32_t boardDisplayUpdatedMs_ = 0;
|
||||||
bool boardPwmLightOn_ = false;
|
bool boardPwmLightOn_ = false;
|
||||||
|
bool opticalCalibrationActive_ = false;
|
||||||
|
uint32_t opticalCalibrationStartedMs_ = 0;
|
||||||
|
uint32_t opticalCalibrationUpdatedMs_ = 0;
|
||||||
mutable uint32_t lastUsbHostSeenMs_ = 0;
|
mutable uint32_t lastUsbHostSeenMs_ = 0;
|
||||||
char serialLine_[96] = {};
|
char serialLine_[96] = {};
|
||||||
uint8_t serialLineLength_ = 0;
|
uint8_t serialLineLength_ = 0;
|
||||||
|
|||||||
@@ -5,13 +5,15 @@
|
|||||||
// ------------------------- Hardware configuration -------------------------
|
// ------------------------- Hardware configuration -------------------------
|
||||||
// Enabled for the hand-wired prototype. Comment out for the production PCB.
|
// Enabled for the hand-wired prototype. Comment out for the production PCB.
|
||||||
// Both profiles map S3 signals by physical header position with 5V/GND aligned.
|
// Both profiles map S3 signals by physical header position with 5V/GND aligned.
|
||||||
//#define MAKETKA
|
#define MAKETKA
|
||||||
|
|
||||||
// Select exactly one populated receiver circuit. Use
|
// Select exactly one populated receiver circuit. Use
|
||||||
// BOARD_RX_INTERFACE_DIGITAL for MAKETKA and boards fitted with GPIO_RX.
|
// BOARD_RX_INTERFACE_DIGITAL for MAKETKA and boards fitted with GPIO_RX.
|
||||||
#define BOARD_RX_INTERFACE_ADC 1
|
#define BOARD_RX_INTERFACE_ADC 1
|
||||||
#define BOARD_RX_INTERFACE_DIGITAL 2
|
#define BOARD_RX_INTERFACE_DIGITAL 2
|
||||||
#define BOARD_RX_INTERFACE BOARD_RX_INTERFACE_ADC
|
#ifndef BOARD_RX_INTERFACE
|
||||||
|
#define BOARD_RX_INTERFACE BOARD_RX_INTERFACE_DIGITAL
|
||||||
|
#endif
|
||||||
|
|
||||||
#if BOARD_RX_INTERFACE != BOARD_RX_INTERFACE_ADC && \
|
#if BOARD_RX_INTERFACE != BOARD_RX_INTERFACE_ADC && \
|
||||||
BOARD_RX_INTERFACE != BOARD_RX_INTERFACE_DIGITAL
|
BOARD_RX_INTERFACE != BOARD_RX_INTERFACE_DIGITAL
|
||||||
@@ -38,12 +40,16 @@ constexpr uint8_t GPIO_RX = 4;
|
|||||||
constexpr bool BOARD_ADC_AVAILABLE = false;
|
constexpr bool BOARD_ADC_AVAILABLE = false;
|
||||||
constexpr uint8_t GPIO_BUTTON_MODE = 0;
|
constexpr uint8_t GPIO_BUTTON_MODE = 0;
|
||||||
constexpr uint8_t GPIO_BUTTON_START = 1;
|
constexpr uint8_t GPIO_BUTTON_START = 1;
|
||||||
|
constexpr uint8_t GPIO_OPTICAL_CURRENT = 2;
|
||||||
|
constexpr uint8_t GPIO_OPTICAL_VCC = 5;
|
||||||
constexpr uint8_t GPIO_VBAT = UINT8_MAX;
|
constexpr uint8_t GPIO_VBAT = UINT8_MAX;
|
||||||
constexpr uint8_t GPIO_ANALOG_RX = UINT8_MAX;
|
constexpr uint8_t GPIO_ANALOG_RX = UINT8_MAX;
|
||||||
#else
|
#else
|
||||||
constexpr bool BOARD_ADC_AVAILABLE = true;
|
constexpr bool BOARD_ADC_AVAILABLE = true;
|
||||||
constexpr uint8_t GPIO_BUTTON_MODE = 20;
|
constexpr uint8_t GPIO_BUTTON_MODE = 20;
|
||||||
constexpr uint8_t GPIO_BUTTON_START = 10;
|
constexpr uint8_t GPIO_BUTTON_START = 10;
|
||||||
|
constexpr uint8_t GPIO_OPTICAL_CURRENT = 1;
|
||||||
|
constexpr uint8_t GPIO_OPTICAL_VCC = 5;
|
||||||
constexpr uint8_t GPIO_VBAT = 2;
|
constexpr uint8_t GPIO_VBAT = 2;
|
||||||
constexpr uint8_t GPIO_ANALOG_RX = 0;
|
constexpr uint8_t GPIO_ANALOG_RX = 0;
|
||||||
#endif
|
#endif
|
||||||
@@ -58,6 +64,8 @@ constexpr uint8_t GPIO_PWM = 12;
|
|||||||
constexpr uint8_t GPIO_RX = 13;
|
constexpr uint8_t GPIO_RX = 13;
|
||||||
constexpr uint8_t GPIO_BUTTON_MODE = 9;
|
constexpr uint8_t GPIO_BUTTON_MODE = 9;
|
||||||
constexpr uint8_t GPIO_BUTTON_START = 10;
|
constexpr uint8_t GPIO_BUTTON_START = 10;
|
||||||
|
constexpr uint8_t GPIO_OPTICAL_CURRENT = 2;
|
||||||
|
constexpr uint8_t GPIO_OPTICAL_VCC = 6;
|
||||||
constexpr uint8_t GPIO_SDA = 44;
|
constexpr uint8_t GPIO_SDA = 44;
|
||||||
constexpr uint8_t GPIO_SCL = 1;
|
constexpr uint8_t GPIO_SCL = 1;
|
||||||
constexpr uint8_t GPIO_VBAT = UINT8_MAX;
|
constexpr uint8_t GPIO_VBAT = UINT8_MAX;
|
||||||
@@ -70,6 +78,8 @@ constexpr uint8_t GPIO_PWM = 12;
|
|||||||
constexpr uint8_t GPIO_RX = 13;
|
constexpr uint8_t GPIO_RX = 13;
|
||||||
constexpr uint8_t GPIO_BUTTON_MODE = 5;
|
constexpr uint8_t GPIO_BUTTON_MODE = 5;
|
||||||
constexpr uint8_t GPIO_BUTTON_START = 4;
|
constexpr uint8_t GPIO_BUTTON_START = 4;
|
||||||
|
constexpr uint8_t GPIO_OPTICAL_CURRENT = 10;
|
||||||
|
constexpr uint8_t GPIO_OPTICAL_VCC = 6;
|
||||||
constexpr uint8_t GPIO_SDA = 44;
|
constexpr uint8_t GPIO_SDA = 44;
|
||||||
constexpr uint8_t GPIO_SCL = 1;
|
constexpr uint8_t GPIO_SCL = 1;
|
||||||
constexpr uint8_t GPIO_VBAT = 11;
|
constexpr uint8_t GPIO_VBAT = 11;
|
||||||
@@ -79,6 +89,22 @@ constexpr uint8_t GPIO_ANALOG_RX = 9;
|
|||||||
#error "Only ESP32-C3 and ESP32-S3 are supported"
|
#error "Only ESP32-C3 and ESP32-S3 are supported"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static_assert(GPIO_OPTICAL_CURRENT != GPIO_PWM &&
|
||||||
|
GPIO_OPTICAL_CURRENT != GPIO_RX &&
|
||||||
|
GPIO_OPTICAL_CURRENT != GPIO_BUTTON_MODE &&
|
||||||
|
GPIO_OPTICAL_CURRENT != GPIO_BUTTON_START &&
|
||||||
|
GPIO_OPTICAL_CURRENT != GPIO_SDA &&
|
||||||
|
GPIO_OPTICAL_CURRENT != GPIO_SCL,
|
||||||
|
"Optical-current ADC GPIO conflicts with another board signal");
|
||||||
|
static_assert(GPIO_OPTICAL_VCC != GPIO_OPTICAL_CURRENT &&
|
||||||
|
GPIO_OPTICAL_VCC != GPIO_PWM &&
|
||||||
|
GPIO_OPTICAL_VCC != GPIO_RX &&
|
||||||
|
GPIO_OPTICAL_VCC != GPIO_BUTTON_MODE &&
|
||||||
|
GPIO_OPTICAL_VCC != GPIO_BUTTON_START &&
|
||||||
|
GPIO_OPTICAL_VCC != GPIO_SDA &&
|
||||||
|
GPIO_OPTICAL_VCC != GPIO_SCL,
|
||||||
|
"Optical-VCC ADC GPIO conflicts with another board signal");
|
||||||
|
|
||||||
constexpr uint8_t OLED_ROTATION = 0;
|
constexpr uint8_t OLED_ROTATION = 0;
|
||||||
|
|
||||||
constexpr uint8_t OLED_ADDRESS = 0x3C;
|
constexpr uint8_t OLED_ADDRESS = 0x3C;
|
||||||
@@ -89,6 +115,11 @@ constexpr uint32_t SERIAL_BAUD = 115200;
|
|||||||
constexpr uint32_t SERIAL_TX_TIMEOUT_MS = 2;
|
constexpr uint32_t SERIAL_TX_TIMEOUT_MS = 2;
|
||||||
constexpr uint32_t BOARD_ADC_PRINT_INTERVAL_MS = 100;
|
constexpr uint32_t BOARD_ADC_PRINT_INTERVAL_MS = 100;
|
||||||
constexpr uint32_t BOARD_TEST_DISPLAY_INTERVAL_MS = 250;
|
constexpr uint32_t BOARD_TEST_DISPLAY_INTERVAL_MS = 250;
|
||||||
|
constexpr float OPTICAL_VCC = 5.1f;
|
||||||
|
constexpr float OPTICAL_SENSE_R = 47.0f;
|
||||||
|
constexpr float OPTICAL_DIVIDER_RATIO = 2.0f;
|
||||||
|
constexpr uint32_t OPTICAL_CURRENT_SETTLE_MS = 20;
|
||||||
|
constexpr uint32_t OPTICAL_CURRENT_AVERAGING_MS = 200;
|
||||||
constexpr bool SERIAL_ACTION_LOG = true;
|
constexpr bool SERIAL_ACTION_LOG = true;
|
||||||
constexpr bool SERIAL_LOG_TIMESTAMPS = true;
|
constexpr bool SERIAL_LOG_TIMESTAMPS = true;
|
||||||
constexpr bool SERIAL_MINIMAL_LOG = true;
|
constexpr bool SERIAL_MINIMAL_LOG = true;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ constexpr const char *MENU_MIN_PULSE = "МИН. ИМПУЛЬС:";
|
|||||||
constexpr const char *MENU_ACCURACY = "ТОЧНОСТЬ:";
|
constexpr const char *MENU_ACCURACY = "ТОЧНОСТЬ:";
|
||||||
constexpr const char *MENU_TEST_TIME = "ВРЕМЯ ВЫБОРКИ:";
|
constexpr const char *MENU_TEST_TIME = "ВРЕМЯ ВЫБОРКИ:";
|
||||||
constexpr const char *MENU_LIGHT_CODE = "АКТ. УРОВЕНЬ:";
|
constexpr const char *MENU_LIGHT_CODE = "АКТ. УРОВЕНЬ:";
|
||||||
|
constexpr const char *MENU_OPTICAL_CALIBRATION = "КАЛИБР. ОПТИКИ";
|
||||||
constexpr const char *LIGHT_CODE_FORMAT = "TX:%c, RX:%c";
|
constexpr const char *LIGHT_CODE_FORMAT = "TX:%c, RX:%c";
|
||||||
constexpr const char *LIGHT_AUTO = "АВТО";
|
constexpr const char *LIGHT_AUTO = "АВТО";
|
||||||
constexpr const char *LIGHT_AUTO_FORMAT = "TX/RX: АВТО";
|
constexpr const char *LIGHT_AUTO_FORMAT = "TX/RX: АВТО";
|
||||||
@@ -136,6 +137,7 @@ constexpr const char *MENU_MIN_PULSE = "MIN PULSE:";
|
|||||||
constexpr const char *MENU_ACCURACY = "ACCURACY:";
|
constexpr const char *MENU_ACCURACY = "ACCURACY:";
|
||||||
constexpr const char *MENU_TEST_TIME = "TEST TIME:";
|
constexpr const char *MENU_TEST_TIME = "TEST TIME:";
|
||||||
constexpr const char *MENU_LIGHT_CODE = "ACTIVE LEVEL:";
|
constexpr const char *MENU_LIGHT_CODE = "ACTIVE LEVEL:";
|
||||||
|
constexpr const char *MENU_OPTICAL_CALIBRATION = "OPTICAL CALIBRATION";
|
||||||
constexpr const char *LIGHT_CODE_FORMAT = "TX:%c, RX:%c";
|
constexpr const char *LIGHT_CODE_FORMAT = "TX:%c, RX:%c";
|
||||||
constexpr const char *LIGHT_AUTO = "AUTO";
|
constexpr const char *LIGHT_AUTO = "AUTO";
|
||||||
constexpr const char *LIGHT_AUTO_FORMAT = "TX/RX: AUTO";
|
constexpr const char *LIGHT_AUTO_FORMAT = "TX/RX: AUTO";
|
||||||
|
|||||||
74
OpticalChannelTester/OpticalCurrent.cpp
Normal file
74
OpticalChannelTester/OpticalCurrent.cpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include "OpticalCurrent.h"
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct AdcAccumulator {
|
||||||
|
uint64_t senseRaw = 0;
|
||||||
|
uint64_t vccRaw = 0;
|
||||||
|
uint64_t senseMillivolts = 0;
|
||||||
|
uint64_t vccMillivolts = 0;
|
||||||
|
uint32_t samples = 0;
|
||||||
|
uint32_t startedMs = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
AdcAccumulator accumulator;
|
||||||
|
|
||||||
|
void resetAccumulator(uint32_t now) {
|
||||||
|
accumulator = {};
|
||||||
|
accumulator.startedMs = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpticalCurrentMeasurement finishMeasurement() {
|
||||||
|
const float senseAdcVoltage =
|
||||||
|
accumulator.senseMillivolts / (1000.0f * accumulator.samples);
|
||||||
|
const float vccAdcVoltage =
|
||||||
|
accumulator.vccMillivolts / (1000.0f * accumulator.samples);
|
||||||
|
const float senseVoltage = senseAdcVoltage * OPTICAL_DIVIDER_RATIO;
|
||||||
|
const float vccVoltage = vccAdcVoltage * OPTICAL_DIVIDER_RATIO;
|
||||||
|
const float resistorVoltage = vccVoltage - senseVoltage;
|
||||||
|
const float currentMa = resistorVoltage * 1000.0f / OPTICAL_SENSE_R;
|
||||||
|
return {
|
||||||
|
static_cast<uint16_t>(accumulator.senseRaw / accumulator.samples),
|
||||||
|
static_cast<uint16_t>(accumulator.vccRaw / accumulator.samples),
|
||||||
|
senseAdcVoltage, vccAdcVoltage, senseVoltage, vccVoltage,
|
||||||
|
currentMa > 0.0f ? currentMa : 0.0f
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void optical_current_begin(void) {
|
||||||
|
analogReadResolution(12);
|
||||||
|
pinMode(GPIO_OPTICAL_CURRENT, INPUT);
|
||||||
|
pinMode(GPIO_OPTICAL_VCC, INPUT);
|
||||||
|
// Both 10k/10k dividers can present about 2.5 V to their ADC inputs.
|
||||||
|
analogSetPinAttenuation(GPIO_OPTICAL_CURRENT, ADC_11db);
|
||||||
|
analogSetPinAttenuation(GPIO_OPTICAL_VCC, ADC_11db);
|
||||||
|
resetAccumulator(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool optical_current_poll(OpticalCurrentMeasurement &measurement) {
|
||||||
|
const uint32_t now = millis();
|
||||||
|
if (!accumulator.startedMs) resetAccumulator(now ? now : 1U);
|
||||||
|
|
||||||
|
accumulator.senseRaw += analogRead(GPIO_OPTICAL_CURRENT);
|
||||||
|
accumulator.senseMillivolts += analogReadMilliVolts(GPIO_OPTICAL_CURRENT);
|
||||||
|
accumulator.vccRaw += analogRead(GPIO_OPTICAL_VCC);
|
||||||
|
accumulator.vccMillivolts += analogReadMilliVolts(GPIO_OPTICAL_VCC);
|
||||||
|
++accumulator.samples;
|
||||||
|
|
||||||
|
if (now - accumulator.startedMs < OPTICAL_CURRENT_AVERAGING_MS) return false;
|
||||||
|
measurement = finishMeasurement();
|
||||||
|
resetAccumulator(now);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpticalCurrentMeasurement optical_get_led_measurement(void) {
|
||||||
|
OpticalCurrentMeasurement measurement = {};
|
||||||
|
resetAccumulator(millis());
|
||||||
|
while (!optical_current_poll(measurement)) delay(1);
|
||||||
|
return measurement;
|
||||||
|
}
|
||||||
|
|
||||||
|
float optical_get_led_current_ma(void) {
|
||||||
|
return optical_get_led_measurement().currentMa;
|
||||||
|
}
|
||||||
18
OpticalChannelTester/OpticalCurrent.h
Normal file
18
OpticalChannelTester/OpticalCurrent.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct OpticalCurrentMeasurement {
|
||||||
|
uint16_t senseRaw;
|
||||||
|
uint16_t vccRaw;
|
||||||
|
float senseAdcVoltage;
|
||||||
|
float vccAdcVoltage;
|
||||||
|
float senseVoltage;
|
||||||
|
float vccVoltage;
|
||||||
|
float currentMa;
|
||||||
|
};
|
||||||
|
|
||||||
|
void optical_current_begin(void);
|
||||||
|
bool optical_current_poll(OpticalCurrentMeasurement &measurement);
|
||||||
|
OpticalCurrentMeasurement optical_get_led_measurement(void);
|
||||||
|
float optical_get_led_current_ma(void);
|
||||||
Reference in New Issue
Block a user