From d59724acd05bbcad41cbfb1abfdf7c5678053af5 Mon Sep 17 00:00:00 2001 From: recrof Date: Fri, 5 Sep 2025 16:21:19 +0200 Subject: [PATCH] new variant: RAK WisMesh Tag --- .../sensors/EnvironmentSensorManager.cpp | 34 ++--- .../rak_wismesh_tag/RAKWismeshTagBoard.cpp | 81 ++++++++++++ variants/rak_wismesh_tag/RAKWismeshTagBoard.h | 80 ++++++++++++ variants/rak_wismesh_tag/platformio.ini | 116 +++++++++++++++++ variants/rak_wismesh_tag/target.cpp | 54 ++++++++ variants/rak_wismesh_tag/target.h | 27 ++++ variants/rak_wismesh_tag/variant.cpp | 21 +++ variants/rak_wismesh_tag/variant.h | 121 ++++++++++++++++++ 8 files changed, 518 insertions(+), 16 deletions(-) create mode 100644 variants/rak_wismesh_tag/RAKWismeshTagBoard.cpp create mode 100644 variants/rak_wismesh_tag/RAKWismeshTagBoard.h create mode 100644 variants/rak_wismesh_tag/platformio.ini create mode 100644 variants/rak_wismesh_tag/target.cpp create mode 100644 variants/rak_wismesh_tag/target.h create mode 100644 variants/rak_wismesh_tag/variant.cpp create mode 100644 variants/rak_wismesh_tag/variant.h diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index f444b67b..df08ed78 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -66,8 +66,8 @@ static Adafruit_INA260 INA260; #endif #if ENV_INCLUDE_INA226 -#define TELEM_INA226_ADDRESS 0x44 -#define TELEM_INA226_SHUNT_VALUE 0.100 +#define TELEM_INA226_ADDRESS 0x44 +#define TELEM_INA226_SHUNT_VALUE 0.100 #define TELEM_INA226_MAX_AMP 0.8 #include static INA226 INA226(TELEM_INA226_ADDRESS); @@ -85,7 +85,11 @@ static Adafruit_MLX90614 MLX90614; static Adafruit_VL53L0X VL53L0X; #endif -#if ENV_INCLUDE_GPS && RAK_BOARD +#if ENV_INCLUDE_GPS && defined(RAK_BOARD) && !defined(RAK_WISMESH_TAG) +#define RAK_WISBLOCK_GPS +#endif + +#ifdef RAK_WISBLOCK_GPS static uint32_t gpsResetPin = 0; static bool i2cGPSFlag = false; static bool serialGPSFlag = false; @@ -96,7 +100,7 @@ static SFE_UBLOX_GNSS ublox_GNSS; bool EnvironmentSensorManager::begin() { #if ENV_INCLUDE_GPS - #if RAK_BOARD + #ifdef RAK_WISBLOCK_GPS rakGPSInit(); //probe base board/sockets for GPS #else initBasicGPS(); @@ -457,7 +461,7 @@ void EnvironmentSensorManager::initBasicGPS() { gps_active = false; //Set GPS visibility off until setting is changed } -#ifdef RAK_BOARD +#ifdef RAK_WISBLOCK_GPS void EnvironmentSensorManager::rakGPSInit(){ Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX); @@ -531,7 +535,7 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){ void EnvironmentSensorManager::start_gps() { gps_active = true; - #ifdef RAK_BOARD + #ifdef RAK_WISBLOCK_GPS pinMode(gpsResetPin, OUTPUT); digitalWrite(gpsResetPin, HIGH); return; @@ -547,7 +551,7 @@ void EnvironmentSensorManager::start_gps() { void EnvironmentSensorManager::stop_gps() { gps_active = false; - #ifdef RAK_BOARD + #ifdef RAK_WISBLOCK_GPS pinMode(gpsResetPin, OUTPUT); digitalWrite(gpsResetPin, LOW); return; @@ -568,13 +572,7 @@ void EnvironmentSensorManager::loop() { if (millis() > next_gps_update) { if(gps_active){ - #ifndef RAK_BOARD - 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); - } - #else + #ifdef RAK_WISBLOCK_GPS if(i2cGPSFlag){ node_lat = ((double)ublox_GNSS.getLatitude())/10000000.; node_lon = ((double)ublox_GNSS.getLongitude())/10000000.; @@ -585,8 +583,12 @@ void EnvironmentSensorManager::loop() { node_lon = ((double)_location->getLongitude())/1000000.; MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); } - //else - //MESH_DEBUG_PRINTLN("No valid GPS data"); + #else + 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); + } #endif } next_gps_update = millis() + 1000; diff --git a/variants/rak_wismesh_tag/RAKWismeshTagBoard.cpp b/variants/rak_wismesh_tag/RAKWismeshTagBoard.cpp new file mode 100644 index 00000000..68ce2fd8 --- /dev/null +++ b/variants/rak_wismesh_tag/RAKWismeshTagBoard.cpp @@ -0,0 +1,81 @@ +#include +#include "RAKWismeshTagBoard.h" + +#include +#include + +static BLEDfu bledfu; + +static void connect_callback(uint16_t conn_handle) { + (void)conn_handle; + MESH_DEBUG_PRINTLN("BLE client connected"); +} + +static void disconnect_callback(uint16_t conn_handle, uint8_t reason) { + (void)conn_handle; + (void)reason; + + MESH_DEBUG_PRINTLN("BLE client disconnected"); +} + +void RAKWismeshTagBoard::begin() { + // for future use, sub-classes SHOULD call this from their begin() + startup_reason = BD_STARTUP_NORMAL; + pinMode(PIN_VBAT_READ, INPUT); + pinMode(PIN_USER_BTN, INPUT_PULLUP); + + Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); + Wire.begin(); + + pinMode(SX126X_POWER_EN, OUTPUT); + digitalWrite(SX126X_POWER_EN, HIGH); + delay(10); // give sx1262 some time to power up +} + +bool RAKWismeshTagBoard::startOTAUpdate(const char* id, char reply[]) { + // Config the peripheral connection with maximum bandwidth + // more SRAM required by SoftDevice + // Note: All config***() function must be called before begin() + Bluefruit.configPrphBandwidth(BANDWIDTH_MAX); + Bluefruit.configPrphConn(92, BLE_GAP_EVENT_LENGTH_MIN, 16, 16); + + Bluefruit.begin(1, 0); + // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4 + Bluefruit.setTxPower(4); + // Set the BLE device name + Bluefruit.setName("WISMESHTAG_OTA"); + + Bluefruit.Periph.setConnectCallback(connect_callback); + Bluefruit.Periph.setDisconnectCallback(disconnect_callback); + + // To be consistent OTA DFU should be added first if it exists + bledfu.begin(); + + // Set up and start advertising + // Advertising packet + Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); + Bluefruit.Advertising.addTxPower(); + Bluefruit.Advertising.addName(); + + /* Start Advertising + - Enable auto advertising if disconnected + - Interval: fast mode = 20 ms, slow mode = 152.5 ms + - Timeout for fast mode is 30 seconds + - Start(timeout) with timeout = 0 will advertise forever (until connected) + + For recommended advertising interval + https://developer.apple.com/library/content/qa/qa1931/_index.html + */ + Bluefruit.Advertising.restartOnDisconnect(true); + Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms + Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode + Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds + + uint8_t mac_addr[6]; + memset(mac_addr, 0, sizeof(mac_addr)); + Bluefruit.getAddr(mac_addr); + sprintf(reply, "OK - mac: %02X:%02X:%02X:%02X:%02X:%02X", + mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); + + return true; +} diff --git a/variants/rak_wismesh_tag/RAKWismeshTagBoard.h b/variants/rak_wismesh_tag/RAKWismeshTagBoard.h new file mode 100644 index 00000000..22af6f74 --- /dev/null +++ b/variants/rak_wismesh_tag/RAKWismeshTagBoard.h @@ -0,0 +1,80 @@ +#pragma once + +#include +#include + +// built-ins +#define PIN_VBAT_READ 5 +#define ADC_MULTIPLIER (3 * 1.73 * 1.187 * 1000) + +class RAKWismeshTagBoard : public mesh::MainBoard { +protected: + uint8_t startup_reason; + +public: + void begin(); + uint8_t getStartupReason() const override { return startup_reason; } + +#if defined(P_LORA_TX_LED) && defined(LED_STATE_ON) + void onBeforeTransmit() override { + digitalWrite(P_LORA_TX_LED, LED_STATE_ON); // turn TX LED on + } + void onAfterTransmit() override { + digitalWrite(P_LORA_TX_LED, !LED_STATE_ON); // turn TX LED off + } +#endif + + #define BATTERY_SAMPLES 8 + + uint16_t getBattMilliVolts() override { + 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; + } + + const char* getManufacturerName() const override { + return "RAK WisMesh Tag"; + } + + void reboot() override { + NVIC_SystemReset(); + } + + bool startOTAUpdate(const char* id, char reply[]) override; + + void powerOff() override { + #ifdef BUZZER_EN + digitalWrite(BUZZER_EN, LOW); + #endif + + #ifdef PIN_GPS_EN + digitalWrite(PIN_GPS_EN, LOW); + #endif + + // set led on and wait for button release before poweroff + #ifdef LED_PIN + digitalWrite(LED_PIN, HIGH); + #endif + #ifdef BUTTON_PIN + while(digitalRead(BUTTON_PIN)); + #endif + #ifdef LED_GREEN + digitalWrite(LED_GREEN, LOW); + #endif + #ifdef LED_BLUE + digitalWrite(LED_BLUE, LOW); + #endif + + #ifdef BUTTON_PIN + nrf_gpio_cfg_sense_input(digitalPinToInterrupt(BUTTON_PIN), NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); + #endif + + sd_power_system_off(); + } +}; diff --git a/variants/rak_wismesh_tag/platformio.ini b/variants/rak_wismesh_tag/platformio.ini new file mode 100644 index 00000000..6f7d28ba --- /dev/null +++ b/variants/rak_wismesh_tag/platformio.ini @@ -0,0 +1,116 @@ +[rak_wismesh_tag] +extends = nrf52_base +platform = https://github.com/maxgerhardt/platform-nordicnrf52.git#rak +board = wiscore_rak4631 +board_check = true +build_flags = ${nrf52_base.build_flags} + ${sensor_base.build_flags} + -I variants/rak_wismesh_tag + -I src/helpers/ui + -D RAK_WISMESH_TAG + -D RAK_BOARD + -D P_LORA_TX_LED=LED_GREEN + -D P_LORA_DIO_1=SX126X_DIO1 + -D P_LORA_NSS=PIN_SPI_NSS + -D P_LORA_RESET=SX126X_RESET + -D P_LORA_BUSY=SX126X_BUSY + -D P_LORA_SCLK=PIN_SPI_SCK + -D P_LORA_MISO=PIN_SPI_MISO + -D P_LORA_MOSI=PIN_SPI_MOSI + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D DISPLAY_CLASS=NullDisplayDriver + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=140 + -D SX126X_RX_BOOSTED_GAIN=1 + -D PIN_BUZZER=21 + -D PIN_BOARD_SDA=PIN_WIRE_SDA + -D PIN_BOARD_SCL=PIN_WIRE_SCL +build_src_filter = ${nrf52_base.build_src_filter} + +<../variants/rak_wismesh_tag> + + + + + + + + +lib_deps = + ${nrf52_base.lib_deps} + ${sensor_base.lib_deps} + +[env:RAK_WisMesh_Tag_Repeater] +extends = rak_wismesh_tag +build_flags = + ${rak_wismesh_tag.build_flags} + -D ADVERT_NAME='"RAK WM 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 = ${rak_wismesh_tag.build_src_filter} + +<../examples/simple_repeater> + +[env:RAK_WisMesh_Tag_room_server] +extends = rak_wismesh_tag +build_flags = + ${rak_wismesh_tag.build_flags} + -D ADVERT_NAME='"RAK WM 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 = ${rak_wismesh_tag.build_src_filter} + +<../examples/simple_room_server> + +[env:RAK_WisMesh_Tag_companion_radio_usb] +extends = rak_wismesh_tag +build_flags = + ${rak_wismesh_tag.build_flags} + -I examples/companion_radio/ui-orig + -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 = ${rak_wismesh_tag.build_src_filter} + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> +lib_deps = + ${rak_wismesh_tag.lib_deps} + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:RAK_WisMesh_Tag_companion_radio_ble] +extends = rak_wismesh_tag +build_flags = + ${rak_wismesh_tag.build_flags} + -I examples/companion_radio/ui-orig + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D OFFLINE_QUEUE_SIZE=256 +; -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 +build_src_filter = ${rak_wismesh_tag.build_src_filter} + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> +lib_deps = + ${rak4631.lib_deps} + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:RAK_WisMesh_Tag_sensor] +extends = rak4631 +build_flags = + ${rak4631.build_flags} + -D ADVERT_NAME='"RAK WM Sensor"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 +build_src_filter = ${rak4631.build_src_filter} + +<../examples/simple_sensor> \ No newline at end of file diff --git a/variants/rak_wismesh_tag/target.cpp b/variants/rak_wismesh_tag/target.cpp new file mode 100644 index 00000000..2bd30864 --- /dev/null +++ b/variants/rak_wismesh_tag/target.cpp @@ -0,0 +1,54 @@ +#include +#include "target.h" +#include + +RAKWismeshTagBoard board; + +#ifndef PIN_USER_BTN + #define PIN_USER_BTN (-1) +#endif + +#ifdef DISPLAY_CLASS + DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true); +#endif + +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); + +WRAPPER_CLASS radio_driver(radio, board); + +VolatileRTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); + +#if ENV_INCLUDE_GPS + #include + MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); + EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else + EnvironmentSensorManager sensors; +#endif + +bool radio_init() { + rtc_clock.begin(Wire); + return radio.std_init(&SPI); +} + +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/rak_wismesh_tag/target.h b/variants/rak_wismesh_tag/target.h new file mode 100644 index 00000000..150d0831 --- /dev/null +++ b/variants/rak_wismesh_tag/target.h @@ -0,0 +1,27 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include + +#ifdef DISPLAY_CLASS + #include + extern DISPLAY_CLASS display; + #include + extern MomentaryButton user_btn; +#endif + +extern RAKWismeshTagBoard board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; +extern EnvironmentSensorManager 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/rak_wismesh_tag/variant.cpp b/variants/rak_wismesh_tag/variant.cpp new file mode 100644 index 00000000..ac3af5d2 --- /dev/null +++ b/variants/rak_wismesh_tag/variant.cpp @@ -0,0 +1,21 @@ +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 +}; + +void initVariant() { + // LEDs + pinMode(LED_BLUE, OUTPUT); + pinMode(LED_GREEN, OUTPUT); + digitalWrite(LED_BLUE, LOW); + digitalWrite(LED_GREEN, LOW); + + // GPS + pinMode(PIN_GPS_EN, OUTPUT); + digitalWrite(PIN_GPS_EN, HIGH); +} \ No newline at end of file diff --git a/variants/rak_wismesh_tag/variant.h b/variants/rak_wismesh_tag/variant.h new file mode 100644 index 00000000..b0e51efc --- /dev/null +++ b/variants/rak_wismesh_tag/variant.h @@ -0,0 +1,121 @@ +/* + * variant.h + * Copyright (C) 2023 Seeed K.K. + * MIT License + */ + +#pragma once + +#include "WVariant.h" + +//////////////////////////////////////////////////////////////////////////////// +// Low frequency clock source + +#define USE_LFXO // 32.768 kHz crystal oscillator +#define VARIANT_MCK (64000000ul) + +#define WIRE_INTERFACES_COUNT (1) +#define PIN_TXCO (21) +//////////////////////////////////////////////////////////////////////////////// +// Power + +#define PIN_PWR_EN (12) + +#define BATTERY_PIN (5) +#define ADC_MULTIPLIER (1.73F) + +#define ADC_RESOLUTION (14) +#define BATTERY_SENSE_RES (12) + +#define AREF_VOLTAGE (3.0) + +//////////////////////////////////////////////////////////////////////////////// +// Number of pins + +#define PINS_COUNT (48) +#define NUM_DIGITAL_PINS (48) +#define NUM_ANALOG_INPUTS (6) +#define NUM_ANALOG_OUTPUTS (0) + +//////////////////////////////////////////////////////////////////////////////// +// UART pin definition + +#define PIN_SERIAL1_RX (15) +#define PIN_SERIAL1_TX (16) + +//////////////////////////////////////////////////////////////////////////////// +// I2C pin definition +#define WIRE_INTERFACES_COUNT (1) +#define PIN_WIRE_SDA (25) +#define PIN_WIRE_SCL (24) + +//////////////////////////////////////////////////////////////////////////////// +// SPI pin definition + +#define SPI_INTERFACES_COUNT (2) + +#define PIN_SPI_MISO (45) +#define PIN_SPI_MOSI (44) +#define PIN_SPI_SCK (43) +#define PIN_SPI_NSS (42) + +//////////////////////////////////////////////////////////////////////////////// +// Builtin LEDs + +#define LED_RED (-1) +#define LED_BLUE (36) +#define LED_GREEN (35) + +//#define PIN_STATUS_LED LED_BLUE +#define LED_BUILTIN LED_GREEN +#define LED_PIN LED_GREEN +#define LED_STATE_ON HIGH + +//////////////////////////////////////////////////////////////////////////////// +// Builtin buttons + +#define PIN_BUTTON1 (9) +#define BUTTON_PIN PIN_BUTTON1 +#define PIN_USER_BTN BUTTON_PIN + +#define PIN_BUTTON2 (12) +#define BUTTON_PIN2 PIN_BUTTON2 + +//////////////////////////////////////////////////////////////////////////////// +// Lora + +#define USE_SX1262 +#define LORA_CS (42) +#define SX126X_DIO1 (47) +#define SX126X_BUSY (46) +#define SX126X_RESET (38) +#define SX126X_POWER_EN (37) +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +//////////////////////////////////////////////////////////////////////////////// +// SPI1 + +#define PIN_SPI1_MISO (29) +#define PIN_SPI1_MOSI (30) +#define PIN_SPI1_SCK (3) + +// GxEPD2 needs that for a panel that is not even used ! +extern const int MISO; +extern const int MOSI; +extern const int SCK; + +//////////////////////////////////////////////////////////////////////////////// +// GPS + +#define PIN_GPS_RX (PIN_SERIAL1_TX) +#define PIN_GPS_TX (PIN_SERIAL1_RX) +#define PIN_GPS_PPS (17) +#define PIN_GPS_EN (34) + +/////////////////////////////////////////////////////////////////////////////// +// OTHER PINS +#define PIN_AREF (2) +#define PIN_NFC1 (9) +#define PIN_NFC2 (10) +#define PIN_BUZZER (21)