From 8f6b2b75d7cfd1dace9eea34cac73ce33de14e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Br=C3=A1zio?= Date: Sun, 15 Jun 2025 23:48:49 +0100 Subject: [PATCH 1/6] Waveshare RP2040-LoRa board support --- platformio.ini | 2 + src/helpers/rp2040/WaveshareBoard.cpp | 29 +++++ src/helpers/rp2040/WaveshareBoard.h | 65 +++++++++++ variants/picow/platformio.ini | 2 +- variants/waveshare_rp2040_lora/platformio.ini | 107 ++++++++++++++++++ variants/waveshare_rp2040_lora/target.cpp | 81 +++++++++++++ variants/waveshare_rp2040_lora/target.h | 21 ++++ 7 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 src/helpers/rp2040/WaveshareBoard.cpp create mode 100644 src/helpers/rp2040/WaveshareBoard.h create mode 100644 variants/waveshare_rp2040_lora/platformio.ini create mode 100644 variants/waveshare_rp2040_lora/target.cpp create mode 100644 variants/waveshare_rp2040_lora/target.h diff --git a/platformio.ini b/platformio.ini index 2c3ffd83..ad3ce4eb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -70,6 +70,8 @@ lib_deps = [rp2040_base] extends = arduino_base +platform = https://github.com/maxgerhardt/platform-raspberrypi.git +board_build.core = earlephilhower build_flags = ${arduino_base.build_flags} -D RP2040_PLATFORM diff --git a/src/helpers/rp2040/WaveshareBoard.cpp b/src/helpers/rp2040/WaveshareBoard.cpp new file mode 100644 index 00000000..f4154dbe --- /dev/null +++ b/src/helpers/rp2040/WaveshareBoard.cpp @@ -0,0 +1,29 @@ +#include "WaveshareBoard.h" + +#include +#include + +void WaveshareBoard::begin() { + // for future use, sub-classes SHOULD call this from their begin() + startup_reason = BD_STARTUP_NORMAL; + +#ifdef PIN_LED_BUILTIN + pinMode(PIN_LED_BUILTIN, OUTPUT); +#endif + +#ifdef PIN_VBAT_READ + pinMode(PIN_VBAT_READ, INPUT); +#endif + +#if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) + Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); +#endif + + Wire.begin(); + + delay(10); // give sx1262 some time to power up +} + +bool WaveshareBoard::startOTAUpdate(const char *id, char reply[]) { + return false; +} diff --git a/src/helpers/rp2040/WaveshareBoard.h b/src/helpers/rp2040/WaveshareBoard.h new file mode 100644 index 00000000..0aa136ab --- /dev/null +++ b/src/helpers/rp2040/WaveshareBoard.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include + +// LoRa radio module pins for Waveshare RP2040-LoRa-HF/LF +// https://files.waveshare.com/wiki/RP2040-LoRa/Rp2040-lora-sch.pdf + +#define P_LORA_DIO_1 16 +#define P_LORA_NSS 13 // CS +#define P_LORA_RESET 23 +#define P_LORA_BUSY 18 +#define P_LORA_SCLK 14 +#define P_LORA_MISO 24 +#define P_LORA_MOSI 15 + +#define SX126X_DIO2_AS_RF_SWITCH true +#define SX126X_DIO3_TCXO_VOLTAGE 0 + +// built-ins +#define PIN_LED_BUILTIN 25 + +// This board has no built-in way to read battery voltage +// #define PIN_VBAT_READ 26 +// #define BATTERY_SAMPLES 8 +// #define ADC_MULTIPLIER (3.1 * 3.3 * 1000) // MT Uses 3.1 + +class WaveshareBoard : public mesh::MainBoard { +protected: + uint8_t startup_reason; + +public: + void begin(); + uint8_t getStartupReason() const override { return startup_reason; } + + void onBeforeTransmit() override { + digitalWrite(PIN_LED_BUILTIN, HIGH); // turn TX LED on + } + + void onAfterTransmit() override { + digitalWrite(PIN_LED_BUILTIN, LOW); // turn TX LED off + } + + uint16_t getBattMilliVolts() override { +#if defined(PIN_VBAT_READ) && defined(ADC_MULTIPLIER) + analogReadResolution(12); + + uint32_t raw = 0; + for (int i = 0; i < BATTERY_SAMPLES; i++) { + raw += analogRead(PIN_VBAT_READ); + } + raw = raw / BATTERY_SAMPLES; + + return (ADC_MULTIPLIER * raw) / 4096; +#else + return 0; +#endif + } + + const char *getManufacturerName() const override { return "Waveshare RP2040-LoRa"; } + + void reboot() override { rp2040.reboot(); } + + bool startOTAUpdate(const char *id, char reply[]) override; +}; diff --git a/variants/picow/platformio.ini b/variants/picow/platformio.ini index 0e925486..8b6c2506 100644 --- a/variants/picow/platformio.ini +++ b/variants/picow/platformio.ini @@ -14,7 +14,7 @@ build_flags = ${rp2040_base.build_flags} -D LORA_TX_POWER=22 -D SX126X_RX_BOOSTED_GAIN=1 build_src_filter = ${rp2040_base.build_src_filter} - + + + +<../variants/picow> lib_deps = ${rp2040_base.lib_deps} diff --git a/variants/waveshare_rp2040_lora/platformio.ini b/variants/waveshare_rp2040_lora/platformio.ini new file mode 100644 index 00000000..e84e57ad --- /dev/null +++ b/variants/waveshare_rp2040_lora/platformio.ini @@ -0,0 +1,107 @@ +; Waveshare RP2040-LoRa-HF/LF +; https://files.waveshare.com/wiki/RP2040-LoRa/Rp2040-lora-sch.pdf + +[waveshare_rp2040_lora] +extends = rp2040_base + +board = pico +board_build.filesystem_size = 0.5m + +build_flags = ${rp2040_base.build_flags} + -I variants/waveshare_rp2040_lora + -D SX126X_CURRENT_LIMIT=130 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_RX_BOOSTED_GAIN=1 +; Debug options + ; -D DEBUG_RP2040_WIRE=1 + ; -D DEBUG_RP2040_SPI=1 + ; -D DEBUG_RP2040_CORE=1 + ; -D RADIOLIB_DEBUG_SPI=1 + ; -D DEBUG_RP2040_PORT=Serial + +build_src_filter = ${rp2040_base.build_src_filter} + + + +<../variants/waveshare_rp2040_lora> + +lib_deps = ${rp2040_base.lib_deps} + +[env:waveshare_rp2040_lora_Repeater] +extends = waveshare_rp2040_lora +build_flags = ${waveshare_rp2040_lora.build_flags} + -D ADVERT_NAME='"Waveshare RP2040-LoRa 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 = ${waveshare_rp2040_lora.build_src_filter} + +<../examples/simple_repeater> + +[env:waveshare_rp2040_lora_room_server] +extends = waveshare_rp2040_lora +build_flags = ${waveshare_rp2040_lora.build_flags} + -D ADVERT_NAME='"Test 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 = ${waveshare_rp2040_lora.build_src_filter} + +<../examples/simple_room_server> + +[env:waveshare_rp2040_lora_companion_radio_usb] +extends = waveshare_rp2040_lora +build_flags = ${waveshare_rp2040_lora.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${waveshare_rp2040_lora.build_src_filter} + +<../examples/companion_radio> +lib_deps = ${waveshare_rp2040_lora.lib_deps} + densaugeo/base64 @ ~1.4.0 + +; [env:waveshare_rp2040_lora_companion_radio_ble] +; extends = waveshare_rp2040_lora +; build_flags = ${waveshare_rp2040_lora.build_flags} +; -D MAX_CONTACTS=100 +; -D MAX_GROUP_CHANNELS=8 +; -D BLE_PIN_CODE=123456 +; -D BLE_DEBUG_LOGGING=1 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${waveshare_rp2040_lora.build_src_filter} +; +<../examples/companion_radio> +; lib_deps = ${waveshare_rp2040_lora.lib_deps} +; densaugeo/base64 @ ~1.4.0 + +; [env:waveshare_rp2040_lora_companion_radio_wifi] +; extends = waveshare_rp2040_lora +; build_flags = ${waveshare_rp2040_lora.build_flags} +; -D MAX_CONTACTS=100 +; -D MAX_GROUP_CHANNELS=8 +; -D WIFI_DEBUG_LOGGING=1 +; -D WIFI_SSID='"myssid"' +; -D WIFI_PWD='"mypwd"' +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${waveshare_rp2040_lora.build_src_filter} +; +<../examples/companion_radio> +; lib_deps = ${waveshare_rp2040_lora.lib_deps} +; densaugeo/base64 @ ~1.4.0 + +[env:waveshare_rp2040_lora_terminal_chat] +extends = waveshare_rp2040_lora +build_flags = ${waveshare_rp2040_lora.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${waveshare_rp2040_lora.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = ${waveshare_rp2040_lora.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/waveshare_rp2040_lora/target.cpp b/variants/waveshare_rp2040_lora/target.cpp new file mode 100644 index 00000000..895f6db2 --- /dev/null +++ b/variants/waveshare_rp2040_lora/target.cpp @@ -0,0 +1,81 @@ +#include "target.h" + +#include +#include + +WaveshareBoard board; + +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI1); +WRAPPER_CLASS radio_driver(radio, board); + +VolatileRTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); +SensorManager sensors; + +#ifndef LORA_CR +#define LORA_CR 5 +#endif + +bool radio_init() { + rtc_clock.begin(Wire); + +#ifdef SX126X_DIO3_TCXO_VOLTAGE + float tcxo = SX126X_DIO3_TCXO_VOLTAGE; +#else + float tcxo = 1.6f; +#endif + + SPI1.setSCK(P_LORA_SCLK); + SPI1.setTX(P_LORA_MOSI); + SPI1.setRX(P_LORA_MISO); + + pinMode(P_LORA_NSS, OUTPUT); + digitalWrite(P_LORA_NSS, HIGH); + + SPI1.begin(false); + + int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, + LORA_TX_POWER, 8, tcxo); + + if (status != RADIOLIB_ERR_NONE) { + Serial.print("ERROR: radio init failed: "); + Serial.println(status); + return false; // fail + } + + radio.setCRC(1); + +#ifdef SX126X_CURRENT_LIMIT + radio.setCurrentLimit(SX126X_CURRENT_LIMIT); +#endif + +#ifdef SX126X_DIO2_AS_RF_SWITCH + radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); +#endif + +#ifdef SX126X_RX_BOOSTED_GAIN + radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); +#endif + + 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/waveshare_rp2040_lora/target.h b/variants/waveshare_rp2040_lora/target.h new file mode 100644 index 00000000..3ebe0570 --- /dev/null +++ b/variants/waveshare_rp2040_lora/target.h @@ -0,0 +1,21 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 + +#include +#include +#include +#include +#include +#include + +extern WaveshareBoard board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock 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(); From 52acae1fe7b76615cb1dc22e45d66a8438e387e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Br=C3=A1zio?= Date: Mon, 16 Jun 2025 02:01:04 +0100 Subject: [PATCH 2/6] Set default upload protocol --- platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index ad3ce4eb..b3aabad2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -70,8 +70,9 @@ lib_deps = [rp2040_base] extends = arduino_base -platform = https://github.com/maxgerhardt/platform-raspberrypi.git +upload_protocol = picotool board_build.core = earlephilhower +platform = https://github.com/maxgerhardt/platform-raspberrypi.git build_flags = ${arduino_base.build_flags} -D RP2040_PLATFORM From 3448db6e3649d330eced7004d821feff2f59b49f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Br=C3=A1zio?= Date: Mon, 16 Jun 2025 02:01:16 +0100 Subject: [PATCH 3/6] Rename LED pin --- src/helpers/rp2040/WaveshareBoard.cpp | 4 ++-- src/helpers/rp2040/WaveshareBoard.h | 15 +++++---------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/helpers/rp2040/WaveshareBoard.cpp b/src/helpers/rp2040/WaveshareBoard.cpp index f4154dbe..12e3d4f1 100644 --- a/src/helpers/rp2040/WaveshareBoard.cpp +++ b/src/helpers/rp2040/WaveshareBoard.cpp @@ -7,8 +7,8 @@ void WaveshareBoard::begin() { // for future use, sub-classes SHOULD call this from their begin() startup_reason = BD_STARTUP_NORMAL; -#ifdef PIN_LED_BUILTIN - pinMode(PIN_LED_BUILTIN, OUTPUT); +#ifdef P_LORA_TX_LED + pinMode(P_LORA_TX_LED, OUTPUT); #endif #ifdef PIN_VBAT_READ diff --git a/src/helpers/rp2040/WaveshareBoard.h b/src/helpers/rp2040/WaveshareBoard.h index 0aa136ab..492d54df 100644 --- a/src/helpers/rp2040/WaveshareBoard.h +++ b/src/helpers/rp2040/WaveshareBoard.h @@ -13,13 +13,11 @@ #define P_LORA_SCLK 14 #define P_LORA_MISO 24 #define P_LORA_MOSI 15 +#define P_LORA_TX_LED 25 #define SX126X_DIO2_AS_RF_SWITCH true #define SX126X_DIO3_TCXO_VOLTAGE 0 -// built-ins -#define PIN_LED_BUILTIN 25 - // This board has no built-in way to read battery voltage // #define PIN_VBAT_READ 26 // #define BATTERY_SAMPLES 8 @@ -33,13 +31,10 @@ public: void begin(); uint8_t getStartupReason() const override { return startup_reason; } - void onBeforeTransmit() override { - digitalWrite(PIN_LED_BUILTIN, HIGH); // turn TX LED on - } - - void onAfterTransmit() override { - digitalWrite(PIN_LED_BUILTIN, LOW); // turn TX LED off - } +#ifdef P_LORA_TX_LED + void onBeforeTransmit() override { digitalWrite(P_LORA_TX_LED, HIGH); } + void onAfterTransmit() override { digitalWrite(P_LORA_TX_LED, LOW); } +#endif uint16_t getBattMilliVolts() override { #if defined(PIN_VBAT_READ) && defined(ADC_MULTIPLIER) From f3e85a6fbaa004642dc18d62c7ac44c82c4985b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Br=C3=A1zio?= Date: Mon, 16 Jun 2025 16:57:43 +0100 Subject: [PATCH 4/6] Update SX126X_CURRENT_LIMIT --- variants/waveshare_rp2040_lora/platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/variants/waveshare_rp2040_lora/platformio.ini b/variants/waveshare_rp2040_lora/platformio.ini index e84e57ad..2730734d 100644 --- a/variants/waveshare_rp2040_lora/platformio.ini +++ b/variants/waveshare_rp2040_lora/platformio.ini @@ -9,7 +9,7 @@ board_build.filesystem_size = 0.5m build_flags = ${rp2040_base.build_flags} -I variants/waveshare_rp2040_lora - -D SX126X_CURRENT_LIMIT=130 + -D SX126X_CURRENT_LIMIT=140 -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 @@ -30,7 +30,7 @@ lib_deps = ${rp2040_base.lib_deps} [env:waveshare_rp2040_lora_Repeater] extends = waveshare_rp2040_lora build_flags = ${waveshare_rp2040_lora.build_flags} - -D ADVERT_NAME='"Waveshare RP2040-LoRa Repeater"' + -D ADVERT_NAME='"RP2040-LoRa Repeater"' -D ADVERT_LAT=0.0 -D ADVERT_LON=0.0 -D ADMIN_PASSWORD='"password"' @@ -43,7 +43,7 @@ build_src_filter = ${waveshare_rp2040_lora.build_src_filter} [env:waveshare_rp2040_lora_room_server] extends = waveshare_rp2040_lora build_flags = ${waveshare_rp2040_lora.build_flags} - -D ADVERT_NAME='"Test Room"' + -D ADVERT_NAME='"RP2040-LoRa Room"' -D ADVERT_LAT=0.0 -D ADVERT_LON=0.0 -D ADMIN_PASSWORD='"password"' From 110bd494072684638a3d512b325d72aeeab9592c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Br=C3=A1zio?= Date: Mon, 16 Jun 2025 19:51:53 +0100 Subject: [PATCH 5/6] VBAT schematic --- src/helpers/rp2040/WaveshareBoard.cpp | 3 ++- src/helpers/rp2040/WaveshareBoard.h | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/helpers/rp2040/WaveshareBoard.cpp b/src/helpers/rp2040/WaveshareBoard.cpp index 12e3d4f1..2e622933 100644 --- a/src/helpers/rp2040/WaveshareBoard.cpp +++ b/src/helpers/rp2040/WaveshareBoard.cpp @@ -16,7 +16,8 @@ void WaveshareBoard::begin() { #endif #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) - Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); + Wire.setSDA(PIN_BOARD_SDA); + Wire.setSCL(PIN_BOARD_SCL); #endif Wire.begin(); diff --git a/src/helpers/rp2040/WaveshareBoard.h b/src/helpers/rp2040/WaveshareBoard.h index 492d54df..a09c4b62 100644 --- a/src/helpers/rp2040/WaveshareBoard.h +++ b/src/helpers/rp2040/WaveshareBoard.h @@ -18,10 +18,20 @@ #define SX126X_DIO2_AS_RF_SWITCH true #define SX126X_DIO3_TCXO_VOLTAGE 0 -// This board has no built-in way to read battery voltage -// #define PIN_VBAT_READ 26 -// #define BATTERY_SAMPLES 8 -// #define ADC_MULTIPLIER (3.1 * 3.3 * 1000) // MT Uses 3.1 +/* + * This board has no built-in way to read battery voltage. + * Nevertheless it's very easy to make it work, you only require two 1% resistors. + * + * VSYS -- /\/\/\/\-- --+ + * 200k | + * +-- GPIO28 + * | + * GND -- /\/\/\/\-- --+ + * 100k + */ +#define PIN_VBAT_READ 28 +#define BATTERY_SAMPLES 8 +#define ADC_MULTIPLIER (3.0f * 3.3f * 1000) class WaveshareBoard : public mesh::MainBoard { protected: From 24464d0c4e994b4e0e993c68f532a8f6da6a3b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Br=C3=A1zio?= Date: Mon, 16 Jun 2025 21:28:59 +0100 Subject: [PATCH 6/6] Update VBAT schematic --- src/helpers/rp2040/WaveshareBoard.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/helpers/rp2040/WaveshareBoard.h b/src/helpers/rp2040/WaveshareBoard.h index a09c4b62..c2b5aff5 100644 --- a/src/helpers/rp2040/WaveshareBoard.h +++ b/src/helpers/rp2040/WaveshareBoard.h @@ -22,12 +22,15 @@ * This board has no built-in way to read battery voltage. * Nevertheless it's very easy to make it work, you only require two 1% resistors. * - * VSYS -- /\/\/\/\-- --+ - * 200k | - * +-- GPIO28 - * | - * GND -- /\/\/\/\-- --+ - * 100k + * BAT+ -----+ + * | + * VSYS --+ -/\/\/\/\- --+ + * 200k | + * +-- GPIO28 + * | + * GND --+ -/\/\/\/\- --+ + * | 100k + * BAT- -----+ */ #define PIN_VBAT_READ 28 #define BATTERY_SAMPLES 8