new variant: RAK WisMesh Tag

This commit is contained in:
recrof
2025-09-05 16:21:19 +02:00
parent 0ebca4b88e
commit d59724acd0
8 changed files with 518 additions and 16 deletions

View File

@@ -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 <INA226.h>
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;

View File

@@ -0,0 +1,81 @@
#include <Arduino.h>
#include "RAKWismeshTagBoard.h"
#include <bluefruit.h>
#include <Wire.h>
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;
}

View File

@@ -0,0 +1,80 @@
#pragma once
#include <MeshCore.h>
#include <Arduino.h>
// 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();
}
};

View File

@@ -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>
+<helpers/ui/buzzer.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/NullDisplayDriver.cpp>
+<helpers/sensors>
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}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../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>

View File

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

View File

@@ -0,0 +1,27 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <RAKWismeshTagBoard.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/NullDisplayDriver.h>
extern DISPLAY_CLASS display;
#include <helpers/ui/MomentaryButton.h>
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();

View File

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

View File

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