APC second test

This reverts commit 4bd84ddf7e.
This commit is contained in:
liquidraver
2026-03-14 21:15:57 +01:00
parent 4bd84ddf7e
commit d794b57e31
8 changed files with 38 additions and 10 deletions
+4 -1
View File
@@ -351,7 +351,7 @@ config ZEPHCORE_LORA_RX_DUTY_CYCLE
config ZEPHCORE_APC
bool "Adaptive Power Control (APC)"
default y
default n
help
Automatically reduce TX power when echo packets from neighbors
indicate excess SNR margin. Saves battery and reduces channel
@@ -361,6 +361,9 @@ config ZEPHCORE_APC
Uses rogue-filtering: clusters echo SNRs to avoid one badly
placed high-SNR neighbor from over-reducing power.
Off by default. Enable with CONFIG_ZEPHCORE_APC=y in board.conf
or via EXTRA_CONF_FILE.
endmenu
menu "GPS Configuration"
+1
View File
@@ -185,6 +185,7 @@ void CompanionMesh::begin()
BaseChatMesh::begin();
#ifdef CONFIG_ZEPHCORE_APC
_power_ctrl.setSF(prefs.sf);
_power_ctrl.setTargetMargin(20); /* companions are mobile — more conservative */
#endif
}
+6
View File
@@ -211,6 +211,12 @@ public:
void setAPCEnabled(bool en) override {
getPowerController().setEnabled(en);
}
uint8_t getAPCTargetMargin() const override {
return getPowerController().getTargetMargin();
}
void setAPCTargetMargin(uint8_t margin_db) override {
getPowerController().setTargetMargin(margin_db);
}
#endif
void handleCommand(uint32_t sender_timestamp, char* command, char* reply);
+3 -2
View File
@@ -178,6 +178,9 @@ should ONLY contain settings that can't be inferred from hardware:
CONFIG_ESPTOOLPY_FLASHSIZE_16MB ESP32 boards with 16MB flash
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM Boards with external PA
CONFIG_ZEPHCORE_MAX_TX_POWER_DBM Boards with external PA
CONFIG_ZEPHCORE_APC Adaptive Power Control — OFF by default.
Reduces TX power when echo SNR shows excess margin.
See apc.md for details on target margin tuning.
AUTO-DETECTED (do NOT set in board.conf):
CONFIG_PWM Auto from DT buzzer nodelabel
@@ -186,8 +189,6 @@ should ONLY contain settings that can't be inferred from hardware:
CONFIG_SPI Auto from ZEPHCORE_RADIO_LR1110
CONFIG_NORDIC_QSPI_NOR Auto from DT nordic,qspi-nor node
CONFIG_ZEPHCORE_LORA_RX_DUTY_CYCLE Auto: ON for companion+SX1262, OFF for repeater/LR1110
CONFIG_ZEPHCORE_APC Adaptive Power Control — ON by default for all boards/roles.
Set to n in board.conf to disable for a specific board.
Config Inheritance
+13 -2
View File
@@ -428,13 +428,16 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
float ff = _callbacks->getFloodDelayFactor();
snprintf(reply, CLI_REPLY_SIZE, "> adaptive (est=%.1f flood=%.2f)",
(double)est, (double)ff);
} else if (memcmp(config, "apc.margin", 10) == 0) {
snprintf(reply, CLI_REPLY_SIZE, "> %d dB", (int)_callbacks->getAPCTargetMargin());
} else if (memcmp(config, "txpower", 7) == 0) {
if (_callbacks->isAPCEnabled()) {
int8_t apc = _callbacks->getAPCReduction();
float margin = _callbacks->getAPCMargin();
int effective = (int)_prefs->tx_power_dbm - (int)apc;
snprintf(reply, CLI_REPLY_SIZE, "> %ddBm (max=%d apc=-%d margin=%.1f)",
effective, (int)_prefs->tx_power_dbm, (int)apc, (double)margin);
snprintf(reply, CLI_REPLY_SIZE, "> %ddBm (max=%d apc=-%d margin=%.1f target=%d)",
effective, (int)_prefs->tx_power_dbm, (int)apc, (double)margin,
(int)_callbacks->getAPCTargetMargin());
} else {
snprintf(reply, CLI_REPLY_SIZE, "> %ddBm (apc=off)",
(int)_prefs->tx_power_dbm);
@@ -669,6 +672,14 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
savePrefs();
strcpy(reply, "OK");
}
} else if (memcmp(config, "apc.margin ", 11) == 0) {
int val = atoi(&config[11]);
if (val >= 6 && val <= 30) {
_callbacks->setAPCTargetMargin((uint8_t)val);
snprintf(reply, CLI_REPLY_SIZE, "OK - APC target margin=%d dB", val);
} else {
strcpy(reply, "Error, range 6-30 dB");
}
} else if (memcmp(config, "tx ", 3) == 0) {
if (memcmp(&config[3], "apc", 3) == 0) {
_callbacks->setAPCEnabled(true);
+2
View File
@@ -57,6 +57,8 @@ public:
virtual float getAPCMargin() const { return 0.0f; }
virtual bool isAPCEnabled() const { return true; }
virtual void setAPCEnabled(bool en) { (void)en; }
virtual uint8_t getAPCTargetMargin() const { return 16; }
virtual void setAPCTargetMargin(uint8_t margin_db) { (void)margin_db; }
// Sensor manager interface (for GPS)
virtual double getNodeLat() const { return 0.0; }
+7 -3
View File
@@ -31,6 +31,11 @@ public:
/* Set current spreading factor (needed for margin calculation). */
void setSF(uint8_t sf) { _sf = sf; }
/* Set target link margin in dB. Higher = more conservative
* (better for networks with poor-RX hardware). Default 16 dB. */
void setTargetMargin(uint8_t margin_db) { _target_margin_x4 = (int)margin_db * 4; }
uint8_t getTargetMargin() const { return (uint8_t)(_target_margin_x4 / 4); }
/* Called when we send or retransmit a flood packet. */
void trackTransmit(uint32_t hash32, uint32_t now_ms);
@@ -69,9 +74,7 @@ private:
static constexpr int8_t MAX_REDUCTION_DB = 12;
static constexpr int8_t MIN_TX_POWER_DBM = -9; /* SX1262 hw min */
static constexpr int CLUSTER_WIDTH_X4 = 24; /* 6 dB in x4 */
/* TARGET_MARGIN: 16 dB above SF threshold.
* For SF8 (threshold -10 dB): reduce at SNR > +7, increase at SNR < +5 */
static constexpr int TARGET_MARGIN_X4 = 64; /* 16 dB * 4 */
static constexpr int DEFAULT_TARGET_MARGIN_X4 = 64; /* 16 dB * 4 */
static constexpr int HYSTERESIS_X4 = 4; /* 1 dB * 4 */
struct Source {
@@ -97,6 +100,7 @@ private:
bool _enabled;
uint8_t _sf;
uint8_t _last_source_count;
int _target_margin_x4;
void finalizeEntry(int idx);
int findEntry(uint32_t hash32) const;
+2 -2
View File
@@ -25,7 +25,7 @@ namespace mesh {
PowerController::PowerController()
: _next_idx(0), _margin_ema_x256(0), _finalized_count(0),
_last_echo_ms(0), _power_reduction_db(0), _enabled(true),
_sf(8), _last_source_count(0)
_sf(8), _last_source_count(0), _target_margin_x4(DEFAULT_TARGET_MARGIN_X4)
{
memset(_ring, 0, sizeof(_ring));
}
@@ -203,7 +203,7 @@ void PowerController::tick(uint32_t now_ms)
if (!isWarmedUp()) return;
int32_t margin_x256 = _margin_ema_x256;
int32_t target_x256 = TARGET_MARGIN_X4 << 6;
int32_t target_x256 = _target_margin_x4 << 6;
int32_t hyst_x256 = HYSTERESIS_X4 << 6;
int8_t old_reduction = _power_reduction_db;