From 2282284fed4dbdc52ab6ff906c1c6a29a13807e3 Mon Sep 17 00:00:00 2001 From: YourName Date: Tue, 24 Feb 2026 17:02:08 +0100 Subject: [PATCH 1/3] Added firmware support for the SEIRv5 from Orobas --- variants/orobas_seir/partitions.csv | 7 ++ variants/orobas_seir/pins_arduino.h | 57 +++++++++++ variants/orobas_seir/platformio.ini | 141 ++++++++++++++++++++++++++++ variants/orobas_seir/target.cpp | 139 +++++++++++++++++++++++++++ variants/orobas_seir/target.h | 109 +++++++++++++++++++++ 5 files changed, 453 insertions(+) create mode 100644 variants/orobas_seir/partitions.csv create mode 100644 variants/orobas_seir/pins_arduino.h create mode 100644 variants/orobas_seir/platformio.ini create mode 100644 variants/orobas_seir/target.cpp create mode 100644 variants/orobas_seir/target.h diff --git a/variants/orobas_seir/partitions.csv b/variants/orobas_seir/partitions.csv new file mode 100644 index 000000000..e28da11c8 --- /dev/null +++ b/variants/orobas_seir/partitions.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size +nvs, data, nvs, 0x9000, 0x2000 +phy, data, phy, 0xF000, 0x1000 + +app0, app, factory, 0x10000, 0x400000 + +spiffs, data, spiffs, 0x410000, 0xBB0000 diff --git a/variants/orobas_seir/pins_arduino.h b/variants/orobas_seir/pins_arduino.h new file mode 100644 index 000000000..f7bb5eeb1 --- /dev/null +++ b/variants/orobas_seir/pins_arduino.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +// ===================================================================== +// Arduino core required pins for OROBAS SEIR v5 Board +// ===================================================================== + +// Pin 1 is used for LORA TX +#ifndef LED_BUILTIN +#define LED_BUILTIN 1 +#endif + +// LORA SCK (Serial Clock) +#ifndef SCK +#define SCK 10 +#endif + +// LORA MISO (Master In Slave Out) +#ifndef MISO +#define MISO 9 +#endif + +// LORA MOSI (Master Out Slave In) +#ifndef MOSI +#define MOSI 11 +#endif + +// LORA SS (Slave Select) +#ifndef SS +#define SS 6 +#endif + +// --------------------------------------------------------------------- +// I2C pins (not used on this board, but required by Arduino core) +// These dummy values are defined to satisfy Arduino core requirements +// but I2C is not implemented on this board +// --------------------------------------------------------------------- +#ifndef SDA +#define SDA 255 +#endif + +#ifndef SCL +#define SCL 255 +#endif + +// --------------------------------------------------------------------- +// UART pins (GPS communication) +// These pins are used specifically for GPS module communication +// --------------------------------------------------------------------- +#ifndef TX +#define TX 7 // GPS TX (Transmit) pin - connected to GPS module's RX pin +#endif + +#ifndef RX +#define RX 5 // GPS RX (Receive) pin - connected to GPS module's TX pin +#endif diff --git a/variants/orobas_seir/platformio.ini b/variants/orobas_seir/platformio.ini new file mode 100644 index 000000000..2de08a34d --- /dev/null +++ b/variants/orobas_seir/platformio.ini @@ -0,0 +1,141 @@ +[orobas_seir] +extends = esp32c6_base +board = esp32-c6-devkitm-1 +board_build.partitions = variants/orobas_seir/partitions.csv + +monitor_speed = 115200 + +board_build.boot = dio +board_build.flash_mode = dio +board_build.flash_size = 16MB +board_upload.flash_size = 16MB +board_build.f_flash = 40000000L + +build_flags = + ${esp32c6_base.build_flags} + -I variants/orobas_seir + +; BOARD CONFIG + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D ARDUINO_USB_MODE=1 + -D CONFIG_ARDUINO_LOOP_STACK_SIZE=16384 + -D ARDUINO_LOOP_STACK_SIZE=16384 + -D DISABLE_WIFI_OTA=1 + +; GPS CONFIG + -D HAS_GPS=1 + -D ENV_INCLUDE_GPS=1 + -D GPS_UART_NUM=1 + -D GPS_RX_PIN=5 + -D GPS_TX_PIN=7 + -D GPS_PPS_PIN=3 + +; LORA CONFIG + -D P_LORA_TX_LED=1 + -D P_LORA_SCLK=10 + -D P_LORA_MISO=9 + -D P_LORA_MOSI=11 + -D P_LORA_NSS=6 + -D P_LORA_RESET=16 + -D P_LORA_DIO_1=4 + -D P_LORA_BUSY=2 + -D LORA_FREQ=869.618 + -D LORA_BW=62.5 + -D LORA_CR=8 + -D LORA_SF=8 + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=140 + -D SX126X_RX_BOOSTED_GAIN=1 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + +build_src_filter = + ${esp32c6_base.build_src_filter} + +<../variants/orobas_seir/*.cpp> + +lib_deps = + rweather/Crypto + adafruit/RTClib + electroniccats/CayenneLPP + jgromes/RadioLib + melopero/Melopero RV3028 + densaugeo/base64 + stevemarple/MicroNMEA + sparkfun/SparkFun u-blox GNSS v3 + + +[env:OROBAS_SEIR_repeater] +extends = orobas_seir +build_src_filter = + ${orobas_seir.build_src_filter} + +<../examples/simple_repeater/*.cpp> + +build_flags = + ${orobas_seir.build_flags} + -D ADVERT_NAME='"OROBAS.NL"' + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=50 + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + + +[env:OROBAS_SEIR_companion_radio_ble] +extends = orobas_seir +build_src_filter = + ${orobas_seir.build_src_filter} + + + - + +<../examples/companion_radio/*.cpp> + +build_flags = + ${orobas_seir.build_flags} + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D BLE_PIN_CODE=123456 + -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_PRIVATE_KEY_IMPORT=1 + -D ENABLE_PRIVATE_KEY_EXPORT=1 + -D BLE_NAME_PREFIX='"OROBAS-"' +; -D BLE_DEBUG_LOGGING=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + +[env:OROBAS_SEIR_companion_radio_usb] +extends = orobas_seir +build_src_filter = + ${orobas_seir.build_src_filter} + + + - + +<../examples/companion_radio/*.cpp> + +build_flags = + ${orobas_seir.build_flags} + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_PRIVATE_KEY_IMPORT=1 + -D ENABLE_PRIVATE_KEY_EXPORT=1 +; DO NOT ENABLE -D MESH_PACKET_LOGGING=1 +; DO NOT ENABLE -D MESH_DEBUG=1 + + +[env:OROBAS_SEIR_room_server] +extends = orobas_seir +build_src_filter = + ${orobas_seir.build_src_filter} + + + - + +<../examples/companion_radio/*.cpp> + +build_flags = + ${orobas_seir.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 MAX_GROUP_CHANNELS=40 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 diff --git a/variants/orobas_seir/target.cpp b/variants/orobas_seir/target.cpp new file mode 100644 index 000000000..59e46d5a0 --- /dev/null +++ b/variants/orobas_seir/target.cpp @@ -0,0 +1,139 @@ +#include "target.h" + +#include +#include +#include + +// ----------------------------- +// Board info +// ----------------------------- +SEIRv5Board board; + +// ----------------------------- +// Clock info +// ----------------------------- +ESP32RTCClock rtc_clock; + +// ----------------------------- +// GPS info +// ----------------------------- +#ifndef GPS_RX_PIN +#define GPS_RX_PIN 5 +#endif +#ifndef GPS_TX_PIN +#define GPS_TX_PIN 7 +#endif + +SFE_UBLOX_GNSS_SERIAL myGNSS; +HardwareSerial gpsSerial(GPS_UART_NUM); +static MicroNMEALocationProvider _gps(gpsSerial, &rtc_clock); +LocationProvider &location = _gps; +SEIRSensorManager sensors(location); + +// ----------------------------- +// LORA info +// ----------------------------- +// Colin: Calibrated freq offset, don't touch! +#ifndef FREQ_OFFSET_MHZ +#define FREQ_OFFSET_MHZ -0.028 +#endif +#ifndef LORA_CR +#define LORA_CR 8 +#endif +static SPIClass spi(FSPI); +static Module radio_module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); + +static CustomSX1262 radio(&radio_module); +CustomSX1262Wrapper radio_driver(radio, board); + +// ----------------------------- +// Init of the device (radio) +// ----------------------------- +bool radio_init() { + // Initialize GPS + gpsSerial.begin(38400, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); + + // Log GPS provider information + Serial.printf("[SEIR] GPS provider = %p\n", sensors.getLocationProvider()); + + // Attempt to initialize GPS module + if (!myGNSS.begin(gpsSerial)) { + Serial.println("u-blox GNSS not responding"); + // Continue with radio initialization since GPS is optional for core functionality + } else { + Serial.println("u-blox GNSS responding"); + + // Configure GPS module for optimal operation + // Enable NMEA output on UART1 + if (!myGNSS.setUART1Output(COM_TYPE_NMEA, VAL_LAYER_RAM_BBR)) { + Serial.println("GPS: Failed to set UART1 output"); + } + + // Set 1 Hz navigation rate + if (!myGNSS.setNavigationFrequency(1, VAL_LAYER_RAM_BBR)) { + Serial.println("GPS: Failed to set navigation frequency"); + } + + // Set portable dynamics model for better performance + if (!myGNSS.setDynamicModel(DYN_MODEL_PORTABLE, VAL_LAYER_RAM_BBR)) { + Serial.println("GPS: Failed to set dynamic model"); + } + + // Disable UBX AutoPVT (not needed for NMEA) + if (!myGNSS.setAutoPVT(false)) { + Serial.println("GPS: Failed to disable AutoPVT"); + } + + // Configure NMEA messages (all messages enabled) + myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_GLL_UART1, 1); + myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_GSA_UART1, 1); + myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_GSV_UART1, 1); + myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_RMC_UART1, 1); + myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_VTG_UART1, 1); + myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_GGA_UART1, 1); + myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_ZDA_UART1, 1); + + // Apply configuration settings + if (myGNSS.sendCfgValset()) { + Serial.println("u-blox has been configured!"); + } else { + Serial.println("u-blox configuration has failed."); + } + } + + // Initialize LoRa radio + spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI, P_LORA_NSS); + if (radio.std_init(&spi)) { + radio.setSyncWord(RADIOLIB_SX126X_SYNC_WORD_PRIVATE); + radio.explicitHeader(); + radio.setCRC(2); + radio.setIrq(true); + radio.setPreambleLength(16); + radio.setRxBoostedGainMode(true); + return true; + } else { + Serial.println("LoRa radio initialization failed"); + return false; + } +} + +uint32_t radio_get_rng_seed() { + return radio.random(0x7FFFFFFF); +} + +void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { + float real_freq = freq + FREQ_OFFSET_MHZ; + radio.setFrequency(real_freq, false); + radio.setBandwidth(bw); + radio.setSpreadingFactor(sf); + 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); +} diff --git a/variants/orobas_seir/target.h b/variants/orobas_seir/target.h new file mode 100644 index 000000000..9146db8a8 --- /dev/null +++ b/variants/orobas_seir/target.h @@ -0,0 +1,109 @@ +#pragma once + +#include "esp_mac.h" + +#include +#include +#include +#include + +// GPS +#define HAS_GPS 1 + +// BATTERY +#define BATTERY_PIN 0 +#define BATTERY_DIVIDER 2.43f + +//-------------------- +// SEIR VERSION 5 +//-------------------- +class SEIRv5Board : public ESP32Board { +public: + uint16_t getBattMilliVolts() override { + analogReadResolution(12); + + // Set attenuation BEFORE reading + analogSetPinAttenuation(BATTERY_PIN, ADC_11db); + + // Dummy read to force ADC init on ESP32-C6 + analogRead(BATTERY_PIN); + + // Average samples + uint32_t sum = 0; + for (int i = 0; i < 4; i++) { + sum += analogRead(BATTERY_PIN); + } + uint16_t raw = sum / 4; + + float v_adc = (raw / 4095.0f) * 3.3f; + float v_bat = v_adc * BATTERY_DIVIDER; + uint16_t mv = (uint16_t)(v_bat * 1000.0f); + return mv; + } + + const char *getManufacturerName() const { return "OROBAS"; } + + void reboot() override { ESP.restart(); } +}; + +/* ---------- Sensor Manager ---------- */ +class SEIRSensorManager : public SensorManager { + LocationProvider *_loc; + bool gps_active = true; + +public: + SEIRSensorManager(LocationProvider &loc) : _loc(&loc) {} + + bool begin() override { return true; } + void loop() override { + if (!gps_active) return; + + _loc->loop(); + + static uint32_t lastPrint = 0; + uint32_t now = millis(); + } + + bool querySensors(uint8_t requester_permissions, CayenneLPP &telemetry) override { + int next_available_channel = TELEM_CHANNEL_SELF + 1; + + // Location + if ((requester_permissions & TELEM_PERM_LOCATION)) { + if (_loc && _loc->isValid()) { + telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude); + } + } + return true; + } + + LocationProvider *getLocationProvider() override { return _loc; } + + int getNumSettings() const override { return 1; } + + const char *getSettingName(int i) const override { return (i == 0) ? "gps" : nullptr; } + + const char *getSettingValue(int i) const override { return (i == 0 && gps_active) ? "1" : "0"; } + + bool setSettingValue(const char *name, const char *value) override { + if (strcmp(name, "gps") == 0) { + gps_active = strcmp(value, "0") != 0; + return true; + } + return false; + } +}; + +/* ---------- Globals ---------- */ +extern LocationProvider &location; +extern SEIRSensorManager sensors; + +extern SEIRv5Board board; +extern CustomSX1262Wrapper radio_driver; +extern ESP32RTCClock rtc_clock; + +/* ---------- Radio ---------- */ +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 5b5a56686cae6c0ba63d702940d239eb7eebc50b Mon Sep 17 00:00:00 2001 From: Cyber8RU7U5 Date: Thu, 26 Feb 2026 08:53:56 +0100 Subject: [PATCH 2/3] Changed `dbm` from `uint` to `int` to support negative values --- variants/orobas_seir/target.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/orobas_seir/target.h b/variants/orobas_seir/target.h index 9146db8a8..007060c62 100644 --- a/variants/orobas_seir/target.h +++ b/variants/orobas_seir/target.h @@ -105,5 +105,5 @@ extern ESP32RTCClock rtc_clock; 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); +void radio_set_tx_power(int8_t dbm); mesh::LocalIdentity radio_new_identity(); From 488b404909e79a060f87b0601248f865d56dc3e8 Mon Sep 17 00:00:00 2001 From: YourName Date: Thu, 26 Feb 2026 11:52:51 +0100 Subject: [PATCH 3/3] Changed `dbm` to `int8` in `target.h` and `target.cpp` --- variants/orobas_seir/target.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/orobas_seir/target.cpp b/variants/orobas_seir/target.cpp index 59e46d5a0..26fa36466 100644 --- a/variants/orobas_seir/target.cpp +++ b/variants/orobas_seir/target.cpp @@ -129,7 +129,7 @@ void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { radio.setCodingRate(cr); } -void radio_set_tx_power(uint8_t dbm) { +void radio_set_tx_power(int8_t dbm) { radio.setOutputPower(dbm); }