From cb8a7ebbd958651acad36f0aba8c8cecbd0d789b Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Thu, 24 Jul 2025 09:24:56 -0400 Subject: [PATCH 01/13] Fix references to old fusion source files --- targets/aat.ini | 2 +- targets/common.ini | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/targets/aat.ini b/targets/aat.ini index 283e5d01..8e51b153 100644 --- a/targets/aat.ini +++ b/targets/aat.ini @@ -21,7 +21,7 @@ build_flags = lib_deps = ${env.lib_deps} adafruit/Adafruit SSD1306 @ 2.5.9 -build_src_filter = ${common_env_data.build_src_filter} - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - - [env:AAT_ESP_Backpack_via_WIFI] extends = env:AAT_ESP_Backpack_via_UART diff --git a/targets/common.ini b/targets/common.ini index c8b200bd..6744b795 100644 --- a/targets/common.ini +++ b/targets/common.ini @@ -90,7 +90,7 @@ build_src_filter = - - - - - + - - - - @@ -110,7 +110,7 @@ build_src_filter = ; - - - - - + - - - - @@ -130,7 +130,7 @@ build_src_filter = - ; - - - - + - - - - @@ -150,7 +150,7 @@ build_src_filter = - - ; - - - + - - - - @@ -170,7 +170,7 @@ build_src_filter = - - - - ; - + ; - - - - @@ -190,7 +190,7 @@ build_src_filter = - - - - - + - ; - - - @@ -210,7 +210,7 @@ build_src_filter = - - - - - + - - ; - - @@ -230,7 +230,7 @@ build_src_filter = - - - - - + - - - ; - @@ -249,7 +249,7 @@ build_src_filter = - - - - - + - - - - @@ -269,7 +269,7 @@ build_src_filter = - - - - - + - - - - From 2e13ebb37740c3ac348286dd99b70a24c08673b0 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Thu, 24 Jul 2025 15:10:17 -0400 Subject: [PATCH 02/13] Add Vrx Pedal type module --- lib/BUTTON/button.h | 2 + platformio.ini | 1 + src/Vrx_main.cpp | 15 +++++- src/module_pedal.cpp | 114 +++++++++++++++++++++++++++++++++++++++++++ src/module_pedal.h | 41 ++++++++++++++++ targets/common.ini | 3 +- targets/pedal.ini | 34 +++++++++++++ 7 files changed, 207 insertions(+), 3 deletions(-) create mode 100644 src/module_pedal.cpp create mode 100644 src/module_pedal.h create mode 100644 targets/pedal.ini diff --git a/lib/BUTTON/button.h b/lib/BUTTON/button.h index a8d3b1de..cb5c0a45 100644 --- a/lib/BUTTON/button.h +++ b/lib/BUTTON/button.h @@ -30,6 +30,8 @@ class Button // Properties uint8_t getCount() const { return _pressCount; } uint8_t getLongCount() const { return _longCount; } + bool isPressed() const { return _state == STATE_HELD; } + bool isIdle() const { return _state == STATE_IDLE; } Button() : _lastCheck(0), _lastFallingEdge(0), _state(STATE_IDLE), diff --git a/platformio.ini b/platformio.ini index 7bad0d8b..396cbdf3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,6 +12,7 @@ extra_configs = targets/fusion.ini targets/hdzero.ini targets/orqa.ini + targets/pedal.ini targets/rapidfire.ini targets/rx5808.ini targets/skyzone.ini diff --git a/src/Vrx_main.cpp b/src/Vrx_main.cpp index e9921275..2997e77c 100644 --- a/src/Vrx_main.cpp +++ b/src/Vrx_main.cpp @@ -23,7 +23,9 @@ #include "devWIFI.h" #include "devButton.h" #include "devLED.h" +#if defined(HAS_HEADTRACKING) #include "devHeadTracker.h" +#endif #ifdef RAPIDFIRE_BACKPACK #include "rapidfire.h" @@ -43,6 +45,8 @@ #include "module_aat.h" #elif defined(CROSSBOW_BACKPACK) #include "mfd_crossbow.h" +#elif defined(PEDAL_BACKPACK) + #include "module_pedal.h" #endif /////////// DEFINES /////////// @@ -124,6 +128,8 @@ VrxBackpackConfig config; AatModule vrxModule(Serial); #elif defined(CROSSBOW_BACKPACK) MFDCrossbow vrxModule(&Serial); +#elif defined(PEDAL_BACKPACK) + PedalModule vrxModule; #endif /////////// FUNCTION DEFS /////////// @@ -341,7 +347,7 @@ void SetSoftMACAddress() void RequestVTXPacket() { -#if !defined(AAT_BACKPACK) and !defined(CROSSBOW_BACKPACK) +#if !defined(AAT_BACKPACK) && !defined(CROSSBOW_BACKPACK) && !defined(PEDAL_BACKPACK) mspPacket_t packet; packet.reset(); packet.makeCommand(); @@ -370,7 +376,12 @@ void sendMSPViaEspnow(mspPacket_t *packet) return; } - esp_now_send(firmwareOptions.uid, (uint8_t *) &nowDataOutput, packetSize); + esp_err_t err = esp_now_send(firmwareOptions.uid, (uint8_t *) &nowDataOutput, packetSize); + if (err != ESP_OK) + { + DBGLN("ESPNOW err=%u", err); + } + } void resetBootCounter() diff --git a/src/module_pedal.cpp b/src/module_pedal.cpp new file mode 100644 index 00000000..541c59fb --- /dev/null +++ b/src/module_pedal.cpp @@ -0,0 +1,114 @@ +#if defined(PEDAL_BACKPACK) + +#include "module_pedal.h" +#include "common.h" +#include "msptypes.h" + +void sendMSPViaEspnow(mspPacket_t *packet); +bool BindingExpired(uint32_t now); + +PedalModule *PedalModule::instance = nullptr; + +PedalModule::PedalModule() + : _pedalEventFired(false), _lastTxValue(false), _lastTxMs(0), _lastPedalChangeMs(0) +{ + PedalModule::instance = this; + _pedal.OnShortPress = std::bind(&PedalModule::button_OnShortPress, this); + _pedal.OnLongPress = std::bind(&PedalModule::button_OnLongPress, this); +} + +void PedalModule::Init() +{ + _pedalSemaphore = xSemaphoreCreateBinary(); + attachInterrupt(PIN_PEDAL_BUTTON, &PedalModule::button_interrupt, CHANGE); +} + +void PedalModule::Loop(uint32_t now) +{ + if (BindingExpired(now)) + { + connectionState = running; + } + + // Pause here to lower power usage (C3 drops from 100mA to 90mA) + // If button is currently transitioning or pressed just consume the semaphore, else delay until an interrupt + xSemaphoreTake(_pedalSemaphore, _pedal.isIdle() ? pdMS_TO_TICKS(20) : 0); + _pedal.update(); + + // Don't TX if binding/wifi + if (connectionState != running) + return; + // Don't TX on startup + if (_lastTxMs == 0 && now < STARTUP_MS) + return; + + checkSendPedalPos(now); +} + +void PedalModule::checkSendPedalPos(uint32_t now) +{ + bool pedalPressed = _pedalEventFired || _pedal.isPressed(); + bool pedalChanged = pedalPressed != _lastTxValue; + _pedalEventFired = false; + + if (pedalChanged) + { + _lastPedalChangeMs = now; + } + + // Send the pedal position frequently after last change, until it is unchanged for one UNCHANGED_MS interval + uint32_t txIntervalMs = (now - _lastPedalChangeMs < PEDAL_INTERVAL_UNCHANGED_MS) ? PEDAL_INTERVAL_CHANGED_MS : PEDAL_INTERVAL_UNCHANGED_MS; + if (pedalChanged || now - _lastTxMs > txIntervalMs) + { + _lastTxMs = now; + _lastTxValue = pedalPressed; + DBGLN("%u pedal %u", now, pedalPressed); + + // Pedal is 1000us if not pressed, 2000us if pressed + uint16_t pedalState = pedalPressed ? CRSF_CHANNEL_VALUE_2000 : CRSF_CHANNEL_VALUE_1000; + mspPacket_t packet; + packet.reset(); + packet.makeCommand(); + packet.function = MSP_ELRS_BACKPACK_SET_PTR; + packet.addByte(pedalState & 0xFF); // CH0 + packet.addByte(pedalState >> 8); + packet.addByte(0); // CH1 + packet.addByte(0); + packet.addByte(0); // CH2 + packet.addByte(0); + sendMSPViaEspnow(&packet); + } +} + +void IRAM_ATTR PedalModule::button_interrupt() +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(PedalModule::instance->_pedalSemaphore, &xHigherPriorityTaskWoken); + // No need to if (xHigherPriorityTaskWoken) portYIELD_FROM_ISR(), just let the loop break +} + +void PedalModule::button_OnShortPress() +{ + _pedalEventFired = true; + DBGLN("Short %u", _pedal.getCount()); +} + +void PedalModule::button_OnLongPress() +{ + _pedalEventFired = true; + DBGLN("Long %u", _pedal.getLongCount()); + + // Long press of the pedal for 5s takes the pedal into binding mode + if (_pedal.getLongCount() >= 10 && connectionState == running) + { + bindingStart = millis(); + connectionState = binding; + } + // Long press of pedal for 10s goes from binding to wifi + else if (_pedal.getLongCount() >= 20 && connectionState == binding) + { + connectionState = wifiUpdate; + } +} + +#endif /* PEDAL_BACKPACK */ \ No newline at end of file diff --git a/src/module_pedal.h b/src/module_pedal.h new file mode 100644 index 00000000..b2828b8e --- /dev/null +++ b/src/module_pedal.h @@ -0,0 +1,41 @@ +#pragma once + +#if defined(PEDAL_BACKPACK) +#include "module_base.h" +#include "logging.h" +#include "button.h" + +// For wake +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +class PedalModule : public ModuleBase +{ +public: + PedalModule(); + + void Init(); + void Loop(uint32_t now); +private: + static PedalModule *instance; + static void button_interrupt(); + + // Don't send updates on for a short time after bootup + static constexpr uint32_t STARTUP_MS = 2000U; + // Transmit interval differs based on how recently the pedal changed position + static constexpr uint32_t PEDAL_INTERVAL_UNCHANGED_MS = 1000U; + static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = 100U; + + void button_OnShortPress(); + void button_OnLongPress(); + void checkSendPedalPos(uint32_t now); + + Button _pedal; + SemaphoreHandle_t _pedalSemaphore; + bool _pedalEventFired; + bool _lastTxValue; + uint32_t _lastTxMs; + uint32_t _lastPedalChangeMs; +}; + +#endif /* PEDAL_BACKPACK */ \ No newline at end of file diff --git a/targets/common.ini b/targets/common.ini index 6744b795..5c9e699a 100644 --- a/targets/common.ini +++ b/targets/common.ini @@ -10,7 +10,6 @@ lib_deps = ottowinter/ESPAsyncWebServer-esphome @ 3.2.2 esphome/AsyncTCP-esphome @ 2.1.3 # use specific version - an update to this library breaks the build bblanchon/ArduinoJson @ 7.1.0 -monitor_filters = esp8266_exception_decoder [common_env_data] @@ -26,6 +25,7 @@ board_build.ldscript = eagle.flash.1m.ld upload_speed = 460800 monitor_speed = 460800 board_build.f_cpu = 160000000L +monitor_filters = esp8266_exception_decoder build_flags = -D PLATFORM_ESP8266=1 @@ -36,6 +36,7 @@ board_build.ldscript = eagle.flash.1m.ld upload_speed = 921600 monitor_speed = 460800 board_build.f_cpu = 160000000L +monitor_filters = esp8266_exception_decoder build_flags = -D PLATFORM_ESP8266=1 diff --git a/targets/pedal.ini b/targets/pedal.ini new file mode 100644 index 00000000..a0754718 --- /dev/null +++ b/targets/pedal.ini @@ -0,0 +1,34 @@ +# ******************************** +# Pedal VRX backpack -- External pedal trigger using headtracking messages +# ******************************** + +[pedal_backpack_common] +build_flags = + ${common_env_data.build_flags} + -D TARGET_VRX_BACKPACK + -D PEDAL_BACKPACK + -D ARDUINO_USB_CDC_ON_BOOT=1 + ;-DDEBUG_LOG -DDEBUG_LOG_VERBOSE +build_src_filter = + ${common_env_data.build_src_filter} + - + ; - + - + - + - + - + - + - + - + - + - + - + +[env:Pedal_ESP32C3_Backpack_via_UART] +extends = env_common_esp32c3, pedal_backpack_common +board_build.f_cpu = 80000000L +build_flags = + ${env_common_esp32c3.build_flags} + ${pedal_backpack_common.build_flags} + -D PIN_LED=8 + -D PIN_PEDAL_BUTTON=9 From c80f53fe4066e23c2cd5f2e19c56f52fda11f27c Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 25 Jul 2025 11:29:38 -0400 Subject: [PATCH 03/13] Lower TX intervals, correct pedalchanged event, yield from ISR --- src/module_pedal.cpp | 24 ++++++++++++------------ src/module_pedal.h | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/module_pedal.cpp b/src/module_pedal.cpp index 541c59fb..c4e15c73 100644 --- a/src/module_pedal.cpp +++ b/src/module_pedal.cpp @@ -7,20 +7,22 @@ void sendMSPViaEspnow(mspPacket_t *packet); bool BindingExpired(uint32_t now); -PedalModule *PedalModule::instance = nullptr; - PedalModule::PedalModule() : _pedalEventFired(false), _lastTxValue(false), _lastTxMs(0), _lastPedalChangeMs(0) { - PedalModule::instance = this; _pedal.OnShortPress = std::bind(&PedalModule::button_OnShortPress, this); _pedal.OnLongPress = std::bind(&PedalModule::button_OnLongPress, this); } +PedalModule::~PedalModule() +{ + detachInterrupt(PIN_PEDAL_BUTTON); +} + void PedalModule::Init() { _pedalSemaphore = xSemaphoreCreateBinary(); - attachInterrupt(PIN_PEDAL_BUTTON, &PedalModule::button_interrupt, CHANGE); + attachInterruptArg(PIN_PEDAL_BUTTON, &PedalModule::button_interrupt, this, CHANGE); } void PedalModule::Loop(uint32_t now) @@ -47,8 +49,8 @@ void PedalModule::Loop(uint32_t now) void PedalModule::checkSendPedalPos(uint32_t now) { - bool pedalPressed = _pedalEventFired || _pedal.isPressed(); - bool pedalChanged = pedalPressed != _lastTxValue; + bool pedalPressed = _pedal.isPressed(); + bool pedalChanged = _pedalEventFired || pedalPressed != _lastTxValue; _pedalEventFired = false; if (pedalChanged) @@ -80,24 +82,22 @@ void PedalModule::checkSendPedalPos(uint32_t now) } } -void IRAM_ATTR PedalModule::button_interrupt() +void IRAM_ATTR PedalModule::button_interrupt(void *instance) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xSemaphoreGiveFromISR(PedalModule::instance->_pedalSemaphore, &xHigherPriorityTaskWoken); - // No need to if (xHigherPriorityTaskWoken) portYIELD_FROM_ISR(), just let the loop break + xSemaphoreGiveFromISR(((PedalModule *)instance)->_pedalSemaphore, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken) + portYIELD_FROM_ISR(); } void PedalModule::button_OnShortPress() { _pedalEventFired = true; - DBGLN("Short %u", _pedal.getCount()); } void PedalModule::button_OnLongPress() { _pedalEventFired = true; - DBGLN("Long %u", _pedal.getLongCount()); - // Long press of the pedal for 5s takes the pedal into binding mode if (_pedal.getLongCount() >= 10 && connectionState == running) { diff --git a/src/module_pedal.h b/src/module_pedal.h index b2828b8e..ab280e5c 100644 --- a/src/module_pedal.h +++ b/src/module_pedal.h @@ -13,18 +13,18 @@ class PedalModule : public ModuleBase { public: PedalModule(); + ~PedalModule(); void Init(); void Loop(uint32_t now); private: - static PedalModule *instance; - static void button_interrupt(); + static void button_interrupt(void *instance); // Don't send updates on for a short time after bootup static constexpr uint32_t STARTUP_MS = 2000U; // Transmit interval differs based on how recently the pedal changed position - static constexpr uint32_t PEDAL_INTERVAL_UNCHANGED_MS = 1000U; - static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = 100U; + static constexpr uint32_t PEDAL_INTERVAL_UNCHANGED_MS = 750U; + static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = PEDAL_INTERVAL_UNCHANGED_MS / 10U; void button_OnShortPress(); void button_OnLongPress(); From aaa73c2501902fe4ff3d03de0521b2d1a823aa49 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 25 Jul 2025 12:12:24 -0400 Subject: [PATCH 04/13] Stop using pedalChanged flag, still unreliable --- src/Vrx_main.cpp | 1 - src/module_pedal.cpp | 13 +++---------- src/module_pedal.h | 4 +--- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/Vrx_main.cpp b/src/Vrx_main.cpp index 2997e77c..bed4251e 100644 --- a/src/Vrx_main.cpp +++ b/src/Vrx_main.cpp @@ -381,7 +381,6 @@ void sendMSPViaEspnow(mspPacket_t *packet) { DBGLN("ESPNOW err=%u", err); } - } void resetBootCounter() diff --git a/src/module_pedal.cpp b/src/module_pedal.cpp index c4e15c73..154bbbb6 100644 --- a/src/module_pedal.cpp +++ b/src/module_pedal.cpp @@ -8,9 +8,8 @@ void sendMSPViaEspnow(mspPacket_t *packet); bool BindingExpired(uint32_t now); PedalModule::PedalModule() - : _pedalEventFired(false), _lastTxValue(false), _lastTxMs(0), _lastPedalChangeMs(0) + : _lastTxValue(false), _lastTxMs(0), _lastPedalChangeMs(0) { - _pedal.OnShortPress = std::bind(&PedalModule::button_OnShortPress, this); _pedal.OnLongPress = std::bind(&PedalModule::button_OnLongPress, this); } @@ -50,8 +49,7 @@ void PedalModule::Loop(uint32_t now) void PedalModule::checkSendPedalPos(uint32_t now) { bool pedalPressed = _pedal.isPressed(); - bool pedalChanged = _pedalEventFired || pedalPressed != _lastTxValue; - _pedalEventFired = false; + bool pedalChanged = pedalPressed != _lastTxValue; if (pedalChanged) { @@ -79,6 +77,7 @@ void PedalModule::checkSendPedalPos(uint32_t now) packet.addByte(0); // CH2 packet.addByte(0); sendMSPViaEspnow(&packet); + yield(); } } @@ -90,14 +89,8 @@ void IRAM_ATTR PedalModule::button_interrupt(void *instance) portYIELD_FROM_ISR(); } -void PedalModule::button_OnShortPress() -{ - _pedalEventFired = true; -} - void PedalModule::button_OnLongPress() { - _pedalEventFired = true; // Long press of the pedal for 5s takes the pedal into binding mode if (_pedal.getLongCount() >= 10 && connectionState == running) { diff --git a/src/module_pedal.h b/src/module_pedal.h index ab280e5c..4c3bbac0 100644 --- a/src/module_pedal.h +++ b/src/module_pedal.h @@ -24,15 +24,13 @@ class PedalModule : public ModuleBase static constexpr uint32_t STARTUP_MS = 2000U; // Transmit interval differs based on how recently the pedal changed position static constexpr uint32_t PEDAL_INTERVAL_UNCHANGED_MS = 750U; - static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = PEDAL_INTERVAL_UNCHANGED_MS / 10U; + static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = 50U; - void button_OnShortPress(); void button_OnLongPress(); void checkSendPedalPos(uint32_t now); Button _pedal; SemaphoreHandle_t _pedalSemaphore; - bool _pedalEventFired; bool _lastTxValue; uint32_t _lastTxMs; uint32_t _lastPedalChangeMs; From 5c60d30d987ed54285a50ab4607f6f21727df56f Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 25 Jul 2025 12:31:50 -0400 Subject: [PATCH 05/13] ESP32 target --- targets/pedal.ini | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/targets/pedal.ini b/targets/pedal.ini index a0754718..fd706320 100644 --- a/targets/pedal.ini +++ b/targets/pedal.ini @@ -7,7 +7,6 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D PEDAL_BACKPACK - -D ARDUINO_USB_CDC_ON_BOOT=1 ;-DDEBUG_LOG -DDEBUG_LOG_VERBOSE build_src_filter = ${common_env_data.build_src_filter} @@ -24,11 +23,22 @@ build_src_filter = - - +[env:Pedal_ESP32_Backpack_via_UART] +extends = env_common_esp32, pedal_backpack_common +board_build.f_cpu = 80000000L +build_flags = + ${env_common_esp32.build_flags} + ${pedal_backpack_common.build_flags} + -D LED_INVERTED=1 + -D PIN_LED=2 + -D PIN_PEDAL_BUTTON=0 + [env:Pedal_ESP32C3_Backpack_via_UART] extends = env_common_esp32c3, pedal_backpack_common board_build.f_cpu = 80000000L build_flags = ${env_common_esp32c3.build_flags} ${pedal_backpack_common.build_flags} + -D ARDUINO_USB_CDC_ON_BOOT=1 -D PIN_LED=8 -D PIN_PEDAL_BUTTON=9 From e632efd52697451b349b72b5b4975e4a24a91ae6 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 25 Jul 2025 13:05:57 -0400 Subject: [PATCH 06/13] Fix binding timing out immediately and going to wifi mode --- src/module_pedal.cpp | 26 +++++++++++++++----------- src/module_pedal.h | 3 ++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/module_pedal.cpp b/src/module_pedal.cpp index 154bbbb6..53155ec2 100644 --- a/src/module_pedal.cpp +++ b/src/module_pedal.cpp @@ -8,7 +8,7 @@ void sendMSPViaEspnow(mspPacket_t *packet); bool BindingExpired(uint32_t now); PedalModule::PedalModule() - : _lastTxValue(false), _lastTxMs(0), _lastPedalChangeMs(0) + : _lastTxValue(false), _lastNow(0), _lastTxMs(0), _lastPedalChangeMs(0) { _pedal.OnLongPress = std::bind(&PedalModule::button_OnLongPress, this); } @@ -26,7 +26,11 @@ void PedalModule::Init() void PedalModule::Loop(uint32_t now) { - if (BindingExpired(now)) + // Need to store what the main loop thinks is "now" in case the button + // event is going to use it to set the bindstart time, otherwise millis() + // could be in the future (compared to now) and timeout immediately + _lastNow = now; + if (BindingExpired(_lastNow)) { connectionState = running; } @@ -40,29 +44,29 @@ void PedalModule::Loop(uint32_t now) if (connectionState != running) return; // Don't TX on startup - if (_lastTxMs == 0 && now < STARTUP_MS) + if (_lastTxMs == 0 && _lastNow < STARTUP_MS) return; - checkSendPedalPos(now); + checkSendPedalPos(); } -void PedalModule::checkSendPedalPos(uint32_t now) +void PedalModule::checkSendPedalPos() { bool pedalPressed = _pedal.isPressed(); bool pedalChanged = pedalPressed != _lastTxValue; if (pedalChanged) { - _lastPedalChangeMs = now; + _lastPedalChangeMs = _lastNow; } // Send the pedal position frequently after last change, until it is unchanged for one UNCHANGED_MS interval - uint32_t txIntervalMs = (now - _lastPedalChangeMs < PEDAL_INTERVAL_UNCHANGED_MS) ? PEDAL_INTERVAL_CHANGED_MS : PEDAL_INTERVAL_UNCHANGED_MS; - if (pedalChanged || now - _lastTxMs > txIntervalMs) + uint32_t txIntervalMs = (_lastNow - _lastPedalChangeMs < PEDAL_INTERVAL_UNCHANGED_MS) ? PEDAL_INTERVAL_CHANGED_MS : PEDAL_INTERVAL_UNCHANGED_MS; + if (pedalChanged || _lastNow - _lastTxMs > txIntervalMs) { - _lastTxMs = now; + _lastTxMs = _lastNow; _lastTxValue = pedalPressed; - DBGLN("%u pedal %u", now, pedalPressed); + DBGLN("%u pedal %u", _lastNow, pedalPressed); // Pedal is 1000us if not pressed, 2000us if pressed uint16_t pedalState = pedalPressed ? CRSF_CHANNEL_VALUE_2000 : CRSF_CHANNEL_VALUE_1000; @@ -94,7 +98,7 @@ void PedalModule::button_OnLongPress() // Long press of the pedal for 5s takes the pedal into binding mode if (_pedal.getLongCount() >= 10 && connectionState == running) { - bindingStart = millis(); + bindingStart = _lastNow; connectionState = binding; } // Long press of pedal for 10s goes from binding to wifi diff --git a/src/module_pedal.h b/src/module_pedal.h index 4c3bbac0..27218bfc 100644 --- a/src/module_pedal.h +++ b/src/module_pedal.h @@ -27,11 +27,12 @@ class PedalModule : public ModuleBase static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = 50U; void button_OnLongPress(); - void checkSendPedalPos(uint32_t now); + void checkSendPedalPos(); Button _pedal; SemaphoreHandle_t _pedalSemaphore; bool _lastTxValue; + uint32_t _lastNow; uint32_t _lastTxMs; uint32_t _lastPedalChangeMs; }; From f43bf1e6fe5630a58e81c5b862cc3300a8393d80 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 25 Jul 2025 13:06:20 -0400 Subject: [PATCH 07/13] ESP32S3 Pedal lols --- targets/pedal.ini | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/targets/pedal.ini b/targets/pedal.ini index fd706320..5ef034ca 100644 --- a/targets/pedal.ini +++ b/targets/pedal.ini @@ -3,6 +3,7 @@ # ******************************** [pedal_backpack_common] +board_build.f_cpu = 80000000L build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK @@ -25,7 +26,6 @@ build_src_filter = [env:Pedal_ESP32_Backpack_via_UART] extends = env_common_esp32, pedal_backpack_common -board_build.f_cpu = 80000000L build_flags = ${env_common_esp32.build_flags} ${pedal_backpack_common.build_flags} @@ -35,10 +35,19 @@ build_flags = [env:Pedal_ESP32C3_Backpack_via_UART] extends = env_common_esp32c3, pedal_backpack_common -board_build.f_cpu = 80000000L build_flags = ${env_common_esp32c3.build_flags} ${pedal_backpack_common.build_flags} -D ARDUINO_USB_CDC_ON_BOOT=1 -D PIN_LED=8 -D PIN_PEDAL_BUTTON=9 + +[env:Pedal_ESP32S3_Backpack_via_UART] +extends = env_common_esp32s3, pedal_backpack_common +build_flags = + ${env_common_esp32s3.build_flags} + ${pedal_backpack_common.build_flags} + -D LED_INVERTED=1 + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D PIN_LED=38 + -D PIN_PEDAL_BUTTON=0 From 91c734078854cd42398553fe0936e25d885cc1b6 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 25 Jul 2025 13:16:36 -0400 Subject: [PATCH 08/13] Remove offensive esp_now_send return type --- src/Vrx_main.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Vrx_main.cpp b/src/Vrx_main.cpp index bed4251e..ee9ae40b 100644 --- a/src/Vrx_main.cpp +++ b/src/Vrx_main.cpp @@ -376,11 +376,7 @@ void sendMSPViaEspnow(mspPacket_t *packet) return; } - esp_err_t err = esp_now_send(firmwareOptions.uid, (uint8_t *) &nowDataOutput, packetSize); - if (err != ESP_OK) - { - DBGLN("ESPNOW err=%u", err); - } + esp_now_send(firmwareOptions.uid, (uint8_t *) &nowDataOutput, packetSize); } void resetBootCounter() From ee721a206b393e620eb695a05a755bcd5771adc2 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 25 Jul 2025 15:04:29 -0400 Subject: [PATCH 09/13] I hate u, windows line endings --- src/module_pedal.cpp | 220 +++++++++++++++++++++---------------------- src/module_pedal.h | 78 +++++++-------- targets/pedal.ini | 106 ++++++++++----------- 3 files changed, 202 insertions(+), 202 deletions(-) diff --git a/src/module_pedal.cpp b/src/module_pedal.cpp index 53155ec2..68c3fc4c 100644 --- a/src/module_pedal.cpp +++ b/src/module_pedal.cpp @@ -1,111 +1,111 @@ -#if defined(PEDAL_BACKPACK) - -#include "module_pedal.h" -#include "common.h" -#include "msptypes.h" - -void sendMSPViaEspnow(mspPacket_t *packet); -bool BindingExpired(uint32_t now); - -PedalModule::PedalModule() - : _lastTxValue(false), _lastNow(0), _lastTxMs(0), _lastPedalChangeMs(0) -{ - _pedal.OnLongPress = std::bind(&PedalModule::button_OnLongPress, this); -} - -PedalModule::~PedalModule() -{ - detachInterrupt(PIN_PEDAL_BUTTON); -} - -void PedalModule::Init() -{ - _pedalSemaphore = xSemaphoreCreateBinary(); - attachInterruptArg(PIN_PEDAL_BUTTON, &PedalModule::button_interrupt, this, CHANGE); -} - -void PedalModule::Loop(uint32_t now) -{ - // Need to store what the main loop thinks is "now" in case the button - // event is going to use it to set the bindstart time, otherwise millis() - // could be in the future (compared to now) and timeout immediately - _lastNow = now; - if (BindingExpired(_lastNow)) - { - connectionState = running; - } - - // Pause here to lower power usage (C3 drops from 100mA to 90mA) - // If button is currently transitioning or pressed just consume the semaphore, else delay until an interrupt - xSemaphoreTake(_pedalSemaphore, _pedal.isIdle() ? pdMS_TO_TICKS(20) : 0); - _pedal.update(); - - // Don't TX if binding/wifi - if (connectionState != running) - return; - // Don't TX on startup - if (_lastTxMs == 0 && _lastNow < STARTUP_MS) - return; - - checkSendPedalPos(); -} - -void PedalModule::checkSendPedalPos() -{ - bool pedalPressed = _pedal.isPressed(); - bool pedalChanged = pedalPressed != _lastTxValue; - - if (pedalChanged) - { - _lastPedalChangeMs = _lastNow; - } - - // Send the pedal position frequently after last change, until it is unchanged for one UNCHANGED_MS interval - uint32_t txIntervalMs = (_lastNow - _lastPedalChangeMs < PEDAL_INTERVAL_UNCHANGED_MS) ? PEDAL_INTERVAL_CHANGED_MS : PEDAL_INTERVAL_UNCHANGED_MS; - if (pedalChanged || _lastNow - _lastTxMs > txIntervalMs) - { - _lastTxMs = _lastNow; - _lastTxValue = pedalPressed; - DBGLN("%u pedal %u", _lastNow, pedalPressed); - - // Pedal is 1000us if not pressed, 2000us if pressed - uint16_t pedalState = pedalPressed ? CRSF_CHANNEL_VALUE_2000 : CRSF_CHANNEL_VALUE_1000; - mspPacket_t packet; - packet.reset(); - packet.makeCommand(); - packet.function = MSP_ELRS_BACKPACK_SET_PTR; - packet.addByte(pedalState & 0xFF); // CH0 - packet.addByte(pedalState >> 8); - packet.addByte(0); // CH1 - packet.addByte(0); - packet.addByte(0); // CH2 - packet.addByte(0); - sendMSPViaEspnow(&packet); - yield(); - } -} - -void IRAM_ATTR PedalModule::button_interrupt(void *instance) -{ - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xSemaphoreGiveFromISR(((PedalModule *)instance)->_pedalSemaphore, &xHigherPriorityTaskWoken); - if (xHigherPriorityTaskWoken) - portYIELD_FROM_ISR(); -} - -void PedalModule::button_OnLongPress() -{ - // Long press of the pedal for 5s takes the pedal into binding mode - if (_pedal.getLongCount() >= 10 && connectionState == running) - { - bindingStart = _lastNow; - connectionState = binding; - } - // Long press of pedal for 10s goes from binding to wifi - else if (_pedal.getLongCount() >= 20 && connectionState == binding) - { - connectionState = wifiUpdate; - } -} - +#if defined(PEDAL_BACKPACK) + +#include "module_pedal.h" +#include "common.h" +#include "msptypes.h" + +void sendMSPViaEspnow(mspPacket_t *packet); +bool BindingExpired(uint32_t now); + +PedalModule::PedalModule() + : _lastTxValue(false), _lastNow(0), _lastTxMs(0), _lastPedalChangeMs(0) +{ + _pedal.OnLongPress = std::bind(&PedalModule::button_OnLongPress, this); +} + +PedalModule::~PedalModule() +{ + detachInterrupt(PIN_PEDAL_BUTTON); +} + +void PedalModule::Init() +{ + _pedalSemaphore = xSemaphoreCreateBinary(); + attachInterruptArg(PIN_PEDAL_BUTTON, &PedalModule::button_interrupt, this, CHANGE); +} + +void PedalModule::Loop(uint32_t now) +{ + // Need to store what the main loop thinks is "now" in case the button + // event is going to use it to set the bindstart time, otherwise millis() + // could be in the future (compared to now) and timeout immediately + _lastNow = now; + if (BindingExpired(_lastNow)) + { + connectionState = running; + } + + // Pause here to lower power usage (C3 drops from 100mA to 90mA) + // If button is currently transitioning or pressed just consume the semaphore, else delay until an interrupt + xSemaphoreTake(_pedalSemaphore, _pedal.isIdle() ? pdMS_TO_TICKS(20) : 0); + _pedal.update(); + + // Don't TX if binding/wifi + if (connectionState != running) + return; + // Don't TX on startup + if (_lastTxMs == 0 && _lastNow < STARTUP_MS) + return; + + checkSendPedalPos(); +} + +void PedalModule::checkSendPedalPos() +{ + bool pedalPressed = _pedal.isPressed(); + bool pedalChanged = pedalPressed != _lastTxValue; + + if (pedalChanged) + { + _lastPedalChangeMs = _lastNow; + } + + // Send the pedal position frequently after last change, until it is unchanged for one UNCHANGED_MS interval + uint32_t txIntervalMs = (_lastNow - _lastPedalChangeMs < PEDAL_INTERVAL_UNCHANGED_MS) ? PEDAL_INTERVAL_CHANGED_MS : PEDAL_INTERVAL_UNCHANGED_MS; + if (pedalChanged || _lastNow - _lastTxMs > txIntervalMs) + { + _lastTxMs = _lastNow; + _lastTxValue = pedalPressed; + DBGLN("%u pedal %u", _lastNow, pedalPressed); + + // Pedal is 1000us if not pressed, 2000us if pressed + uint16_t pedalState = pedalPressed ? CRSF_CHANNEL_VALUE_2000 : CRSF_CHANNEL_VALUE_1000; + mspPacket_t packet; + packet.reset(); + packet.makeCommand(); + packet.function = MSP_ELRS_BACKPACK_SET_PTR; + packet.addByte(pedalState & 0xFF); // CH0 + packet.addByte(pedalState >> 8); + packet.addByte(0); // CH1 + packet.addByte(0); + packet.addByte(0); // CH2 + packet.addByte(0); + sendMSPViaEspnow(&packet); + yield(); + } +} + +void IRAM_ATTR PedalModule::button_interrupt(void *instance) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(((PedalModule *)instance)->_pedalSemaphore, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken) + portYIELD_FROM_ISR(); +} + +void PedalModule::button_OnLongPress() +{ + // Long press of the pedal for 5s takes the pedal into binding mode + if (_pedal.getLongCount() >= 10 && connectionState == running) + { + bindingStart = _lastNow; + connectionState = binding; + } + // Long press of pedal for 10s goes from binding to wifi + else if (_pedal.getLongCount() >= 20 && connectionState == binding) + { + connectionState = wifiUpdate; + } +} + #endif /* PEDAL_BACKPACK */ \ No newline at end of file diff --git a/src/module_pedal.h b/src/module_pedal.h index 27218bfc..67f1eb82 100644 --- a/src/module_pedal.h +++ b/src/module_pedal.h @@ -1,40 +1,40 @@ -#pragma once - -#if defined(PEDAL_BACKPACK) -#include "module_base.h" -#include "logging.h" -#include "button.h" - -// For wake -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" - -class PedalModule : public ModuleBase -{ -public: - PedalModule(); - ~PedalModule(); - - void Init(); - void Loop(uint32_t now); -private: - static void button_interrupt(void *instance); - - // Don't send updates on for a short time after bootup - static constexpr uint32_t STARTUP_MS = 2000U; - // Transmit interval differs based on how recently the pedal changed position - static constexpr uint32_t PEDAL_INTERVAL_UNCHANGED_MS = 750U; - static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = 50U; - - void button_OnLongPress(); - void checkSendPedalPos(); - - Button _pedal; - SemaphoreHandle_t _pedalSemaphore; - bool _lastTxValue; - uint32_t _lastNow; - uint32_t _lastTxMs; - uint32_t _lastPedalChangeMs; -}; - +#pragma once + +#if defined(PEDAL_BACKPACK) +#include "module_base.h" +#include "logging.h" +#include "button.h" + +// For wake +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +class PedalModule : public ModuleBase +{ +public: + PedalModule(); + ~PedalModule(); + + void Init(); + void Loop(uint32_t now); +private: + static void button_interrupt(void *instance); + + // Don't send updates on for a short time after bootup + static constexpr uint32_t STARTUP_MS = 2000U; + // Transmit interval differs based on how recently the pedal changed position + static constexpr uint32_t PEDAL_INTERVAL_UNCHANGED_MS = 750U; + static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = 50U; + + void button_OnLongPress(); + void checkSendPedalPos(); + + Button _pedal; + SemaphoreHandle_t _pedalSemaphore; + bool _lastTxValue; + uint32_t _lastNow; + uint32_t _lastTxMs; + uint32_t _lastPedalChangeMs; +}; + #endif /* PEDAL_BACKPACK */ \ No newline at end of file diff --git a/targets/pedal.ini b/targets/pedal.ini index 5ef034ca..4bfd5fd6 100644 --- a/targets/pedal.ini +++ b/targets/pedal.ini @@ -1,53 +1,53 @@ -# ******************************** -# Pedal VRX backpack -- External pedal trigger using headtracking messages -# ******************************** - -[pedal_backpack_common] -board_build.f_cpu = 80000000L -build_flags = - ${common_env_data.build_flags} - -D TARGET_VRX_BACKPACK - -D PEDAL_BACKPACK - ;-DDEBUG_LOG -DDEBUG_LOG_VERBOSE -build_src_filter = - ${common_env_data.build_src_filter} - - - ; - - - - - - - - - - - - - - - - - - - - - - -[env:Pedal_ESP32_Backpack_via_UART] -extends = env_common_esp32, pedal_backpack_common -build_flags = - ${env_common_esp32.build_flags} - ${pedal_backpack_common.build_flags} - -D LED_INVERTED=1 - -D PIN_LED=2 - -D PIN_PEDAL_BUTTON=0 - -[env:Pedal_ESP32C3_Backpack_via_UART] -extends = env_common_esp32c3, pedal_backpack_common -build_flags = - ${env_common_esp32c3.build_flags} - ${pedal_backpack_common.build_flags} - -D ARDUINO_USB_CDC_ON_BOOT=1 - -D PIN_LED=8 - -D PIN_PEDAL_BUTTON=9 - -[env:Pedal_ESP32S3_Backpack_via_UART] -extends = env_common_esp32s3, pedal_backpack_common -build_flags = - ${env_common_esp32s3.build_flags} - ${pedal_backpack_common.build_flags} - -D LED_INVERTED=1 - -D ARDUINO_USB_CDC_ON_BOOT=1 - -D PIN_LED=38 - -D PIN_PEDAL_BUTTON=0 +# ******************************** +# Pedal VRX backpack -- External pedal trigger using headtracking messages +# ******************************** + +[pedal_backpack_common] +board_build.f_cpu = 80000000L +build_flags = + ${common_env_data.build_flags} + -D TARGET_VRX_BACKPACK + -D PEDAL_BACKPACK + ;-DDEBUG_LOG -DDEBUG_LOG_VERBOSE +build_src_filter = + ${common_env_data.build_src_filter} + - + ; - + - + - + - + - + - + - + - + - + - + - + +[env:Pedal_ESP32_Backpack_via_UART] +extends = env_common_esp32, pedal_backpack_common +build_flags = + ${env_common_esp32.build_flags} + ${pedal_backpack_common.build_flags} + -D LED_INVERTED=1 + -D PIN_LED=2 + -D PIN_PEDAL_BUTTON=0 + +[env:Pedal_ESP32C3_Backpack_via_UART] +extends = env_common_esp32c3, pedal_backpack_common +build_flags = + ${env_common_esp32c3.build_flags} + ${pedal_backpack_common.build_flags} + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D PIN_LED=8 + -D PIN_PEDAL_BUTTON=9 + +[env:Pedal_ESP32S3_Backpack_via_UART] +extends = env_common_esp32s3, pedal_backpack_common +build_flags = + ${env_common_esp32s3.build_flags} + ${pedal_backpack_common.build_flags} + -D LED_INVERTED=1 + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D PIN_LED=38 + -D PIN_PEDAL_BUTTON=0 From 7f633363901c1e4aca5a09eb389e6ae25b9d7bf6 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 25 Jul 2025 16:02:05 -0400 Subject: [PATCH 10/13] Changed inverval to 100ms, S3 to SuperMini --- src/module_pedal.h | 2 +- targets/pedal.ini | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/module_pedal.h b/src/module_pedal.h index 67f1eb82..b5e48b03 100644 --- a/src/module_pedal.h +++ b/src/module_pedal.h @@ -24,7 +24,7 @@ class PedalModule : public ModuleBase static constexpr uint32_t STARTUP_MS = 2000U; // Transmit interval differs based on how recently the pedal changed position static constexpr uint32_t PEDAL_INTERVAL_UNCHANGED_MS = 750U; - static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = 50U; + static constexpr uint32_t PEDAL_INTERVAL_CHANGED_MS = 100U; void button_OnLongPress(); void checkSendPedalPos(); diff --git a/targets/pedal.ini b/targets/pedal.ini index 4bfd5fd6..2fe69cde 100644 --- a/targets/pedal.ini +++ b/targets/pedal.ini @@ -44,10 +44,11 @@ build_flags = [env:Pedal_ESP32S3_Backpack_via_UART] extends = env_common_esp32s3, pedal_backpack_common +board_upload.flash_size = 4MB build_flags = ${env_common_esp32s3.build_flags} ${pedal_backpack_common.build_flags} -D LED_INVERTED=1 -D ARDUINO_USB_CDC_ON_BOOT=1 - -D PIN_LED=38 + -D PIN_LED=48 -D PIN_PEDAL_BUTTON=0 From 388cc5b292224450b6d03bb8fb35ab95b6b1c005 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Fri, 24 Oct 2025 17:47:41 -0400 Subject: [PATCH 11/13] ELRS 4.0 only update 1 channel for Pedal --- src/module_pedal.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/module_pedal.cpp b/src/module_pedal.cpp index 68c3fc4c..5672c0f0 100644 --- a/src/module_pedal.cpp +++ b/src/module_pedal.cpp @@ -76,10 +76,12 @@ void PedalModule::checkSendPedalPos() packet.function = MSP_ELRS_BACKPACK_SET_PTR; packet.addByte(pedalState & 0xFF); // CH0 packet.addByte(pedalState >> 8); - packet.addByte(0); // CH1 - packet.addByte(0); - packet.addByte(0); // CH2 - packet.addByte(0); + // ExpressLRS 4.0 supports only sending as many channels as needed, but for 3.x compatibility + // 6 total payload bytes are required. A channel value of 0xffff means "do not update" in 4.0 + packet.addByte(0xff); // CH1 + packet.addByte(0xff); + packet.addByte(0xff); // CH2 + packet.addByte(0xff); sendMSPViaEspnow(&packet); yield(); } From f03c31481ff071b0963ec59223f6ff529a520b3e Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Wed, 12 Nov 2025 11:55:08 -0500 Subject: [PATCH 12/13] Update for optional separate pedal/bind buttons --- src/module_pedal.cpp | 21 +++++++++++---------- src/module_pedal.h | 3 ++- targets/pedal.ini | 22 ++++++++++++++++------ 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/module_pedal.cpp b/src/module_pedal.cpp index 5672c0f0..19704676 100644 --- a/src/module_pedal.cpp +++ b/src/module_pedal.cpp @@ -10,18 +10,18 @@ bool BindingExpired(uint32_t now); PedalModule::PedalModule() : _lastTxValue(false), _lastNow(0), _lastTxMs(0), _lastPedalChangeMs(0) { - _pedal.OnLongPress = std::bind(&PedalModule::button_OnLongPress, this); + _btnBind.OnLongPress = std::bind(&PedalModule::button_OnLongPress, this); } PedalModule::~PedalModule() { - detachInterrupt(PIN_PEDAL_BUTTON); + detachInterrupt(PIN_BUTTON_PEDAL); } void PedalModule::Init() { _pedalSemaphore = xSemaphoreCreateBinary(); - attachInterruptArg(PIN_PEDAL_BUTTON, &PedalModule::button_interrupt, this, CHANGE); + attachInterruptArg(PIN_BUTTON_PEDAL, &PedalModule::button_interrupt, this, CHANGE); } void PedalModule::Loop(uint32_t now) @@ -37,8 +37,9 @@ void PedalModule::Loop(uint32_t now) // Pause here to lower power usage (C3 drops from 100mA to 90mA) // If button is currently transitioning or pressed just consume the semaphore, else delay until an interrupt - xSemaphoreTake(_pedalSemaphore, _pedal.isIdle() ? pdMS_TO_TICKS(20) : 0); - _pedal.update(); + xSemaphoreTake(_pedalSemaphore, _btnPedal.isIdle() ? pdMS_TO_TICKS(20) : 0); + _btnPedal.update(); + _btnBind.update(); // Don't TX if binding/wifi if (connectionState != running) @@ -52,7 +53,7 @@ void PedalModule::Loop(uint32_t now) void PedalModule::checkSendPedalPos() { - bool pedalPressed = _pedal.isPressed(); + bool pedalPressed = _btnPedal.isPressed(); bool pedalChanged = pedalPressed != _lastTxValue; if (pedalChanged) @@ -97,14 +98,14 @@ void IRAM_ATTR PedalModule::button_interrupt(void *instance) void PedalModule::button_OnLongPress() { - // Long press of the pedal for 5s takes the pedal into binding mode - if (_pedal.getLongCount() >= 10 && connectionState == running) + // Long press of the bind button for 5s takes the pedal into binding mode + if (_btnBind.getLongCount() >= 10 && connectionState == running) { bindingStart = _lastNow; connectionState = binding; } - // Long press of pedal for 10s goes from binding to wifi - else if (_pedal.getLongCount() >= 20 && connectionState == binding) + // Long press of bind button for 10s goes from binding to wifi + else if (_btnBind.getLongCount() >= 20 && connectionState == binding) { connectionState = wifiUpdate; } diff --git a/src/module_pedal.h b/src/module_pedal.h index b5e48b03..316c800a 100644 --- a/src/module_pedal.h +++ b/src/module_pedal.h @@ -29,7 +29,8 @@ class PedalModule : public ModuleBase void button_OnLongPress(); void checkSendPedalPos(); - Button _pedal; + Button _btnPedal; + Button _btnBind; SemaphoreHandle_t _pedalSemaphore; bool _lastTxValue; uint32_t _lastNow; diff --git a/targets/pedal.ini b/targets/pedal.ini index 2fe69cde..1d4be1ab 100644 --- a/targets/pedal.ini +++ b/targets/pedal.ini @@ -1,5 +1,13 @@ # ******************************** # Pedal VRX backpack -- External pedal trigger using headtracking messages +# +# Connections +# PIN_BUTTON_PEDAL - Pedal input. Connect the NO wire from the pedal and its common wire to GND +# PIN_BUTTON_BIND - Bind button. Behaves differently than the standard button. +# Hold for 5 seconds to enter bind mode +# Hold for 10 seconds to enter wifi mode +# PIN_LED - Standard monochrome LED +# PIN_BUTTON_PEDAL and PIN_BUTTON_BIND can be wired/switched together to make the pedal also work as the bind button # ******************************** [pedal_backpack_common] @@ -8,7 +16,7 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D PEDAL_BACKPACK - ;-DDEBUG_LOG -DDEBUG_LOG_VERBOSE + -DDEBUG_LOG -DDEBUG_LOG_VERBOSE build_src_filter = ${common_env_data.build_src_filter} - @@ -29,9 +37,9 @@ extends = env_common_esp32, pedal_backpack_common build_flags = ${env_common_esp32.build_flags} ${pedal_backpack_common.build_flags} - -D LED_INVERTED=1 -D PIN_LED=2 - -D PIN_PEDAL_BUTTON=0 + -D PIN_BUTTON_PEDAL=15 + -D PIN_BUTTON_BIND=0 [env:Pedal_ESP32C3_Backpack_via_UART] extends = env_common_esp32c3, pedal_backpack_common @@ -40,7 +48,9 @@ build_flags = ${pedal_backpack_common.build_flags} -D ARDUINO_USB_CDC_ON_BOOT=1 -D PIN_LED=8 - -D PIN_PEDAL_BUTTON=9 + -D LED_INVERTED + -D PIN_BUTTON_PEDAL=4 + -D PIN_BUTTON_BIND=9 [env:Pedal_ESP32S3_Backpack_via_UART] extends = env_common_esp32s3, pedal_backpack_common @@ -48,7 +58,7 @@ board_upload.flash_size = 4MB build_flags = ${env_common_esp32s3.build_flags} ${pedal_backpack_common.build_flags} - -D LED_INVERTED=1 -D ARDUINO_USB_CDC_ON_BOOT=1 -D PIN_LED=48 - -D PIN_PEDAL_BUTTON=0 + -D PIN_BUTTON_PEDAL=13 + -D PIN_BUTTON_BIND=0 From 865dd306565236a2e186fdc25ed4841b06bd3d97 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Wed, 12 Nov 2025 12:05:46 -0500 Subject: [PATCH 13/13] Add LED indicator for pedal pushing --- src/module_pedal.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/module_pedal.cpp b/src/module_pedal.cpp index 19704676..f7d92b2d 100644 --- a/src/module_pedal.cpp +++ b/src/module_pedal.cpp @@ -3,6 +3,9 @@ #include "module_pedal.h" #include "common.h" #include "msptypes.h" +#if defined(PIN_LED) + #include "devLED.h" +#endif void sendMSPViaEspnow(mspPacket_t *packet); bool BindingExpired(uint32_t now); @@ -85,6 +88,12 @@ void PedalModule::checkSendPedalPos() packet.addByte(0xff); sendMSPViaEspnow(&packet); yield(); + +#if defined(PIN_LED) + // Flash the LED to indicate the high-speed pedal update mode + if (pedalPressed) + blinkLED(); +#endif } }