mirror of
https://github.com/Fishwaldo/LMIC-node.git
synced 2025-03-15 19:31:44 +00:00
getRSSI, ABP+Classic guard & STM32 delay override
Add support for SX1276 Low port and SX1272 in RSSI calculation. Add LMIC library and LMIC debug level (if >0) to print output. Add option to override STM32_POST_INITSERIAL_DELAY_MS in platformio.ini Add compile error when ABP is used with Classic LMIC. Fix ABP_DEVICEID not being used if defined in lorawan-keys.h. Fix offset for RSSI calculation when using MCCI LMIC. Fix printEvent() error when USE_DISPLAY and USE_SERIAL are not defined.
This commit is contained in:
parent
b0c3e2194c
commit
349a89b1d9
2 changed files with 152 additions and 103 deletions
|
@ -98,36 +98,57 @@ int16_t getSnrTenfold()
|
|||
{
|
||||
// Returns ten times the SNR (dB) value of the last received packet.
|
||||
// Ten times to prevent the use of float but keep 1 decimal digit accuracy.
|
||||
// Calculation per SX1276 datasheet (Rev.6) 6.4.
|
||||
// Calculation per SX1276 datasheet rev.7 §6.4, SX1276 datasheet rev.4 §6.4.
|
||||
// LMIC.snr contains value of PacketSnr, which is 4 times the actual SNR value.
|
||||
return (LMIC.snr * 10) / 4;
|
||||
}
|
||||
|
||||
|
||||
int16_t getRssi(int16_t snr)
|
||||
int16_t getRssi(int8_t snr)
|
||||
{
|
||||
// Returns correct RSSI (dBm) value of the last received packet.
|
||||
// Calculation per SX1276 datasheet (Rev.6) 5.5.5.
|
||||
// Correct calculation of RSSI depends on whether the HF or LF port is used.
|
||||
// Note: Below code assumes that only HF port is used and only SX1276 is used (not SX1272)
|
||||
// if not then the values will be less reliable.
|
||||
// Calculation per SX1276 datasheet rev.7 §5.5.5, SX1272 datasheet rev.4 §5.5.5.
|
||||
|
||||
const int16_t rssiOffset = -157; // For HF port use -157, for LF port use -164.
|
||||
|
||||
// LMIC.rssi contains modified value of PacketRssi.
|
||||
// Revert modification (applied in lmic/radio.c) to get PacketRssi.
|
||||
// (Purpose of modification is unclear and the magic numbers seem undocumented.)
|
||||
int16_t packetRssi = LMIC.rssi + 125 - 64;
|
||||
#define RSSI_OFFSET 64
|
||||
#define SX1276_FREQ_LF_MAX 525000000 // per datasheet 6.3
|
||||
#define SX1272_RSSI_ADJUST -139
|
||||
#define SX1276_RSSI_ADJUST_LF -164
|
||||
#define SX1276_RSSI_ADJUST_HF -157
|
||||
|
||||
int16_t rssi;
|
||||
if (snr < 0)
|
||||
{
|
||||
rssi = rssiOffset + packetRssi + snr;
|
||||
}
|
||||
else
|
||||
{
|
||||
rssi = rssiOffset + (16 / 15.0 * packetRssi);
|
||||
}
|
||||
|
||||
#ifdef MCCI_LMIC
|
||||
|
||||
rssi = LMIC.rssi - RSSI_OFFSET;
|
||||
|
||||
#else
|
||||
int16_t rssiAdjust;
|
||||
#ifdef CFG_sx1276_radio
|
||||
if (LMIC.freq > SX1276_FREQ_LF_MAX)
|
||||
{
|
||||
rssiAdjust = SX1276_RSSI_ADJUST_HF;
|
||||
}
|
||||
else
|
||||
{
|
||||
rssiAdjust = SX1276_RSSI_ADJUST_LF;
|
||||
}
|
||||
#else
|
||||
// CFG_sx1272_radio
|
||||
rssiAdjust = SX1272_RSSI_ADJUST;
|
||||
#endif
|
||||
|
||||
// Revert modification (applied in lmic/radio.c) to get PacketRssi.
|
||||
int16_t packetRssi = LMIC.rssi + 125 - RSSI_OFFSET;
|
||||
if (snr < 0)
|
||||
{
|
||||
rssi = rssiAdjust + packetRssi + snr;
|
||||
}
|
||||
else
|
||||
{
|
||||
rssi = rssiAdjust + (16 * packetRssi) / 15;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rssi;
|
||||
}
|
||||
|
||||
|
@ -142,7 +163,7 @@ void printEvent(ostime_t timestamp,
|
|||
if (target == PrintTarget::All || target == PrintTarget::Display)
|
||||
{
|
||||
display.clearLine(TIME_ROW);
|
||||
display.setCursor(0, TIME_ROW);
|
||||
display.setCursor(COL_0, TIME_ROW);
|
||||
display.print(F("Time:"));
|
||||
display.print(timestamp);
|
||||
display.clearLine(EVENT_ROW);
|
||||
|
@ -150,7 +171,7 @@ void printEvent(ostime_t timestamp,
|
|||
{
|
||||
display.clearLine(STATUS_ROW);
|
||||
}
|
||||
display.setCursor(0, EVENT_ROW);
|
||||
display.setCursor(COL_0, EVENT_ROW);
|
||||
display.print(message);
|
||||
}
|
||||
#endif
|
||||
|
@ -179,7 +200,9 @@ void printEvent(ostime_t timestamp,
|
|||
|
||||
void printEvent(ostime_t timestamp, ev_t ev, PrintTarget target = PrintTarget::All, bool clearDisplayStatusRow = true)
|
||||
{
|
||||
printEvent(timestamp, lmicEventNames[ev], target, clearDisplayStatusRow, true);
|
||||
#if defined(USE_DISPLAY) || defined(USE_SERIAL)
|
||||
printEvent(timestamp, lmicEventNames[ev], target, clearDisplayStatusRow, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -189,7 +212,7 @@ void printFrameCounters(PrintTarget target = PrintTarget::All)
|
|||
if (target == PrintTarget::Display || target == PrintTarget::All)
|
||||
{
|
||||
display.clearLine(FRMCNTRS_ROW);
|
||||
display.setCursor(0, FRMCNTRS_ROW);
|
||||
display.setCursor(COL_0, FRMCNTRS_ROW);
|
||||
display.print(F("Up:"));
|
||||
display.print(LMIC.seqnoUp);
|
||||
display.print(F(" Dn:"));
|
||||
|
@ -201,9 +224,9 @@ void printFrameCounters(PrintTarget target = PrintTarget::All)
|
|||
if (target == PrintTarget::Serial || target == PrintTarget::All)
|
||||
{
|
||||
printSpaces(serial, MESSAGE_INDENT);
|
||||
serial.print(F("Up#: "));
|
||||
serial.print(F("Up: "));
|
||||
serial.print(LMIC.seqnoUp);
|
||||
serial.print(F(", Dn#: "));
|
||||
serial.print(F(", Down: "));
|
||||
serial.println(LMIC.seqnoDn);
|
||||
}
|
||||
#endif
|
||||
|
@ -247,8 +270,8 @@ void printDownlinkInfo()
|
|||
// bool ackReceived = LMIC.txrxFlags & TXRX_ACK;
|
||||
|
||||
int16_t snrTenfold = getSnrTenfold();
|
||||
int16_t snr = snrTenfold / 10;
|
||||
int16_t snrDecimalFraction = snrTenfold % 10;
|
||||
int8_t snr = snrTenfold / 10;
|
||||
int8_t snrDecimalFraction = snrTenfold % 10;
|
||||
int16_t rssi = getRssi(snr);
|
||||
|
||||
uint8_t fPort = 0;
|
||||
|
@ -259,7 +282,7 @@ void printDownlinkInfo()
|
|||
|
||||
#ifdef USE_DISPLAY
|
||||
display.clearLine(EVENT_ROW);
|
||||
display.setCursor(0, EVENT_ROW);
|
||||
display.setCursor(COL_0, EVENT_ROW);
|
||||
display.print(F("RX P:"));
|
||||
display.print(fPort);
|
||||
if (dataLength != 0)
|
||||
|
@ -268,7 +291,7 @@ void printDownlinkInfo()
|
|||
display.print(LMIC.dataLen);
|
||||
}
|
||||
display.clearLine(STATUS_ROW);
|
||||
display.setCursor(0, STATUS_ROW);
|
||||
display.setCursor(COL_0, STATUS_ROW);
|
||||
display.print(F("RSSI"));
|
||||
display.print(rssi);
|
||||
display.print(F(" SNR"));
|
||||
|
@ -312,14 +335,16 @@ void printHeader(void)
|
|||
{
|
||||
#ifdef USE_DISPLAY
|
||||
display.clear();
|
||||
display.setCursor(0, HEADER_ROW);
|
||||
display.setCursor(COL_0, HEADER_ROW);
|
||||
display.print(F("LMIC-node"));
|
||||
// OTAA is default so is not shown here
|
||||
#ifdef ABP_ACTIVATION
|
||||
display.print(F(" ABP"));
|
||||
#endif
|
||||
display.drawString(0, DEVICEID_ROW, deviceId);
|
||||
display.setCursor(0, INTERVAL_ROW);
|
||||
display.drawString(ABPMODE_COL, HEADER_ROW, "ABP");
|
||||
#endif
|
||||
#ifdef CLASSIC_LMIC
|
||||
display.drawString(CLMICSYMBOL_COL, HEADER_ROW, "*");
|
||||
#endif
|
||||
display.drawString(COL_0, DEVICEID_ROW, deviceId);
|
||||
display.setCursor(COL_0, INTERVAL_ROW);
|
||||
display.print(F("Interval:"));
|
||||
display.print(doWorkIntervalSeconds);
|
||||
display.print("s");
|
||||
|
@ -327,17 +352,27 @@ void printHeader(void)
|
|||
|
||||
#ifdef USE_SERIAL
|
||||
serial.println(F("\n\nLMIC-node\n"));
|
||||
serial.print(F("Device-id: "));
|
||||
serial.print(F("Device-id: "));
|
||||
serial.println(deviceId);
|
||||
serial.print(F("Activation: "));
|
||||
serial.print(F("LMIC library: "));
|
||||
#ifdef MCCI_LMIC
|
||||
serial.println(F("MCCI"));
|
||||
#else
|
||||
serial.println(F("Classic [Deprecated]"));
|
||||
#endif
|
||||
serial.print(F("Activation: "));
|
||||
#ifdef OTAA_ACTIVATION
|
||||
serial.println(F("OTAA"));
|
||||
#else
|
||||
serial.println(F("ABP"));
|
||||
#endif
|
||||
serial.print(F("Interval: "));
|
||||
serial.print(doWorkIntervalSeconds);
|
||||
serial.println(F(" seconds"));
|
||||
#if defined(LMIC_DEBUG_LEVEL) && LMIC_DEBUG_LEVEL > 0
|
||||
serial.print(F("LMIC debug: "));
|
||||
serial.println(LMIC_DEBUG_LEVEL);
|
||||
#endif
|
||||
serial.print(F("Interval: "));
|
||||
serial.print(doWorkIntervalSeconds);
|
||||
serial.println(F(" seconds"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -463,7 +498,7 @@ void initLmic() {
|
|||
LMIC_setClockError(clockError);
|
||||
|
||||
#ifdef USE_SERIAL
|
||||
serial.print(F("\nClock Error: "));
|
||||
serial.print(F("Clock Error: "));
|
||||
serial.print(LMIC_CLOCK_ERROR_PPM);
|
||||
serial.print(" ppm (");
|
||||
serial.print(clockError);
|
||||
|
@ -661,6 +696,7 @@ void processWork(ostime_t doWorkJobTimeStamp)
|
|||
// The counter is increased automatically by getCounterValue()
|
||||
// and can be reset with a 'reset counter' command downlink message.
|
||||
|
||||
// Collect input data
|
||||
uint16_t counterValue = getCounterValue();
|
||||
ostime_t timestamp = os_getTime();
|
||||
|
||||
|
@ -669,7 +705,7 @@ void processWork(ostime_t doWorkJobTimeStamp)
|
|||
// This allows to keep the 3rd row empty which makes the
|
||||
// information better readable on the small display.
|
||||
display.clearLine(INTERVAL_ROW);
|
||||
display.setCursor(0, INTERVAL_ROW);
|
||||
display.setCursor(COL_0, INTERVAL_ROW);
|
||||
display.print("I:");
|
||||
display.print(doWorkIntervalSeconds);
|
||||
display.print("s");
|
||||
|
@ -677,7 +713,7 @@ void processWork(ostime_t doWorkJobTimeStamp)
|
|||
display.print(counterValue);
|
||||
#endif
|
||||
#ifdef USE_SERIAL
|
||||
printEvent(timestamp, "Data read", PrintTarget::Serial);
|
||||
printEvent(timestamp, "Input data collected", PrintTarget::Serial);
|
||||
printSpaces(serial, MESSAGE_INDENT);
|
||||
serial.print(F("COUNTER value: "));
|
||||
serial.println(counterValue);
|
||||
|
@ -767,7 +803,7 @@ void setup()
|
|||
#endif
|
||||
#ifdef USE_DISPLAY
|
||||
// Following mesage shown only if failure was unrelated to I2C.
|
||||
display.setCursor(0, FRMCNTRS_ROW);
|
||||
display.setCursor(COL_0, FRMCNTRS_ROW);
|
||||
display.print(F("HW init failed"));
|
||||
#endif
|
||||
abort();
|
||||
|
|
129
src/LMIC-node.h
129
src/LMIC-node.h
|
@ -61,59 +61,28 @@ void processDownlink(ostime_t eventTimestamp, uint8_t fPort, uint8_t* data, uint
|
|||
#define CLASSIC_LMIC
|
||||
#endif
|
||||
|
||||
// Determine if a valid region is defined.
|
||||
// This actually has little effect because
|
||||
// CLASSIC LMIC: defines CFG_eu868 by default,
|
||||
// MCCI LMIC: if no region is defined it
|
||||
// sets CFG_eu868 as default.
|
||||
#if ( \
|
||||
( defined(CLASSIC_LMIC) \
|
||||
&& !( defined(CFG_eu868) \
|
||||
|| defined(CFG_us915) ) ) \
|
||||
|| \
|
||||
( defined(MCCI_LMIC) \
|
||||
&& !( defined(CFG_as923) \
|
||||
|| defined(CFG_as923jp) \
|
||||
|| defined(CFG_au915) \
|
||||
|| defined(CFG_eu868) \
|
||||
|| defined(CFG_in866) \
|
||||
|| defined(CFG_kr920) \
|
||||
|| defined(CFG_us915) ) ) \
|
||||
)
|
||||
#Error No valid region defined
|
||||
#endif
|
||||
|
||||
#include BSFILE // Include Board Support File
|
||||
#include "../keyfiles/lorawan-keys.h"
|
||||
|
||||
#ifdef OTAA_ACTIVATION
|
||||
#if !defined(OTAA_DEVEUI) || !defined(OTAA_APPEUI) || !defined(OTAA_APPKEY)
|
||||
#error One or more LoRaWAN keys (OTAA_DEVEUI, OTAA_APPEUI, OTAA_APPKEY) are not defined.
|
||||
#endif
|
||||
#else
|
||||
// ABP activation
|
||||
#if !defined(ABP_DEVADDR) || !defined(ABP_NWKSKEY) || !defined(ABP_APPSKEY)
|
||||
#error One or more LoRaWAN keys (ABP_DEVADDR, ABP_NWKSKEY, ABP_APPSKEY) are not defined.
|
||||
#endif
|
||||
#if !defined(ABP_ACTIVATION) && !defined(OTAA_ACTIVATION)
|
||||
#define OTAA_ACTIVATION
|
||||
#endif
|
||||
|
||||
|
||||
#include BSFILE // Include Board Support File
|
||||
#include "../keyfiles/lorawan-keys.h"
|
||||
|
||||
|
||||
#if defined(LMIC_DEBUG_LEVEL) && LMIC_DEBUG_LEVEL > 0
|
||||
#ifdef LMIC_PRINTF_TO
|
||||
#undef LMIC_PRINTF_TO
|
||||
// Do not overrule if already defined
|
||||
#ifndef LMIC_PRINTF_TO
|
||||
#define LMIC_PRINTF_TO serial
|
||||
#endif
|
||||
#define LMIC_PRINTF_TO serial
|
||||
#endif
|
||||
|
||||
#if defined(ABP_ACTIVATION) && defined(OTAA_ACTIVATION)
|
||||
#error Only one of ABP_ACTIVATION and OTAA_ACTIVATION can be defined.
|
||||
#endif
|
||||
|
||||
#if !defined(ABP_ACTIVATION) && !defined(OTAA_ACTIVATION)
|
||||
#define OTAA_ACTIVATION
|
||||
#endif
|
||||
|
||||
#if defined(ABP_ACTIVATION) && defined(DEVICEID_ABP)
|
||||
const char deviceId[] = DEVICEID_ABP;
|
||||
#if defined(ABP_ACTIVATION) && defined(ABP_DEVICEID)
|
||||
const char deviceId[] = ABP_DEVICEID;
|
||||
#elif defined(DEVICEID)
|
||||
const char deviceId[] = DEVICEID;
|
||||
#else
|
||||
|
@ -134,6 +103,44 @@ void processDownlink(ostime_t eventTimestamp, uint8_t fPort, uint8_t* data, uint
|
|||
#define WAITFOR_SERIAL_S 0
|
||||
#endif
|
||||
|
||||
#if defined(ABP_ACTIVATION) && defined(CLASSIC_LMIC)
|
||||
#error Do NOT use ABP activation when using the deprecated IBM LMIC framework library. \
|
||||
On The Things Network V3 this will cause a downlink message for EACH uplink message \
|
||||
because it does properly handle MAC commands.
|
||||
#endif
|
||||
|
||||
#ifdef OTAA_ACTIVATION
|
||||
#if !defined(OTAA_DEVEUI) || !defined(OTAA_APPEUI) || !defined(OTAA_APPKEY)
|
||||
#error One or more LoRaWAN keys (OTAA_DEVEUI, OTAA_APPEUI, OTAA_APPKEY) are not defined.
|
||||
#endif
|
||||
#else
|
||||
// ABP activation
|
||||
#if !defined(ABP_DEVADDR) || !defined(ABP_NWKSKEY) || !defined(ABP_APPSKEY)
|
||||
#error One or more LoRaWAN keys (ABP_DEVADDR, ABP_NWKSKEY, ABP_APPSKEY) are not defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Determine if a valid region is defined.
|
||||
// This actually has little effect because
|
||||
// CLASSIC LMIC: defines CFG_eu868 by default,
|
||||
// MCCI LMIC: if no region is defined it
|
||||
// sets CFG_eu868 as default.
|
||||
#if ( \
|
||||
( defined(CLASSIC_LMIC) \
|
||||
&& !( defined(CFG_eu868) \
|
||||
|| defined(CFG_us915) ) ) \
|
||||
|| \
|
||||
( defined(MCCI_LMIC) \
|
||||
&& !( defined(CFG_as923) \
|
||||
|| defined(CFG_as923jp) \
|
||||
|| defined(CFG_au915) \
|
||||
|| defined(CFG_eu868) \
|
||||
|| defined(CFG_in866) \
|
||||
|| defined(CFG_kr920) \
|
||||
|| defined(CFG_us915) ) ) \
|
||||
)
|
||||
#Error No valid LoRaWAN region defined
|
||||
#endif
|
||||
|
||||
#ifndef LMIC_MCCI
|
||||
#define LMIC_ERROR_SUCCESS 0
|
||||
|
@ -217,19 +224,25 @@ void processDownlink(ostime_t eventTimestamp, uint8_t fPort, uint8_t* data, uint
|
|||
|
||||
#ifdef USE_DISPLAY
|
||||
uint8_t transmitSymbol[8] = {0x18, 0x18, 0x00, 0x24, 0x99, 0x42, 0x3c, 0x00};
|
||||
#define LAST_COL 15
|
||||
#define HEADER_ROW 0
|
||||
#define DEVICEID_ROW 1
|
||||
#define INTERVAL_ROW 2
|
||||
#define TIME_ROW 4
|
||||
#define EVENT_ROW 5
|
||||
#define STATUS_ROW 6
|
||||
#define FRMCNTRS_ROW 7
|
||||
#define ROW_0 0
|
||||
#define ROW_1 1
|
||||
#define ROW_2 2
|
||||
#define ROW_3 3
|
||||
#define ROW_4 4
|
||||
#define ROW_0 0
|
||||
#define ROW_1 1
|
||||
#define ROW_2 2
|
||||
#define ROW_3 3
|
||||
#define ROW_4 4
|
||||
#define ROW_5 5
|
||||
#define ROW_6 6
|
||||
#define ROW_7 7
|
||||
#define HEADER_ROW ROW_0
|
||||
#define DEVICEID_ROW ROW_1
|
||||
#define INTERVAL_ROW ROW_2
|
||||
#define TIME_ROW ROW_4
|
||||
#define EVENT_ROW ROW_5
|
||||
#define STATUS_ROW ROW_6
|
||||
#define FRMCNTRS_ROW ROW_7
|
||||
#define COL_0 0
|
||||
#define ABPMODE_COL 10
|
||||
#define CLMICSYMBOL_COL 14
|
||||
#define TXSYMBOL_COL 15
|
||||
|
||||
void initDisplay()
|
||||
{
|
||||
|
@ -241,11 +254,11 @@ void processDownlink(ostime_t eventTimestamp, uint8_t fPort, uint8_t* data, uint
|
|||
{
|
||||
if (visible)
|
||||
{
|
||||
display.drawTile(LAST_COL, ROW_0, 1, transmitSymbol);
|
||||
display.drawTile(TXSYMBOL_COL, ROW_0, 1, transmitSymbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
display.drawGlyph(LAST_COL, ROW_0, char(0x20));
|
||||
display.drawGlyph(TXSYMBOL_COL, ROW_0, char(0x20));
|
||||
}
|
||||
}
|
||||
#endif // USE_DISPLAY
|
||||
|
|
Loading…
Add table
Reference in a new issue