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/examples/companion_radio/UITask.cpp b/examples/companion_radio/UITask.cpp index f97b47f4..f4e3fb0b 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: @@ -232,40 +234,49 @@ 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; + #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; + 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 + 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/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 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/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 6d39e905..dda1fd55 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -1,12 +1,59 @@ #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 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()); @@ -19,7 +66,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; @@ -27,30 +76,39 @@ bool EnvironmentSensorManager::begin() { INA219_initialized = false; MESH_DEBUG_PRINTLN("INA219 was not found at I2C address %02X", TELEM_INA219_ADDRESS); } - - 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); - } + #endif return true; } bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { 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 @@ -64,27 +122,110 @@ 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; -} \ No newline at end of file +} + + +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 +} + +const char* EnvironmentSensorManager::getSettingName(int i) const { + #if ENV_INCLUDE_GPS + return (gps_detected && i == 0) ? "gps" : NULL; + #else + return 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(); + } else { + start_gps(); + } + return true; + } + #endif + return false; // not supported +} + +#if ENV_INCLUDE_GPS +void EnvironmentSensorManager::initBasicGPS() { + 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; + } +} +#endif \ No newline at end of file diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index fa3a1a1e..c9ec6870 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -1,32 +1,42 @@ #pragma once -#include #include -#include -#include -#include -#include - -#define TELEM_AHTX_ADDRESS 0x38 // AHT10, AHT20 temperature and humidity sensor I2C address -#define TELEM_BME280_ADDRESS 0x76 // BME280 environmental sensor I2C address -#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 - -#define TELEM_BME280_SEALEVELPRESSURE_HPA (1013.25) // Athmospheric pressure at sea level +#include +#include 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_detected = false; + bool gps_active = false; + + #if ENV_INCLUDE_GPS + LocationProvider* _location; + void start_gps(); + void stop_gps(); + void initBasicGPS(); + #endif + + 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; + 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; + bool setSettingValue(const char* name, const char* value) override; }; 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/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} diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 568e20d7..11f73d81 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -13,6 +13,14 @@ 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 + -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} + + @@ -23,7 +31,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} @@ -99,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> diff --git a/variants/promicro/target.cpp b/variants/promicro/target.cpp index 841bd1dc..2369bd7a 100644 --- a/variants/promicro/target.cpp +++ b/variants/promicro/target.cpp @@ -2,6 +2,9 @@ #include "target.h" #include +#if ENV_INCLUDE_GPS +#endif + PromicroBoard board; RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); @@ -10,7 +13,13 @@ WRAPPER_CLASS radio_driver(radio, board); VolatileRTCClock fallback_clock; AutoDiscoverRTCClock rtc_clock(fallback_clock); -EnvironmentSensorManager sensors; +#if ENV_INCLUDE_GPS + #include + MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); + EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else + EnvironmentSensorManager sensors; +#endif #ifdef DISPLAY_CLASS DISPLAY_CLASS display; 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..c39b69b1 --- /dev/null +++ b/variants/rak3x72/target.h @@ -0,0 +1,35 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#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; +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/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 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; 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;