Merge branch 'ripplebiz:main' into heltec_v3_sensors

This commit is contained in:
Memo 2025-05-24 10:42:22 +00:00 committed by GitHub
commit 79f60e0675
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 524 additions and 99 deletions

33
boards/rak3172.json Normal file
View file

@ -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"
}

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 <Adafruit_AHTX0.h>
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 <Adafruit_BME280.h>
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 <Adafruit_INA3221.h>
static Adafruit_INA3221 INA3221;
#endif
#if ENV_INCLUDE_INA219
#define TELEM_INA219_ADDRESS 0x40 // INA219 single channel current sensor I2C address
#include <Adafruit_INA219.h>
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;
}
}
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

View file

@ -1,32 +1,42 @@
#pragma once
#include <helpers/SensorManager.h>
#include <Mesh.h>
#include <Adafruit_INA3221.h>
#include <Adafruit_INA219.h>
#include <Adafruit_AHTX0.h>
#include <Adafruit_BME280.h>
#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 <helpers/SensorManager.h>
#include <helpers/sensors/LocationProvider.h>
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;
};

View file

@ -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() )
{

View file

@ -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}
+<helpers/ui/ST7735Display.cpp>
+<../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}
+<helpers/ui/ST7735Display.cpp>
+<../examples/simple_room_server>
lib_deps =
${Heltec_tracker_base.lib_deps}
${esp32_ota.lib_deps}

View file

@ -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}
+<helpers/nrf52/PromicroBoard.cpp>
+<helpers/sensors>
@ -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}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio>

View file

@ -2,6 +2,9 @@
#include "target.h"
#include <helpers/ArduinoHelpers.h>
#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 <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
#endif
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;

View file

@ -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

View file

@ -0,0 +1,67 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>
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
}

35
variants/rak3x72/target.h Normal file
View file

@ -0,0 +1,35 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/RadioLibWrappers.h>
#include <helpers/stm32/STM32Board.h>
#include <helpers/CustomSTM32WLxWrapper.h>
#include <helpers/ArduinoHelpers.h>
#include <helpers/SensorManager.h>
#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();

View file

@ -0,0 +1,5 @@
#pragma once
#include <variant_RAK3172_MODULE.h>
#undef RNG

View file

@ -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

View file

@ -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}

View file

@ -2,7 +2,7 @@
#include "target.h"
#include <helpers/ArduinoHelpers.h>
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

View file

@ -8,7 +8,14 @@
#include <helpers/ArduinoHelpers.h>
#include <helpers/SensorManager.h>
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;

View file

@ -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}
+<helpers/*.cpp>
+<helpers/sensors>
+<helpers/nrf52/XiaoNrf52Board.cpp>
+<../variants/xiao_nrf52>
debug_tool = jlink

View file

@ -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

View file

@ -6,12 +6,12 @@
#include <helpers/nrf52/XiaoNrf52Board.h>
#include <helpers/CustomSX1262Wrapper.h>
#include <helpers/ArduinoHelpers.h>
#include <helpers/SensorManager.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
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();

View file

@ -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;