From faf043327d40e508a6f35fc1100bdb764dde5d66 Mon Sep 17 00:00:00 2001 From: Adam Mealings Date: Wed, 14 May 2025 21:46:39 +0100 Subject: [PATCH 01/16] RAK4631 analogue user button on input 31 --- examples/companion_radio/UITask.cpp | 68 +++++++++++++++++------------ src/helpers/nrf52/RAK4631Board.cpp | 3 ++ variants/rak4631/platformio.ini | 1 + 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/examples/companion_radio/UITask.cpp b/examples/companion_radio/UITask.cpp index e0c2ec51..6eae88c9 100644 --- a/examples/companion_radio/UITask.cpp +++ b/examples/companion_radio/UITask.cpp @@ -209,40 +209,50 @@ void UITask::userLedHandler() { } void UITask::buttonHandler() { -#ifdef PIN_USER_BTN - static int prev_btn_state = !USER_BTN_PRESSED; - static unsigned long btn_state_change_time = 0; - static unsigned long next_read = 0; - int cur_time = millis(); - if (cur_time >= next_read) { - int btn_state = digitalRead(PIN_USER_BTN); - if (btn_state != prev_btn_state) { - if (btn_state == USER_BTN_PRESSED) { // pressed? - if (_display != NULL) { - if (_display->isOn()) { - clearMsgPreview(); - } else { - _display->turnOn(); - _need_refresh = true; + #ifdef PIN_USER_BTN || PIN_USER_BTN_ANA + static int prev_btn_state = !USER_BTN_PRESSED; + static int prev_btn_state_ana = !USER_BTN_PRESSED; + static unsigned long btn_state_change_time = 0; + static unsigned long next_read = 0; + int cur_time = millis(); + if (cur_time >= next_read) { + int btn_state = 0; + int btn_state_ana = 0; + #ifdef PIN_USER_BTN + btn_state = digitalRead(PIN_USER_BTN); + #endif + #ifdef PIN_USER_BTN_ANA + btn_state_ana = (analogRead(PIN_USER_BTN_ANA) < 20); // analogRead returns a value hopefully below 20 when button is pressed. + #endif + //Serial.println(analogRead(PIN_USER_BTN_ANA)); + if (btn_state != prev_btn_state || btn_state_ana != prev_btn_state_ana) { // check for either digital or analogue button change of state + if (btn_state == USER_BTN_PRESSED || btn_state_ana == USER_BTN_PRESSED) { // pressed? + if (_display != NULL) { + if (_display->isOn()) { + clearMsgPreview(); + } else { + _display->turnOn(); + _need_refresh = true; + } + _auto_off = cur_time + AUTO_OFF_MILLIS; // extend auto-off timer + } + } else { // unpressed ? check pressed time ... + if ((cur_time - btn_state_change_time) > 5000) { + #ifdef PIN_STATUS_LED + digitalWrite(PIN_STATUS_LED, LOW); + delay(10); + #endif + _board->powerOff(); } - _auto_off = cur_time + AUTO_OFF_MILLIS; // extend auto-off timer - } - } else { // unpressed ? check pressed time ... - if ((cur_time - btn_state_change_time) > 5000) { - #ifdef PIN_STATUS_LED - digitalWrite(PIN_STATUS_LED, LOW); - delay(10); - #endif - _board->powerOff(); } + btn_state_change_time = millis(); + prev_btn_state = btn_state; + prev_btn_state_ana = btn_state_ana; } - btn_state_change_time = millis(); - prev_btn_state = btn_state; + next_read = millis() + 100; // 10 reads per second } - next_read = millis() + 100; // 10 reads per second + #endif } -#endif -} void UITask::loop() { buttonHandler(); diff --git a/src/helpers/nrf52/RAK4631Board.cpp b/src/helpers/nrf52/RAK4631Board.cpp index 8b368734..6deed5b4 100644 --- a/src/helpers/nrf52/RAK4631Board.cpp +++ b/src/helpers/nrf52/RAK4631Board.cpp @@ -25,6 +25,9 @@ void RAK4631Board::begin() { #ifdef PIN_USER_BTN pinMode(PIN_USER_BTN, INPUT_PULLUP); #endif +#ifdef PIN_USER_BTN_ANA + pinMode(PIN_USER_BTN_ANA, INPUT_PULLUP); +#endif #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index 85f59bfa..af1eb3d4 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -7,6 +7,7 @@ build_flags = ${nrf52840_base.build_flags} -I variants/rak4631 -D RAK_4631 -D PIN_USER_BTN=9 + -D PIN_USER_BTN_ANA=31 -D PIN_BOARD_SCL=14 -D PIN_BOARD_SDA=13 -D PIN_OLED_RESET=-1 From f1df9f7c3b5ad3d118e5001bc4bafab72a408be9 Mon Sep 17 00:00:00 2001 From: adam2872 <53094349+adam2872@users.noreply.github.com> Date: Wed, 14 May 2025 22:04:28 +0100 Subject: [PATCH 02/16] Revert "RAK4631 analogue user button on input 31" --- examples/companion_radio/UITask.cpp | 68 ++++++++++++----------------- src/helpers/nrf52/RAK4631Board.cpp | 3 -- variants/rak4631/platformio.ini | 1 - 3 files changed, 29 insertions(+), 43 deletions(-) diff --git a/examples/companion_radio/UITask.cpp b/examples/companion_radio/UITask.cpp index 6eae88c9..e0c2ec51 100644 --- a/examples/companion_radio/UITask.cpp +++ b/examples/companion_radio/UITask.cpp @@ -209,50 +209,40 @@ void UITask::userLedHandler() { } void UITask::buttonHandler() { - #ifdef PIN_USER_BTN || PIN_USER_BTN_ANA - static int prev_btn_state = !USER_BTN_PRESSED; - static int prev_btn_state_ana = !USER_BTN_PRESSED; - static unsigned long btn_state_change_time = 0; - static unsigned long next_read = 0; - int cur_time = millis(); - if (cur_time >= next_read) { - int btn_state = 0; - int btn_state_ana = 0; - #ifdef PIN_USER_BTN - btn_state = digitalRead(PIN_USER_BTN); - #endif - #ifdef PIN_USER_BTN_ANA - btn_state_ana = (analogRead(PIN_USER_BTN_ANA) < 20); // analogRead returns a value hopefully below 20 when button is pressed. - #endif - //Serial.println(analogRead(PIN_USER_BTN_ANA)); - if (btn_state != prev_btn_state || btn_state_ana != prev_btn_state_ana) { // check for either digital or analogue button change of state - if (btn_state == USER_BTN_PRESSED || btn_state_ana == USER_BTN_PRESSED) { // pressed? - if (_display != NULL) { - if (_display->isOn()) { - clearMsgPreview(); - } else { - _display->turnOn(); - _need_refresh = true; - } - _auto_off = cur_time + AUTO_OFF_MILLIS; // extend auto-off timer - } - } else { // unpressed ? check pressed time ... - if ((cur_time - btn_state_change_time) > 5000) { - #ifdef PIN_STATUS_LED - digitalWrite(PIN_STATUS_LED, LOW); - delay(10); - #endif - _board->powerOff(); +#ifdef PIN_USER_BTN + static int prev_btn_state = !USER_BTN_PRESSED; + static unsigned long btn_state_change_time = 0; + static unsigned long next_read = 0; + int cur_time = millis(); + if (cur_time >= next_read) { + int btn_state = digitalRead(PIN_USER_BTN); + if (btn_state != prev_btn_state) { + if (btn_state == USER_BTN_PRESSED) { // pressed? + if (_display != NULL) { + if (_display->isOn()) { + clearMsgPreview(); + } else { + _display->turnOn(); + _need_refresh = true; } + _auto_off = cur_time + AUTO_OFF_MILLIS; // extend auto-off timer + } + } else { // unpressed ? check pressed time ... + if ((cur_time - btn_state_change_time) > 5000) { + #ifdef PIN_STATUS_LED + digitalWrite(PIN_STATUS_LED, LOW); + delay(10); + #endif + _board->powerOff(); } - btn_state_change_time = millis(); - prev_btn_state = btn_state; - prev_btn_state_ana = btn_state_ana; } - next_read = millis() + 100; // 10 reads per second + btn_state_change_time = millis(); + prev_btn_state = btn_state; } - #endif + next_read = millis() + 100; // 10 reads per second } +#endif +} void UITask::loop() { buttonHandler(); diff --git a/src/helpers/nrf52/RAK4631Board.cpp b/src/helpers/nrf52/RAK4631Board.cpp index 6deed5b4..8b368734 100644 --- a/src/helpers/nrf52/RAK4631Board.cpp +++ b/src/helpers/nrf52/RAK4631Board.cpp @@ -25,9 +25,6 @@ void RAK4631Board::begin() { #ifdef PIN_USER_BTN pinMode(PIN_USER_BTN, INPUT_PULLUP); #endif -#ifdef PIN_USER_BTN_ANA - pinMode(PIN_USER_BTN_ANA, INPUT_PULLUP); -#endif #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index af1eb3d4..85f59bfa 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -7,7 +7,6 @@ build_flags = ${nrf52840_base.build_flags} -I variants/rak4631 -D RAK_4631 -D PIN_USER_BTN=9 - -D PIN_USER_BTN_ANA=31 -D PIN_BOARD_SCL=14 -D PIN_BOARD_SDA=13 -D PIN_OLED_RESET=-1 From 9a0b6e532629354550bc6a5636e7e12bf8f489f5 Mon Sep 17 00:00:00 2001 From: Adam Mealings Date: Tue, 20 May 2025 13:54:31 +0100 Subject: [PATCH 03/16] Updated to use #if defined... instead of #ifdef --- examples/companion_radio/UITask.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/companion_radio/UITask.cpp b/examples/companion_radio/UITask.cpp index 6eae88c9..3bbf87f2 100644 --- a/examples/companion_radio/UITask.cpp +++ b/examples/companion_radio/UITask.cpp @@ -209,7 +209,7 @@ void UITask::userLedHandler() { } void UITask::buttonHandler() { - #ifdef PIN_USER_BTN || PIN_USER_BTN_ANA + #if defined(PIN_USER_BTN) || defined(PIN_USER_BTN_ANA) static int prev_btn_state = !USER_BTN_PRESSED; static int prev_btn_state_ana = !USER_BTN_PRESSED; static unsigned long btn_state_change_time = 0; @@ -224,7 +224,6 @@ void UITask::buttonHandler() { #ifdef PIN_USER_BTN_ANA btn_state_ana = (analogRead(PIN_USER_BTN_ANA) < 20); // analogRead returns a value hopefully below 20 when button is pressed. #endif - //Serial.println(analogRead(PIN_USER_BTN_ANA)); if (btn_state != prev_btn_state || btn_state_ana != prev_btn_state_ana) { // check for either digital or analogue button change of state if (btn_state == USER_BTN_PRESSED || btn_state_ana == USER_BTN_PRESSED) { // pressed? if (_display != NULL) { From 009173ab9ecfcafb724a30ba9d5fb16a9c5172d4 Mon Sep 17 00:00:00 2001 From: Adam Mealings Date: Tue, 20 May 2025 15:16:56 +0100 Subject: [PATCH 04/16] added missing variable defs and pinmode --- src/helpers/nrf52/RAK4631Board.cpp | 4 ++++ variants/rak4631/platformio.ini | 1 + 2 files changed, 5 insertions(+) diff --git a/src/helpers/nrf52/RAK4631Board.cpp b/src/helpers/nrf52/RAK4631Board.cpp index 8b368734..eb1a42c5 100644 --- a/src/helpers/nrf52/RAK4631Board.cpp +++ b/src/helpers/nrf52/RAK4631Board.cpp @@ -26,6 +26,10 @@ void RAK4631Board::begin() { pinMode(PIN_USER_BTN, INPUT_PULLUP); #endif +#ifdef PIN_USER_BTN_ANA + pinMode(PIN_USER_BTN_ANA, INPUT_PULLUP); +#endif + #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); #endif diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index d7584456..c2845fd4 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -7,6 +7,7 @@ build_flags = ${nrf52840_base.build_flags} -I variants/rak4631 -D RAK_4631 -D PIN_USER_BTN=9 + -D PIN_USER_BTN_ANA=31 -D PIN_BOARD_SCL=14 -D PIN_BOARD_SDA=13 -D PIN_OLED_RESET=-1 From a466d3cf80d91ab7a16e882dd7ba29af6dce81b9 Mon Sep 17 00:00:00 2001 From: taco Date: Thu, 22 May 2025 15:36:20 +1000 Subject: [PATCH 05/16] added serial GPS support to EnvironmentSensorClass based on T114 serial GPS and EnvironmentSensorClass. --- .../sensors/EnvironmentSensorManager.cpp | 93 ++++++++++++++++++- .../sensors/EnvironmentSensorManager.h | 19 +++- variants/promicro/platformio.ini | 6 +- variants/promicro/target.cpp | 4 +- 4 files changed, 117 insertions(+), 5 deletions(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 6d39e905..c82235c6 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -1,5 +1,8 @@ #include "EnvironmentSensorManager.h" + +#include + static Adafruit_AHTX0 AHTX0; static Adafruit_BME280 BME280; static Adafruit_INA3221 INA3221; @@ -44,11 +47,14 @@ bool EnvironmentSensorManager::begin() { BME280_initialized = false; MESH_DEBUG_PRINTLN("BME280 was not found at I2C address %02X", TELEM_BME280_ADDRESS); } - + initSerialGPS(); return true; } bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { + if (requester_permissions & TELEM_PERM_LOCATION) { // does requester have permission? + telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, 0.0f); + } next_available_channel = TELEM_CHANNEL_SELF + 1; if (requester_permissions & TELEM_PERM_ENVIRONMENT) { if (INA3221_initialized) { @@ -86,5 +92,90 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen } } + initSerialGPS(); + return true; +} + + +int EnvironmentSensorManager::getNumSettings() const { + return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected +} + +const char* EnvironmentSensorManager::getSettingName(int i) const { + return (gps_detected && i == 0) ? "gps" : NULL; +} + +const char* EnvironmentSensorManager::getSettingValue(int i) const { + if (gps_detected && i == 0) { + return gps_active ? "1" : "0"; + } + return NULL; +} + +bool EnvironmentSensorManager::setSettingValue(const char* name, const char* value) { + if (gps_detected && strcmp(name, "gps") == 0) { + if (strcmp(value, "0") == 0) { + stop_gps(); + } else { + start_gps(); + } + return true; + } + return false; // not supported +} + + + + +void EnvironmentSensorManager::initSerialGPS() { + Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX); + Serial1.begin(9600); + + // Try to detect if GPS is physically connected to determine if we should expose the setting + pinMode(PIN_GPS_EN, OUTPUT); + digitalWrite(PIN_GPS_EN, HIGH); // Power on GPS + + // Give GPS a moment to power up and send data + delay(1000); + + // We'll consider GPS detected if we see any data on Serial1 + gps_detected = (Serial1.available() > 0); + + if (gps_detected) { + MESH_DEBUG_PRINTLN("GPS detected"); + digitalWrite(PIN_GPS_EN, LOW); // Power off GPS until the setting is changed + } else { + MESH_DEBUG_PRINTLN("No GPS detected"); + digitalWrite(PIN_GPS_EN, LOW); + } + +} + + +void EnvironmentSensorManager::start_gps() { + gps_active = true; + pinMode(PIN_GPS_EN, OUTPUT); + digitalWrite(PIN_GPS_EN, HIGH); +} + +void EnvironmentSensorManager::stop_gps() { + gps_active = false; + pinMode(PIN_GPS_EN, OUTPUT); + digitalWrite(PIN_GPS_EN, LOW); +} + +void EnvironmentSensorManager::loop() { + static long next_gps_update = 0; + + _location->loop(); + + if (millis() > next_gps_update) { + if (_location->isValid()) { + node_lat = ((double)_location->getLatitude())/1000000.; + node_lon = ((double)_location->getLongitude())/1000000.; + MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); + } + next_gps_update = millis() + 1000; + } } \ No newline at end of file diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index fa3a1a1e..51ac3051 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -25,8 +26,22 @@ protected: bool INA219_initialized = false; bool BME280_initialized = false; bool AHTX0_initialized = false; + + bool gps_active = false; + bool gps_detected = false; + LocationProvider* _location; + + void start_gps(); + void stop_gps(); + void initSerialGPS(); + public: - EnvironmentSensorManager(){}; + EnvironmentSensorManager(LocationProvider &location): _location(&location){}; bool begin() override; - bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; + bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; + void loop() override; + int getNumSettings() const override; + const char* getSettingName(int i) const override; + const char* getSettingValue(int i) const override; + bool setSettingValue(const char* name, const char* value) override; }; diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 568e20d7..9e2ee075 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -13,6 +13,9 @@ build_flags = ${nrf52840_base.build_flags} -D PIN_BOARD_SDA=8 -D PIN_OLED_RESET=-1 -D PIN_USER_BTN=6 + -D PIN_GPS_RX=3 + -D PIN_GPS_TX=4 + -D PIN_GPS_EN=5 build_src_filter = ${nrf52840_base.build_src_filter} + + @@ -23,7 +26,8 @@ lib_deps= ${nrf52840_base.lib_deps} adafruit/Adafruit INA219 @ ^1.2.3 adafruit/Adafruit AHTX0 @ ^2.0.5 adafruit/Adafruit BME280 Library @ ^2.3.0 - + stevemarple/MicroNMEA @ ^2.0.6 + [env:Faketec_Repeater] extends = Faketec build_src_filter = ${Faketec.build_src_filter} diff --git a/variants/promicro/target.cpp b/variants/promicro/target.cpp index 841bd1dc..666f43f5 100644 --- a/variants/promicro/target.cpp +++ b/variants/promicro/target.cpp @@ -1,6 +1,7 @@ #include #include "target.h" #include +#include PromicroBoard board; @@ -10,7 +11,8 @@ WRAPPER_CLASS radio_driver(radio, board); VolatileRTCClock fallback_clock; AutoDiscoverRTCClock rtc_clock(fallback_clock); -EnvironmentSensorManager sensors; +MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); +EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; From f9473235c618306fcba5284a6b948bba3a3c4ad1 Mon Sep 17 00:00:00 2001 From: Florent Date: Thu, 22 May 2025 11:46:05 +0200 Subject: [PATCH 06/16] rak3x72 : first commit --- boards/rak3172.json | 33 ++++++++++++ src/helpers/stm32/InternalFileSystem.cpp | 3 ++ variants/rak3x72/platformio.ini | 33 ++++++++++++ variants/rak3x72/target.cpp | 67 ++++++++++++++++++++++++ variants/rak3x72/target.h | 27 ++++++++++ variants/rak3x72/variant.h | 5 ++ variants/wio-e5/platformio.ini | 5 +- variants/wio-e5/target.cpp | 8 ++- variants/wio-e5/target.h | 9 +++- 9 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 boards/rak3172.json create mode 100644 variants/rak3x72/platformio.ini create mode 100644 variants/rak3x72/target.cpp create mode 100644 variants/rak3x72/target.h create mode 100644 variants/rak3x72/variant.h diff --git a/boards/rak3172.json b/boards/rak3172.json new file mode 100644 index 00000000..dbb70b03 --- /dev/null +++ b/boards/rak3172.json @@ -0,0 +1,33 @@ +{ + "build": { + "arduino": { + "variant_h": "variant_RAK3172_MODULE.h" + }, + "core": "stm32", + "cpu": "cortex-m4", + "extra_flags": "-DSTM32WL -DSTM32WLxx -DSTM32WLE5xx", + "framework_extra_flags": { + "arduino": "-DUSE_CM4_STARTUP_FILE -DARDUINO_RAK3172_MODULE" + }, + "f_cpu": "48000000L", + "mcu": "stm32wle5ccu", + "product_line": "STM32WLE5xx", + "variant": "STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U" + }, + "debug": { + "default_tools": ["stlink"], + "jlink_device": "STM32WLE5CC", + "openocd_target": "stm32wlx", + "svd_path": "STM32WLE5_CM4.svd" + }, + "frameworks": ["arduino"], + "name": "BB-STM32WL", + "upload": { + "maximum_ram_size": 65536, + "maximum_size": 262144, + "protocol": "stlink", + "protocols": ["stlink", "jlink"] + }, + "url": "https://store.rakwireless.com/products/wisduo-lpwan-module-rak3172", + "vendor": "RAK" +} diff --git a/src/helpers/stm32/InternalFileSystem.cpp b/src/helpers/stm32/InternalFileSystem.cpp index 47706bac..2714ec6b 100644 --- a/src/helpers/stm32/InternalFileSystem.cpp +++ b/src/helpers/stm32/InternalFileSystem.cpp @@ -126,6 +126,9 @@ InternalFileSystem::InternalFileSystem(void) bool InternalFileSystem::begin(void) { + #ifdef FORMAT_FS + this->format(); + #endif // failed to mount, erase all sector then format and mount again if ( !Adafruit_LittleFS::begin() ) { diff --git a/variants/rak3x72/platformio.ini b/variants/rak3x72/platformio.ini new file mode 100644 index 00000000..94e8f595 --- /dev/null +++ b/variants/rak3x72/platformio.ini @@ -0,0 +1,33 @@ +[rak3x72] +extends = stm32_base +board = rak3172 +board_upload.maximum_size = 229376 ; 32kb for FS +build_flags = ${stm32_base.build_flags} + -D RADIO_CLASS=CustomSTM32WLx + -D WRAPPER_CLASS=CustomSTM32WLxWrapper + -D SPI_INTERFACES_COUNT=0 + -D RX_BOOSTED_GAIN=true + -I variants/rak3x72 +build_src_filter = ${stm32_base.build_src_filter} + +<../variants/rak3x72> + +[env:rak3x72-repeater] +extends = rak3x72 +build_flags = ${rak3x72.build_flags} + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"RAK3x72 Repeater"' + -D ADMIN_PASSWORD='"password"' +build_src_filter = ${rak3x72.build_src_filter} + +<../examples/simple_repeater/main.cpp> + +[env:rak3x72_companion_radio_usb] +extends = rak3x72 +build_flags = ${rak3x72.build_flags} +; -D FORMAT_FS=true + -D LORA_TX_POWER=22 + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +build_src_filter = ${rak3x72.build_src_filter} + +<../examples/companion_radio/*.cpp> +lib_deps = ${rak3x72.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/rak3x72/target.cpp b/variants/rak3x72/target.cpp new file mode 100644 index 00000000..4cb5929a --- /dev/null +++ b/variants/rak3x72/target.cpp @@ -0,0 +1,67 @@ +#include +#include "target.h" +#include + +RAK3x72Board board; + +RADIO_CLASS radio = new STM32WLx_Module(); + +WRAPPER_CLASS radio_driver(radio, board); + +static const uint32_t rfswitch_pins[] = {LORAWAN_RFSWITCH_PINS, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; +static const Module::RfSwitchMode_t rfswitch_table[] = { + {STM32WLx::MODE_IDLE, {LOW, LOW}}, + {STM32WLx::MODE_RX, {HIGH, LOW}}, + {STM32WLx::MODE_TX_LP, {LOW, HIGH}}, + {STM32WLx::MODE_TX_HP, {LOW, HIGH}}, + END_OF_MODE_TABLE, +}; + +VolatileRTCClock rtc_clock; +SensorManager sensors; + +#ifndef LORA_CR + #define LORA_CR 5 +#endif + +bool radio_init() { +// rtc_clock.begin(Wire); + + radio.setRfSwitchTable(rfswitch_pins, rfswitch_table); + + int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, 0, 0); // TCXO set to 0 for RAK3172 + + if (status != RADIOLIB_ERR_NONE) { + Serial.print("ERROR: radio init failed: "); + Serial.println(status); + return false; // fail + } + + #ifdef RX_BOOSTED_GAIN + radio.setRxBoostedGainMode(RX_BOOSTED_GAIN); + #endif + + radio.setCRC(1); + + return true; // success +} + +uint32_t radio_get_rng_seed() { + return radio.random(0x7FFFFFFF); +} + +void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { + radio.setFrequency(freq); + radio.setSpreadingFactor(sf); + radio.setBandwidth(bw); + radio.setCodingRate(cr); +} + +void radio_set_tx_power(uint8_t dbm) { + radio.setOutputPower(dbm); +} + +mesh::LocalIdentity radio_new_identity() { + RadioNoiseListener rng(radio); + return mesh::LocalIdentity(&rng); // create new random identity +} diff --git a/variants/rak3x72/target.h b/variants/rak3x72/target.h new file mode 100644 index 00000000..a4c47bc6 --- /dev/null +++ b/variants/rak3x72/target.h @@ -0,0 +1,27 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include + +class RAK3x72Board : public STM32Board { +public: + const char* getManufacturerName() const override { + return "RAK 3x72"; + } +}; + +extern RAK3x72Board board; +extern WRAPPER_CLASS radio_driver; +extern VolatileRTCClock rtc_clock; +extern SensorManager sensors; + +bool radio_init(); +uint32_t radio_get_rng_seed(); +void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); +void radio_set_tx_power(uint8_t dbm); +mesh::LocalIdentity radio_new_identity(); diff --git a/variants/rak3x72/variant.h b/variants/rak3x72/variant.h new file mode 100644 index 00000000..4405be0b --- /dev/null +++ b/variants/rak3x72/variant.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +#undef RNG diff --git a/variants/wio-e5/platformio.ini b/variants/wio-e5/platformio.ini index 4de13e7f..d8f7954f 100644 --- a/variants/wio-e5/platformio.ini +++ b/variants/wio-e5/platformio.ini @@ -6,6 +6,7 @@ build_flags = ${stm32_base.build_flags} -D RADIO_CLASS=CustomSTM32WLx -D WRAPPER_CLASS=CustomSTM32WLxWrapper -D SPI_INTERFACES_COUNT=0 + -D RX_BOOSTED_GAIN=true -I variants/wio-e5 build_src_filter = ${stm32_base.build_src_filter} +<../variants/wio-e5> @@ -13,7 +14,7 @@ build_src_filter = ${stm32_base.build_src_filter} [env:wio-e5-repeater] extends = lora_e5 build_flags = ${lora_e5.build_flags} - -D LORA_TX_POWER=20 + -D LORA_TX_POWER=22 -D ADVERT_NAME='"WIO-E5 Repeater"' -D ADMIN_PASSWORD='"password"' build_src_filter = ${lora_e5.build_src_filter} @@ -22,7 +23,7 @@ build_src_filter = ${lora_e5.build_src_filter} [env:wio-e5_companion_radio_usb] extends = lora_e5 build_flags = ${lora_e5.build_flags} - -D LORA_TX_POWER=20 + -D LORA_TX_POWER=22 -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 build_src_filter = ${lora_e5.build_src_filter} diff --git a/variants/wio-e5/target.cpp b/variants/wio-e5/target.cpp index aee0dafb..8ccbe384 100644 --- a/variants/wio-e5/target.cpp +++ b/variants/wio-e5/target.cpp @@ -2,7 +2,7 @@ #include "target.h" #include -STM32Board board; +WIOE5Board board; RADIO_CLASS radio = new STM32WLx_Module(); @@ -42,7 +42,11 @@ bool radio_init() { Serial.println(status); return false; // fail } - + + #ifdef RX_BOOSTED_GAIN + radio.setRxBoostedGainMode(RX_BOOSTED_GAIN); + #endif + radio.setCRC(1); return true; // success diff --git a/variants/wio-e5/target.h b/variants/wio-e5/target.h index f2dae108..cc6131cf 100644 --- a/variants/wio-e5/target.h +++ b/variants/wio-e5/target.h @@ -8,7 +8,14 @@ #include #include -extern STM32Board board; +class WIOE5Board : public STM32Board { +public: + const char* getManufacturerName() const override { + return "Seeed Wio E5"; + } +}; + +extern WIOE5Board board; extern WRAPPER_CLASS radio_driver; extern VolatileRTCClock rtc_clock; extern SensorManager sensors; From c7fe21184020a9968e6c61e77087f3637368b53a Mon Sep 17 00:00:00 2001 From: Florent de Lamotte Date: Thu, 22 May 2025 16:24:20 +0200 Subject: [PATCH 07/16] rak3x72 : report bat voltage --- variants/rak3x72/target.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/variants/rak3x72/target.h b/variants/rak3x72/target.h index a4c47bc6..c39b69b1 100644 --- a/variants/rak3x72/target.h +++ b/variants/rak3x72/target.h @@ -8,11 +8,19 @@ #include #include +#define PIN_VBAT_READ A0 +#define ADC_MULTIPLIER (5 * 1.73 * 1000) + class RAK3x72Board : public STM32Board { public: const char* getManufacturerName() const override { return "RAK 3x72"; } + + uint16_t getBattMilliVolts() override { + uint32_t raw = analogRead(PIN_VBAT_READ); + return (ADC_MULTIPLIER * raw) / 1024; + } }; extern RAK3x72Board board; From 23f54dd9248655fcad9e17d3ba90adb544c94dff Mon Sep 17 00:00:00 2001 From: taco Date: Fri, 23 May 2025 14:34:34 +1000 Subject: [PATCH 08/16] fix: remove stray initSerialGPS call --- src/helpers/sensors/EnvironmentSensorManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index c82235c6..2594d91b 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -92,7 +92,6 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen } } - initSerialGPS(); return true; } From efa2b4b1b73e02f4da010fb47eff948d6870d19a Mon Sep 17 00:00:00 2001 From: seagull9000 Date: Fri, 23 May 2025 17:58:13 +1200 Subject: [PATCH 09/16] RTTTL-tone-for-Channel-Message I was a bit remiss in removing the tone for channel message event - this puts one in. So: DM event - plays a tone (per current) Channel Message - new shorter tone All others aren't defined at present. Need muting function before we get too carried away. --- examples/companion_radio/UITask.cpp | 2 + src/helpers/ui/button.cpp | 292 ++++++++++++++++++++++++++++ src/helpers/ui/button.h | 79 ++++++++ 3 files changed, 373 insertions(+) create mode 100644 src/helpers/ui/button.cpp create mode 100644 src/helpers/ui/button.h diff --git a/examples/companion_radio/UITask.cpp b/examples/companion_radio/UITask.cpp index f97b47f4..58ffc4d0 100644 --- a/examples/companion_radio/UITask.cpp +++ b/examples/companion_radio/UITask.cpp @@ -67,6 +67,8 @@ switch(bet){ buzzer.play("MsgRcv3:d=4,o=6,b=200:32e,32g,32b,16c7"); break; case UIEventType::channelMessage: + buzzer.play("kerplop:d=16,o=6,b=120:32g#,32c#"); + break; case UIEventType::roomMessage: case UIEventType::newContactMessage: case UIEventType::none: diff --git a/src/helpers/ui/button.cpp b/src/helpers/ui/button.cpp new file mode 100644 index 00000000..7e715b44 --- /dev/null +++ b/src/helpers/ui/button.cpp @@ -0,0 +1,292 @@ +#include "Button.h" + +Button::Button() : + _pin(0), + _inputMode(INPUT_PULLUP), + _buttonPressedState(HIGH), // Assuming INPUT_PULLUP, so HIGH is unpressed + _lastButtonState(HIGH), + _buttonState(false), // Debounced state: false is unpressed + _lastDebouncedState(false), + _lastDebounceTime(0), + _pressStartTime(0), + _releaseTime(0), + _currentSequenceCount(0), + _lastPressEndTime(0), + _callbackCount(0) +{ + for (uint8_t i = 0; i < MAX_PRESSES_IN_SEQUENCE; ++i) { + _currentSequence[i] = ButtonPressType::NONE; + } + for (uint8_t i = 0; i < MAX_CALLBACKS; ++i) { + _registeredCallbacks[i].count = 0; + _registeredCallbacks[i].callback = nullptr; + _registeredCallbacks[i].triggeredInSequence = false; + for (uint8_t j = 0; j < MAX_PRESSES_IN_SEQUENCE; ++j) { + _registeredCallbacks[i].sequence[j] = ButtonPressType::NONE; + } + } +} + +void Button::attach(uint8_t pin, uint8_t inputMode) { + _pin = pin; + _inputMode = inputMode; + pinMode(_pin, _inputMode); + if (_inputMode == INPUT_PULLUP) { + _buttonPressedState = LOW; // Pressed is LOW for PULLUP + _lastButtonState = HIGH; // Initial unpressed state + } else { + _buttonPressedState = HIGH; // Pressed is HIGH for PULLDOWN or regular INPUT + _lastButtonState = LOW; // Initial unpressed state + } + _lastDebouncedState = false; // Not pressed + _buttonState = false; // Not pressed +} + +void Button::update() { + if (_pin == 0) return; // Not attached + + bool reading = digitalRead(_pin); + unsigned long currentTime = millis(); + + // Debounce logic + if (reading != _lastButtonState) { + _lastDebounceTime = currentTime; + } + _lastButtonState = reading; + + if ((currentTime - _lastDebounceTime) > DEBOUNCE_DELAY) { + bool currentDebouncedState = (reading == _buttonPressedState); + + // Edge detection + if (currentDebouncedState != _lastDebouncedState) { + _lastDebouncedState = currentDebouncedState; + + if (currentDebouncedState) { // Button pressed + _pressStartTime = currentTime; + // If a new press starts too long after the previous one, reset sequence + if (_currentSequenceCount > 0 && (currentTime - _lastPressEndTime) > SHORT_PRESS_TIMEOUT) { + _resetSequence(); + } + } else { // Button released + _releaseTime = currentTime; + unsigned long pressDuration = _releaseTime - _pressStartTime; + ButtonPressType pressType = _determinePressType(pressDuration); + + if (pressType != ButtonPressType::NONE) { + _addPressToSequence(pressType); + _lastPressEndTime = currentTime; // Mark end time for next press timeout + _evaluateSequences(); + } + } + } + } + + // Check for sequence timeout if a sequence is in progress + if (_currentSequenceCount > 0 && (currentTime - _lastPressEndTime) > SHORT_PRESS_TIMEOUT) { + // If we timed out, and haven't triggered anything specific from the partial sequence, + // it's time to reset. Callbacks for partial matches should have already fired in _evaluateSequences. + // This handles the case where a sequence like S1 is defined, and the user presses S, then waits. + // We need to ensure S1 callback fires if it exists, even if S2 or S3 are also defined. + // _evaluateSequences called on release handles this. This timeout mainly resets for the next input. + _resetSequence(); + } +} + + +ButtonPressType Button::_determinePressType(unsigned long pressDuration) { + if (pressDuration >= LONG_LONG_PRESS_MIN_DURATION) { + return ButtonPressType::LL; + } else if (pressDuration >= LONGISH_PRESS_MIN_DURATION && pressDuration < LONGISH_PRESS_MAX_DURATION) { + return ButtonPressType::LS; + } else if (pressDuration > DEBOUNCE_DELAY && pressDuration <= SHORT_PRESS_MAX_DURATION) { // Ensure it's more than debounce + return ButtonPressType::S; + } + return ButtonPressType::NONE; +} + +void Button::_addPressToSequence(ButtonPressType pressType) { + if (_currentSequenceCount < MAX_PRESSES_IN_SEQUENCE) { + // Specific handling for LL: it can only be LL1 + if (pressType == ButtonPressType::LL) { + if (_currentSequenceCount == 0) { // LL only valid as the first press in its "sequence" + _currentSequence[_currentSequenceCount++] = pressType; + } else { + // An LL press occurred after other presses, which is not a defined LL1 sequence. + // Treat as an invalid sequence progression, so reset. + _resetSequence(); + // Potentially start a new sequence with this LL if it was intended as LL1. + // For simplicity now, we just reset. More complex logic could try to salvage. + } + } else if (pressType == ButtonPressType::LS) { + // LS can form sequences up to LS3 + // Check if previous was also LS or if sequence is empty + if (_currentSequenceCount == 0 || _currentSequence[_currentSequenceCount -1] == ButtonPressType::LS) { + _currentSequence[_currentSequenceCount++] = pressType; + } else { + // Mixing LS with S in a sequence is not explicitly defined as LS1/2/3 or S1/2/3 + // So, reset the sequence and start new with this LS. + _resetSequence(); + _currentSequence[_currentSequenceCount++] = pressType; + } + } else if (pressType == ButtonPressType::S) { + // S can form sequences up to S3 + // Check if previous was also S or if sequence is empty + if (_currentSequenceCount == 0 || _currentSequence[_currentSequenceCount -1] == ButtonPressType::S) { + _currentSequence[_currentSequenceCount++] = pressType; + } else { + // Mixing S with LS in a sequence is not S1/2/3 or LS1/2/3 + // So, reset the sequence and start new with this S. + _resetSequence(); + _currentSequence[_currentSequenceCount++] = pressType; + } + } + } else { + // Sequence array is full, this shouldn't normally happen if MAX_PRESSES_IN_SEQUENCE is large enough. + // Reset to be safe. + _resetSequence(); + // And add the current press as the start of a new sequence. + if (pressType != ButtonPressType::NONE) { // ensure it's a valid press + _currentSequence[_currentSequenceCount++] = pressType; + } + } +} + +void Button::_evaluateSequences() { + if (_currentSequenceCount == 0) return; + + bool exactMatchFound = false; + + for (uint8_t i = 0; i < _callbackCount; ++i) { + ButtonSequence& registered = _registeredCallbacks[i]; + if (registered.callback == nullptr) continue; + + if (registered.count == _currentSequenceCount) { + bool match = true; + for (uint8_t j = 0; j < _currentSequenceCount; ++j) { + if (_currentSequence[j] != registered.sequence[j]) { + match = false; + break; + } + } + if (match) { + // Exact match found + if (!registered.triggeredInSequence) { // Check if already triggered for this evaluation pass + registered.callback(); + registered.triggeredInSequence = true; // Mark as triggered for this pass + } + exactMatchFound = true; + // For an exact match, we generally reset the current sequence + // as it has been fully consumed by a callback. + } + } + } + + // After checking all callbacks, reset their triggeredInSequence flags for the next evaluation pass + for (uint8_t i = 0; i < _callbackCount; ++i) { + _registeredCallbacks[i].triggeredInSequence = false; + } + + // If an exact match was found, the sequence is "consumed" and should be reset. + // This allows, for example, S1 to trigger, then S2 to trigger, then S3. + // If we don't reset, S1 would trigger, then S1+S2 would require an (S,S) callback. + // The current logic means S triggers S1 callback, then if another S comes, (S,S) triggers S2 callback. + if (exactMatchFound) { + _resetSequence(); + } else { + // If no exact match, but the sequence is full (e.g., S, S, S and no S3 callback) + // or if it's an LL press (which is always a sequence of 1) + // then we should reset to allow new sequences. + if (_currentSequenceCount >= MAX_PRESSES_IN_SEQUENCE || + (_currentSequenceCount > 0 && _currentSequence[_currentSequenceCount -1] == ButtonPressType::LL)) { + _resetSequence(); + } + // Also, if the current sequence is S,S and there's no S2 callback, + // but there IS an S1 callback, S1 should have triggered. + // The current _evaluateSequences iterates all callbacks. + // The problem is if a user defines S and S,S. + // Press S: S callback fires. Current sequence is {S}. + // Press S again: Current sequence becomes {S,S}. S,S callback fires. Sequence resets. This is good. + + // What if user defines S, S,S, S,S,S. + // Press 1: S fires. Seq={S}. + // Press 2: S,S fires. Seq={S,S}. + // Press 3: S,S,S fires. Seq={S,S,S}. + // The reset on exact match handles this. + + // What if only S,S,S is defined? + // Press 1: Seq={S}. No exact match. No reset. + // Press 2: Seq={S,S}. No exact match. No reset. + // Press 3: Seq={S,S,S}. S,S,S fires. Seq resets. Good. + + // What if only S is defined? + // Press 1: Seq={S}. S fires. Seq resets. Good. + // User presses S, S, S. + // S -> S fires, seq resets. + // S -> S fires, seq resets. + // S -> S fires, seq resets. + // This seems correct. A sequence ends once it matches *a* callback. + + // Exception: LL is always a single event. + if (_currentSequenceCount == 1 && _currentSequence[0] == ButtonPressType::LL) { + // LL callback would have fired if registered. Sequence should reset. + // This is handled by `exactMatchFound` leading to reset, + // or by the `_currentSequence[_currentSequenceCount -1] == ButtonPressType::LL` condition above. + } + } +} + + +void Button::_resetSequence() { + _currentSequenceCount = 0; + for (uint8_t i = 0; i < MAX_PRESSES_IN_SEQUENCE; ++i) { + _currentSequence[i] = ButtonPressType::NONE; + } + // _lastPressEndTime is not reset here, because it's used to see if a *new* press + // is starting a new sequence or continuing one (within SHORT_PRESS_TIMEOUT). + // When a sequence fully resets (e.g. due to timeout or completion), + // the _pressStartTime of the *next* press will be compared to the _lastPressEndTime + // of the *previous* press that completed/timed-out the sequence. +} + +bool Button::onPress(ButtonPressType pressType, ButtonCallback callback) { + if (pressType == ButtonPressType::NONE) return false; + // This is a shorthand for a sequence of one. + return onPressSequence(&pressType, 1, callback); +} + +bool Button::onPressSequence(const ButtonPressType types[], uint8_t count, ButtonCallback callback) { + if (_callbackCount >= MAX_CALLBACKS || count == 0 || count > MAX_PRESSES_IN_SEQUENCE) { + return false; // No space or invalid sequence + } + + // Restriction: LL can only be a sequence of 1. + if (count > 1) { + for(uint8_t i=0; i < count; ++i) { + if (types[i] == ButtonPressType::LL) return false; // LL cannot be part of a multi-press sequence definition. + } + } + // Restriction: Sequences must be homogenous (all S or all LS), or a single LL. + if (count > 1) { + ButtonPressType firstType = types[0]; + if (firstType == ButtonPressType::LL) return false; // Should have been caught above. + for (uint8_t i = 1; i < count; ++i) { + if (types[i] != firstType || types[i] == ButtonPressType::LL) { + // Heterogeneous sequence (e.g. S, LS) or LL in multi-press is not allowed by problem def. + return false; + } + } + } + + + _registeredCallbacks[_callbackCount].count = count; + for (uint8_t i = 0; i < count; ++i) { + _registeredCallbacks[_callbackCount].sequence[i] = types[i]; + } + for (uint8_t i = count; i < MAX_PRESSES_IN_SEQUENCE; ++i) { // Zero out rest + _registeredCallbacks[_callbackCount].sequence[i] = ButtonPressType::NONE; + } + _registeredCallbacks[_callbackCount].callback = callback; + _registeredCallbacks[_callbackCount].triggeredInSequence = false; + _callbackCount++; + return true; +} \ No newline at end of file diff --git a/src/helpers/ui/button.h b/src/helpers/ui/button.h new file mode 100644 index 00000000..0f0e3b92 --- /dev/null +++ b/src/helpers/ui/button.h @@ -0,0 +1,79 @@ +#ifndef BUTTON_H +#define BUTTON_H + +#include + +// Maximum number of presses in a sequence (e.g., S3, LS3) +#define MAX_PRESSES_IN_SEQUENCE 3 +// Maximum number of sequences that can be registered +#define MAX_CALLBACKS 10 +// Debounce delay in milliseconds +#define DEBOUNCE_DELAY 50 +// Time to distinguish between short presses in a sequence (ms) +#define SHORT_PRESS_TIMEOUT 500 +// Short press max duration (ms) +#define SHORT_PRESS_MAX_DURATION (SHORT_PRESS_TIMEOUT - 1) // Must be less than timeout +// Longish press min duration (ms) +#define LONGISH_PRESS_MIN_DURATION 1000 +// Longish press max duration (ms) +#define LONGISH_PRESS_MAX_DURATION 2500 +// Long-Long press min duration (ms) +#define LONG_LONG_PRESS_MIN_DURATION 4000 + + +// Enum to represent different press types +enum class ButtonPressType { + NONE, + S, // Short Press + LS, // Longish Press + LL // Long-Long Press +}; + +// Type alias for the callback function +typedef void (*ButtonCallback)(); + +struct ButtonSequence { + ButtonPressType sequence[MAX_PRESSES_IN_SEQUENCE]; + uint8_t count; // Number of presses in this specific sequence + ButtonCallback callback; + bool triggeredInSequence; // To prevent multiple triggers during a sequence evaluation +}; + +class Button { +public: + Button(); + void attach(uint8_t pin, uint8_t inputMode = INPUT_PULLUP); + void update(); + + // Methods to add callbacks + // For single press types (e.g., one long-long press) + bool onPress(ButtonPressType pressType, ButtonCallback callback); + // For sequences of presses (e.g., S, S, S or LS, LS) + bool onPressSequence(const ButtonPressType types[], uint8_t count, ButtonCallback callback); + +private: + uint8_t _pin; + uint8_t _inputMode; + bool _buttonPressedState; // Physical state of the button (HIGH/LOW) + bool _lastButtonState; // Previous physical state for change detection + bool _buttonState; // Debounced button state (true for pressed) + bool _lastDebouncedState; // Last debounced state + + unsigned long _lastDebounceTime; + unsigned long _pressStartTime; + unsigned long _releaseTime; + + ButtonPressType _currentSequence[MAX_PRESSES_IN_SEQUENCE]; + uint8_t _currentSequenceCount; + unsigned long _lastPressEndTime; // Time when the last press in a potential sequence ended + + ButtonSequence _registeredCallbacks[MAX_CALLBACKS]; + uint8_t _callbackCount; + + void _resetSequence(); + void _addPressToSequence(ButtonPressType pressType); + void _evaluateSequences(); + ButtonPressType _determinePressType(unsigned long pressDuration); +}; + +#endif // BUTTON_H \ No newline at end of file From 400c4353dc72141140906c9cfcdf06123c093994 Mon Sep 17 00:00:00 2001 From: taco Date: Fri, 23 May 2025 17:08:23 +1000 Subject: [PATCH 10/16] REFACTOR: sensors are now wrapped in conditionals --- .../sensors/EnvironmentSensorManager.cpp | 119 +++++++++++------- .../sensors/EnvironmentSensorManager.h | 40 ++++-- variants/promicro/platformio.ini | 7 +- 3 files changed, 110 insertions(+), 56 deletions(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 2594d91b..b5f5cd48 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -1,15 +1,45 @@ #include "EnvironmentSensorManager.h" - -#include - +#if ENV_INCLUDE_AHTX0 static Adafruit_AHTX0 AHTX0; +#endif +#if ENV_INCLUDE_BME280 static Adafruit_BME280 BME280; +#endif +#if ENV_INCLUDE_INA3221 static Adafruit_INA3221 INA3221; +#endif +#if ENV_INCLUDE_INA219 static Adafruit_INA219 INA219(TELEM_INA219_ADDRESS); +#endif bool EnvironmentSensorManager::begin() { + #if ENV_INCLUDE_GPS + initBasicGPS(); + #endif + #if ENV_INCLUDE_AHTX0 + if (AHTX0.begin(&Wire, 0, TELEM_AHTX_ADDRESS)) { + MESH_DEBUG_PRINTLN("Found AHT10/AHT20 at address: %02X", TELEM_AHTX_ADDRESS); + AHTX0_initialized = true; + } else { + AHTX0_initialized = false; + MESH_DEBUG_PRINTLN("AHT10/AHT20 was not found at I2C address %02X", TELEM_AHTX_ADDRESS); + } + #endif + + #if ENV_INCLUDE_BME280 + if (BME280.begin(TELEM_BME280_ADDRESS, &Wire)) { + MESH_DEBUG_PRINTLN("Found BME280 at address: %02X", TELEM_BME280_ADDRESS); + MESH_DEBUG_PRINTLN("BME sensor ID: %02X", BME280.sensorID()); + BME280_initialized = true; + } else { + BME280_initialized = false; + MESH_DEBUG_PRINTLN("BME280 was not found at I2C address %02X", TELEM_BME280_ADDRESS); + } + #endif + + #if ENV_INCLUDE_INA3221 if (INA3221.begin(TELEM_INA3221_ADDRESS, &Wire)) { MESH_DEBUG_PRINTLN("Found INA3221 at address: %02X", TELEM_INA3221_ADDRESS); MESH_DEBUG_PRINTLN("%04X %04X", INA3221.getDieID(), INA3221.getManufacturerID()); @@ -22,7 +52,9 @@ bool EnvironmentSensorManager::begin() { INA3221_initialized = false; MESH_DEBUG_PRINTLN("INA3221 was not found at I2C address %02X", TELEM_INA3221_ADDRESS); } + #endif + #if ENV_INCLUDE_INA219 if (INA219.begin(&Wire)) { MESH_DEBUG_PRINTLN("Found INA219 at address: %02X", TELEM_INA219_ADDRESS); INA219_initialized = true; @@ -30,33 +62,39 @@ bool EnvironmentSensorManager::begin() { INA219_initialized = false; MESH_DEBUG_PRINTLN("INA219 was not found at I2C address %02X", TELEM_INA219_ADDRESS); } + #endif - if (AHTX0.begin(&Wire, 0, TELEM_AHTX_ADDRESS)) { - MESH_DEBUG_PRINTLN("Found AHT10/AHT20 at address: %02X", TELEM_AHTX_ADDRESS); - AHTX0_initialized = true; - } else { - AHTX0_initialized = false; - MESH_DEBUG_PRINTLN("AHT10/AHT20 was not found at I2C address %02X", TELEM_AHTX_ADDRESS); - } - - if (BME280.begin(TELEM_BME280_ADDRESS, &Wire)) { - MESH_DEBUG_PRINTLN("Found BME280 at address: %02X", TELEM_BME280_ADDRESS); - MESH_DEBUG_PRINTLN("BME sensor ID: %02X", BME280.sensorID); - BME280_initialized = true; - } else { - BME280_initialized = false; - MESH_DEBUG_PRINTLN("BME280 was not found at I2C address %02X", TELEM_BME280_ADDRESS); - } - initSerialGPS(); return true; } bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { - if (requester_permissions & TELEM_PERM_LOCATION) { // does requester have permission? - telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, 0.0f); - } next_available_channel = TELEM_CHANNEL_SELF + 1; + + if (requester_permissions & TELEM_PERM_LOCATION) { + telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, 0.0f); // allow lat/lon via telemetry even if no GPS is detected + } + if (requester_permissions & TELEM_PERM_ENVIRONMENT) { + + #if ENV_INCLUDE_AHTX0 + if (AHTX0_initialized) { + sensors_event_t humidity, temp; + AHTX0.getEvent(&humidity, &temp); + telemetry.addTemperature(TELEM_CHANNEL_SELF, temp.temperature); + telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, humidity.relative_humidity); + } + #endif + + #if ENV_INCLUDE_BME280 + if (BME280_initialized) { + telemetry.addTemperature(TELEM_CHANNEL_SELF, BME280.readTemperature()); + telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, BME280.readHumidity()); + telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BME280.readPressure()); + telemetry.addAltitude(TELEM_CHANNEL_SELF, BME280.readAltitude(TELEM_BME280_SEALEVELPRESSURE_HPA)); + } + #endif + + #if ENV_INCLUDE_INA3221 if (INA3221_initialized) { for(int i = 0; i < TELEM_INA3221_NUM_CHANNELS; i++) { // add only enabled INA3221 channels to telemetry @@ -70,49 +108,46 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen } } } + #endif + + #if ENV_INCLUDE_INA219 if (INA219_initialized) { telemetry.addVoltage(next_available_channel, INA219.getBusVoltage_V()); telemetry.addCurrent(next_available_channel, INA219.getCurrent_mA() / 1000); telemetry.addPower(next_available_channel, INA219.getPower_mW() / 1000); next_available_channel++; } - if (AHTX0_initialized) { - sensors_event_t humidity, temp; - AHTX0.getEvent(&humidity, &temp); + #endif - telemetry.addTemperature(TELEM_CHANNEL_SELF, temp.temperature); - telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, humidity.relative_humidity); - } - - if (BME280_initialized) { - telemetry.addTemperature(TELEM_CHANNEL_SELF, BME280.readTemperature()); - telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, BME280.readHumidity()); - telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BME280.readPressure()); - telemetry.addAltitude(TELEM_CHANNEL_SELF, BME280.readAltitude(TELEM_BME280_SEALEVELPRESSURE_HPA)); - } } - return true; } int EnvironmentSensorManager::getNumSettings() const { + #if ENV_INCLUDE_GPS return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected + #endif } const char* EnvironmentSensorManager::getSettingName(int i) const { + #if ENV_INCLUDE_GPS return (gps_detected && i == 0) ? "gps" : NULL; + #endif } const char* EnvironmentSensorManager::getSettingValue(int i) const { + #if ENV_INCLUDE_GPS if (gps_detected && i == 0) { return gps_active ? "1" : "0"; } + #endif return NULL; } bool EnvironmentSensorManager::setSettingValue(const char* name, const char* value) { + #if ENV_INCLUDE_GPS if (gps_detected && strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { stop_gps(); @@ -121,13 +156,12 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val } return true; } + #endif return false; // not supported } - - - -void EnvironmentSensorManager::initSerialGPS() { +#if ENV_INCLUDE_GPS +void EnvironmentSensorManager::initBasicGPS() { Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX); Serial1.begin(9600); @@ -177,4 +211,5 @@ void EnvironmentSensorManager::loop() { } next_gps_update = millis() + 1000; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index 51ac3051..2a2d6b81 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -1,45 +1,59 @@ #pragma once +#include #include #include -#include -#include -#include -#include -#include + +#if ENV_INCLUDE_AHTX0 #define TELEM_AHTX_ADDRESS 0x38 // AHT10, AHT20 temperature and humidity sensor I2C address +#include +#endif +#if ENV_INCLUDE_BME280 #define TELEM_BME280_ADDRESS 0x76 // BME280 environmental sensor I2C address +#define TELEM_BME280_SEALEVELPRESSURE_HPA (1013.25) // Athmospheric pressure at sea level +#include +#endif +#if ENV_INCLUDE_INA3221 #define TELEM_INA3221_ADDRESS 0x42 // INA3221 3 channel current sensor I2C address -#define TELEM_INA219_ADDRESS 0x40 // INA219 single channel current sensor I2C address - #define TELEM_INA3221_SHUNT_VALUE 0.100 // most variants will have a 0.1 ohm shunts #define TELEM_INA3221_NUM_CHANNELS 3 +#include +#endif +#if ENV_INCLUDE_INA219 +#define TELEM_INA219_ADDRESS 0x40 // INA219 single channel current sensor I2C address +#include +#endif + -#define TELEM_BME280_SEALEVELPRESSURE_HPA (1013.25) // Athmospheric pressure at sea level class EnvironmentSensorManager : public SensorManager { protected: int next_available_channel = TELEM_CHANNEL_SELF + 1; + bool AHTX0_initialized = false; + bool BME280_initialized = false; bool INA3221_initialized = false; bool INA219_initialized = false; - bool BME280_initialized = false; - bool AHTX0_initialized = false; - bool gps_active = false; - bool gps_detected = false; LocationProvider* _location; + bool gps_detected = false; + bool gps_active = false; + #if ENV_INCLUDE_GPS void start_gps(); void stop_gps(); - void initSerialGPS(); + void initBasicGPS(); + #endif + public: EnvironmentSensorManager(LocationProvider &location): _location(&location){}; bool begin() override; bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; + #if ENV_INCLUDE_GPS void loop() override; + #endif int getNumSettings() const override; const char* getSettingName(int i) const override; const char* getSettingValue(int i) const override; diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 9e2ee075..11f73d81 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -16,6 +16,11 @@ build_flags = ${nrf52840_base.build_flags} -D PIN_GPS_RX=3 -D PIN_GPS_TX=4 -D PIN_GPS_EN=5 + -D ENV_INCLUDE_GPS=1 + -D ENV_INCLUDE_AHTX0=1 + -D ENV_INCLUDE_BME280=1 + -D ENV_INCLUDE_INA3221=1 + -D ENV_INCLUDE_INA219=1 build_src_filter = ${nrf52840_base.build_src_filter} + + @@ -103,7 +108,7 @@ build_flags = ${Faketec.build_flags} -D OFFLINE_QUEUE_SIZE=256 -D DISPLAY_CLASS=SSD1306Display ; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_DEBUG=1 build_src_filter = ${Faketec.build_src_filter} + +<../examples/companion_radio> From 5630533d220171e538663dc915a3dcc7ee8265cc Mon Sep 17 00:00:00 2001 From: seagull9000 Date: Fri, 23 May 2025 17:58:13 +1200 Subject: [PATCH 11/16] RTTTL-tone-for-Channel-Message I was a bit remiss in removing the tone for channel message event - this puts one in. So: DM event - plays a tone (per current) Channel Message - new shorter tone All others aren't defined at present. Need muting function before we get too carried away. --- examples/companion_radio/UITask.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/companion_radio/UITask.cpp b/examples/companion_radio/UITask.cpp index f97b47f4..58ffc4d0 100644 --- a/examples/companion_radio/UITask.cpp +++ b/examples/companion_radio/UITask.cpp @@ -67,6 +67,8 @@ switch(bet){ buzzer.play("MsgRcv3:d=4,o=6,b=200:32e,32g,32b,16c7"); break; case UIEventType::channelMessage: + buzzer.play("kerplop:d=16,o=6,b=120:32g#,32c#"); + break; case UIEventType::roomMessage: case UIEventType::newContactMessage: case UIEventType::none: From 5987e95ce909fb2e4a9aba381b4d8e3924eb2f9f Mon Sep 17 00:00:00 2001 From: taco Date: Fri, 23 May 2025 18:58:45 +1000 Subject: [PATCH 12/16] refactor: more conditionals for GPS also re-added some missing returns. --- src/helpers/sensors/EnvironmentSensorManager.cpp | 6 ++++-- src/helpers/sensors/EnvironmentSensorManager.h | 6 +++++- variants/promicro/target.cpp | 13 ++++++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index b5f5cd48..c300cbe4 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -127,14 +127,16 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen int EnvironmentSensorManager::getNumSettings() const { #if ENV_INCLUDE_GPS - return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected + return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected #endif + return NULL; } const char* EnvironmentSensorManager::getSettingName(int i) const { #if ENV_INCLUDE_GPS - return (gps_detected && i == 0) ? "gps" : NULL; + return (gps_detected && i == 0) ? "gps" : NULL; #endif + return NULL; } const char* EnvironmentSensorManager::getSettingValue(int i) const { diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index 2a2d6b81..2a72f2d0 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -36,11 +36,11 @@ protected: bool INA3221_initialized = false; bool INA219_initialized = false; - LocationProvider* _location; bool gps_detected = false; bool gps_active = false; #if ENV_INCLUDE_GPS + LocationProvider* _location; void start_gps(); void stop_gps(); void initBasicGPS(); @@ -48,7 +48,11 @@ protected: public: + #if ENV_INCLUDE_GPS EnvironmentSensorManager(LocationProvider &location): _location(&location){}; + #else + EnvironmentSensorManager(){}; + #endif bool begin() override; bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; #if ENV_INCLUDE_GPS diff --git a/variants/promicro/target.cpp b/variants/promicro/target.cpp index 666f43f5..2369bd7a 100644 --- a/variants/promicro/target.cpp +++ b/variants/promicro/target.cpp @@ -1,7 +1,9 @@ #include #include "target.h" #include -#include + +#if ENV_INCLUDE_GPS +#endif PromicroBoard board; @@ -11,8 +13,13 @@ WRAPPER_CLASS radio_driver(radio, board); VolatileRTCClock fallback_clock; AutoDiscoverRTCClock rtc_clock(fallback_clock); -MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); -EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#if ENV_INCLUDE_GPS + #include + MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); + EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else + EnvironmentSensorManager sensors; +#endif #ifdef DISPLAY_CLASS DISPLAY_CLASS display; From 0defa837d8394932463044ccfc62e87d259cdf99 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Fri, 23 May 2025 19:12:32 +1000 Subject: [PATCH 13/16] * EnvironmentSensorManager: some tidy ups --- .../sensors/EnvironmentSensorManager.cpp | 22 ++++++++++++++---- .../sensors/EnvironmentSensorManager.h | 23 ------------------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index c300cbe4..dda1fd55 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -1,15 +1,29 @@ #include "EnvironmentSensorManager.h" #if ENV_INCLUDE_AHTX0 +#define TELEM_AHTX_ADDRESS 0x38 // AHT10, AHT20 temperature and humidity sensor I2C address +#include static Adafruit_AHTX0 AHTX0; #endif + #if ENV_INCLUDE_BME280 +#define TELEM_BME280_ADDRESS 0x76 // BME280 environmental sensor I2C address +#define TELEM_BME280_SEALEVELPRESSURE_HPA (1013.25) // Athmospheric pressure at sea level +#include static Adafruit_BME280 BME280; #endif + #if ENV_INCLUDE_INA3221 +#define TELEM_INA3221_ADDRESS 0x42 // INA3221 3 channel current sensor I2C address +#define TELEM_INA3221_SHUNT_VALUE 0.100 // most variants will have a 0.1 ohm shunts +#define TELEM_INA3221_NUM_CHANNELS 3 +#include static Adafruit_INA3221 INA3221; #endif + #if ENV_INCLUDE_INA219 +#define TELEM_INA219_ADDRESS 0x40 // INA219 single channel current sensor I2C address +#include static Adafruit_INA219 INA219(TELEM_INA219_ADDRESS); #endif @@ -128,15 +142,17 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen int EnvironmentSensorManager::getNumSettings() const { #if ENV_INCLUDE_GPS return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected + #else + return 0; #endif - return NULL; } const char* EnvironmentSensorManager::getSettingName(int i) const { #if ENV_INCLUDE_GPS return (gps_detected && i == 0) ? "gps" : NULL; + #else + return NULL; #endif - return NULL; } const char* EnvironmentSensorManager::getSettingValue(int i) const { @@ -184,10 +200,8 @@ void EnvironmentSensorManager::initBasicGPS() { MESH_DEBUG_PRINTLN("No GPS detected"); digitalWrite(PIN_GPS_EN, LOW); } - } - void EnvironmentSensorManager::start_gps() { gps_active = true; pinMode(PIN_GPS_EN, OUTPUT); diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index 2a72f2d0..c9ec6870 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -4,29 +4,6 @@ #include #include - -#if ENV_INCLUDE_AHTX0 -#define TELEM_AHTX_ADDRESS 0x38 // AHT10, AHT20 temperature and humidity sensor I2C address -#include -#endif -#if ENV_INCLUDE_BME280 -#define TELEM_BME280_ADDRESS 0x76 // BME280 environmental sensor I2C address -#define TELEM_BME280_SEALEVELPRESSURE_HPA (1013.25) // Athmospheric pressure at sea level -#include -#endif -#if ENV_INCLUDE_INA3221 -#define TELEM_INA3221_ADDRESS 0x42 // INA3221 3 channel current sensor I2C address -#define TELEM_INA3221_SHUNT_VALUE 0.100 // most variants will have a 0.1 ohm shunts -#define TELEM_INA3221_NUM_CHANNELS 3 -#include -#endif -#if ENV_INCLUDE_INA219 -#define TELEM_INA219_ADDRESS 0x40 // INA219 single channel current sensor I2C address -#include -#endif - - - class EnvironmentSensorManager : public SensorManager { protected: int next_available_channel = TELEM_CHANNEL_SELF + 1; From f8b45ec01ed30ebbfaff089d728ad923c6e52c25 Mon Sep 17 00:00:00 2001 From: Normunds Gavars Date: Fri, 23 May 2025 21:24:02 +0300 Subject: [PATCH 14/16] Add sensor support to Xiao Nrf --- variants/xiao_nrf52/platformio.ini | 12 ++++++++++++ variants/xiao_nrf52/target.cpp | 2 +- variants/xiao_nrf52/target.h | 4 ++-- variants/xiao_nrf52/variant.h | 4 ++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini index 5083b1a3..2f468f4f 100644 --- a/variants/xiao_nrf52/platformio.ini +++ b/variants/xiao_nrf52/platformio.ini @@ -16,6 +16,11 @@ lib_ignore = lib_deps = ${nrf52_base.lib_deps} rweather/Crypto @ ^0.4.0 + adafruit/Adafruit INA3221 Library @ ^1.0.1 + adafruit/Adafruit INA219 @ ^1.2.3 + adafruit/Adafruit AHTX0 @ ^2.0.5 + adafruit/Adafruit BME280 Library @ ^2.3.0 + [Xiao_nrf52] extends = nrf52840_xiao @@ -35,8 +40,15 @@ build_flags = ${nrf52840_xiao.build_flags} -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 + -D PIN_WIRE_SCL=6 + -D PIN_WIRE_SDA=7 + -D ENV_INCLUDE_AHTX0=1 + -D ENV_INCLUDE_BME280=1 + -D ENV_INCLUDE_INA3221=1 + -D ENV_INCLUDE_INA219=1 build_src_filter = ${nrf52840_xiao.build_src_filter} + + + + +<../variants/xiao_nrf52> debug_tool = jlink diff --git a/variants/xiao_nrf52/target.cpp b/variants/xiao_nrf52/target.cpp index 1d23e76a..c78ea159 100644 --- a/variants/xiao_nrf52/target.cpp +++ b/variants/xiao_nrf52/target.cpp @@ -9,7 +9,7 @@ RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BU WRAPPER_CLASS radio_driver(radio, board); VolatileRTCClock rtc_clock; -SensorManager sensors; +EnvironmentSensorManager sensors; #ifndef LORA_CR #define LORA_CR 5 diff --git a/variants/xiao_nrf52/target.h b/variants/xiao_nrf52/target.h index 868664b5..ec298a43 100644 --- a/variants/xiao_nrf52/target.h +++ b/variants/xiao_nrf52/target.h @@ -6,12 +6,12 @@ #include #include #include -#include +#include extern XiaoNrf52Board board; extern WRAPPER_CLASS radio_driver; extern VolatileRTCClock rtc_clock; -extern SensorManager sensors; +extern EnvironmentSensorManager sensors; bool radio_init(); uint32_t radio_get_rng_seed(); diff --git a/variants/xiao_nrf52/variant.h b/variants/xiao_nrf52/variant.h index 0d0950af..d941463e 100644 --- a/variants/xiao_nrf52/variant.h +++ b/variants/xiao_nrf52/variant.h @@ -110,8 +110,8 @@ static const uint8_t A5 = PIN_A5; // Wire Interfaces #define WIRE_INTERFACES_COUNT (1) -#define PIN_WIRE_SDA (17) // 4 and 5 are used for the sx1262 ! -#define PIN_WIRE_SCL (16) // use WIRE1_SDA +// #define PIN_WIRE_SDA (17) // 4 and 5 are used for the sx1262 ! +// #define PIN_WIRE_SCL (16) // use WIRE1_SDA static const uint8_t SDA = PIN_WIRE_SDA; static const uint8_t SCL = PIN_WIRE_SCL; From 5cb2ba8c6283a62b2a2802129f8c47717d85ce72 Mon Sep 17 00:00:00 2001 From: recrof Date: Sat, 24 May 2025 07:05:33 +0200 Subject: [PATCH 15/16] added repeater and room server roles to heltec wireless tracker --- variants/heltec_tracker/platformio.ini | 44 ++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/variants/heltec_tracker/platformio.ini b/variants/heltec_tracker/platformio.ini index f54eda86..d62771f4 100644 --- a/variants/heltec_tracker/platformio.ini +++ b/variants/heltec_tracker/platformio.ini @@ -31,6 +31,8 @@ build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_tracker> lib_deps = ${esp32_base.lib_deps} + stevemarple/MicroNMEA @ ^2.0.6 + adafruit/Adafruit ST7735 and ST7789 Library @ ^1.11.0 [env:Heltec_Wireless_Tracker_companion_radio_ble] extends = Heltec_tracker_base @@ -56,5 +58,43 @@ build_src_filter = ${Heltec_tracker_base.build_src_filter} lib_deps = ${Heltec_tracker_base.lib_deps} densaugeo/base64 @ ~1.4.0 - stevemarple/MicroNMEA @ ^2.0.6 - adafruit/Adafruit ST7735 and ST7789 Library @ ^1.11.0 + +[env:Heltec_Wireless_Tracker_repeater] +extends = Heltec_tracker_base +build_flags = + ${Heltec_tracker_base.build_flags} + -D DISPLAY_ROTATION=1 + -D DISPLAY_CLASS=ST7735Display + -D ADVERT_NAME='"Heltec Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_tracker_base.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_tracker_base.lib_deps} + ${esp32_ota.lib_deps} + +[env:Heltec_Wireless_Tracker_room_server] +extends = Heltec_tracker_base +build_flags = + ${Heltec_tracker_base.build_flags} + -D DISPLAY_ROTATION=1 + -D DISPLAY_CLASS=ST7735Display + -D ADVERT_NAME='"Heltec Room"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_tracker_base.build_src_filter} + + + +<../examples/simple_room_server> +lib_deps = + ${Heltec_tracker_base.lib_deps} + ${esp32_ota.lib_deps} From 0bad7ee1068e66965a3569e7f8b748af8ed14dee Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Sat, 24 May 2025 16:19:19 +1000 Subject: [PATCH 16/16] * ver bump to 1.6.2 --- examples/companion_radio/main.cpp | 4 ++-- examples/simple_repeater/main.cpp | 4 ++-- examples/simple_room_server/main.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 03a8c90a..13db88c0 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -81,11 +81,11 @@ static uint32_t _atoi(const char* sp) { #define FIRMWARE_VER_CODE 5 #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "17 May 2025" + #define FIRMWARE_BUILD_DATE "24 May 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.6.1" + #define FIRMWARE_VERSION "v1.6.2" #endif #define CMD_APP_START 1 diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 5e04de54..12c843b7 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -22,11 +22,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "17 May 2025" + #define FIRMWARE_BUILD_DATE "24 May 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.6.1" + #define FIRMWARE_VERSION "v1.6.2" #endif #ifndef LORA_FREQ diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 5ffef515..dad7ce78 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -22,11 +22,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "17 May 2025" + #define FIRMWARE_BUILD_DATE "24 May 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.6.1" + #define FIRMWARE_VERSION "v1.6.2" #endif #ifndef LORA_FREQ