Changed Lora SF to Lora DR control

This commit is contained in:
Verkehrsrot 2019-09-20 13:22:45 +02:00
parent cc248419ae
commit c3bad526a7
11 changed files with 90 additions and 83 deletions

View File

@ -305,13 +305,27 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
0 = display off 0 = display off
1 = display on [default] 1 = display on [default]
0x05 set LoRa spread factor 0x05 set LoRa datarate
7 ... 12 [default: 9] 0 ... 15 see LoRaWAN regional parameters for details [default: 5]
Example for EU868:
DataRate Radio Bit/s
0 LoRa: SF12 / 125 kHz 250
1 LoRa: SF11 / 125 kHz 440
2 LoRa: SF10 / 125 kHz 980
3 LoRa: SF9 / 125 kHz 1760
4 LoRa: SF8 / 125 kHz 3125
5 LoRa: SF7 / 125 kHz 5470
6* LoRa: SF7 / 250 kHz 11000
7* FSK: 50 kbps 50000
*) not supported by TheThingsNetwork
0x06 set LoRa TXpower 0x06 set LoRa TXpower
2 ... 15 [default: 15] 0 ... 15 [default: 14]
0x07 set LoRa Adaptive Data Rate mode 0x07 set LoRa Adaptive Data Rate mode

View File

@ -50,7 +50,7 @@ enum timesource_t { _gps, _rtc, _lora, _unsynced };
// Struct holding devices's runtime configuration // Struct holding devices's runtime configuration
typedef struct { typedef struct {
uint8_t lorasf; // 7-12, lora spreadfactor uint8_t loradr; // 0-15, lora datarate
uint8_t txpower; // 2-15, lora tx power uint8_t txpower; // 2-15, lora tx power
uint8_t adrmode; // 0=disabled, 1=enabled uint8_t adrmode; // 0=disabled, 1=enabled
uint8_t screensaver; // 0=disabled, 1=enabled uint8_t screensaver; // 0=disabled, 1=enabled

View File

@ -40,7 +40,6 @@ void os_getDevKey(u1_t *buf);
void os_getArtEui(u1_t *buf); void os_getArtEui(u1_t *buf);
void os_getDevEui(u1_t *buf); void os_getDevEui(u1_t *buf);
void showLoraKeys(void); void showLoraKeys(void);
void switch_lora(uint8_t sf, uint8_t tx);
void lora_send(void *pvParameters); void lora_send(void *pvParameters);
void lora_enqueuedata(MessageBuffer_t *message); void lora_enqueuedata(MessageBuffer_t *message);
void lora_queuereset(void); void lora_queuereset(void);
@ -51,6 +50,8 @@ void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[],
const uint8_t tablesize); const uint8_t tablesize);
uint8_t getBattLevel(void); uint8_t getBattLevel(void);
const char *getSfName(rps_t rps); const char *getSfName(rps_t rps);
const char *getBwName(rps_t rps);
const char *getCrName(rps_t rps);
#if (TIME_SYNC_LORAWAN) #if (TIME_SYNC_LORAWAN)
void user_request_network_time_callback(void *pVoidUserUTCTime, void user_request_network_time_callback(void *pVoidUserUTCTime,

View File

@ -43,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I
[common] [common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c" ; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 1.8.2 release_version = 1.8.3
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 3 debug_level = 3
@ -74,6 +74,7 @@ lib_deps_basic =
274@>=2.3.3 ;RTC by Michael Miller 274@>=2.3.3 ;RTC by Michael Miller
SimpleButton SimpleButton
AXP202X_Library@^1.0.0 AXP202X_Library@^1.0.0
;https://github.com/cyberman54/AXP202X_Library.git
lib_deps_all = lib_deps_all =
${common.lib_deps_basic} ${common.lib_deps_basic}
${common.lib_deps_lora} ${common.lib_deps_lora}

View File

@ -37,7 +37,7 @@ function Decoder(bytes, port) {
if (port === 3) { if (port === 3) {
// device config data // device config data
return decode(bytes, [uint8, uint8, int16, uint8, uint8, uint8, uint8, bitmap1, bitmap2, version], ['lorasf', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags', 'payloadmask', 'version']); return decode(bytes, [uint8, uint8, int16, uint8, uint8, uint8, uint8, bitmap1, bitmap2, version], ['loradr', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags', 'payloadmask', 'version']);
} }
if (port === 4) { if (port === 4) {

View File

@ -10,12 +10,13 @@ esp_err_t err;
#define PAYLOADMASK \ #define PAYLOADMASK \
((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \ ((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \
SENSOR2_DATA | SENSOR3_DATA) & ~BATT_DATA) SENSOR2_DATA | SENSOR3_DATA) & \
~BATT_DATA)
// populate cfg vars with factory settings // populate cfg vars with factory settings
void defaultConfig() { void defaultConfig() {
cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora sf, see pacounter.conf cfg.loradr = LORADRDEFAULT; // 0-15, lora datarate, see pacounter.conf
cfg.txpower = 15; // 2-15, lora tx power cfg.txpower = LORATXPOWDEFAULT; // 0-15, lora tx power
cfg.adrmode = 1; // 0=disabled, 1=enabled cfg.adrmode = 1; // 0=disabled, 1=enabled
cfg.screensaver = 0; // 0=disabled, 1=enabled cfg.screensaver = 0; // 0=disabled, 1=enabled
cfg.screenon = 1; // 0=disabled, 1=enabled cfg.screenon = 1; // 0=disabled, 1=enabled
@ -96,9 +97,9 @@ void saveConfig() {
strcmp(storedversion, cfg.version) != 0) strcmp(storedversion, cfg.version) != 0)
nvs_set_str(my_handle, "version", cfg.version); nvs_set_str(my_handle, "version", cfg.version);
if (nvs_get_i8(my_handle, "lorasf", &flash8) != ESP_OK || if (nvs_get_i8(my_handle, "loradr", &flash8) != ESP_OK ||
flash8 != cfg.lorasf) flash8 != cfg.loradr)
nvs_set_i8(my_handle, "lorasf", cfg.lorasf); nvs_set_i8(my_handle, "loradr", cfg.loradr);
if (nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK || if (nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK ||
flash8 != cfg.txpower) flash8 != cfg.txpower)
@ -221,11 +222,11 @@ void loadConfig() {
ESP_LOGI(TAG, "bsecstate = %d", cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE]); ESP_LOGI(TAG, "bsecstate = %d", cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE]);
}; };
if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { if (nvs_get_i8(my_handle, "loradr", &flash8) == ESP_OK) {
cfg.lorasf = flash8; cfg.loradr = flash8;
ESP_LOGI(TAG, "lorasf = %d", flash8); ESP_LOGI(TAG, "loradr = %d", flash8);
} else { } else {
ESP_LOGI(TAG, "lorasf set to default %d", cfg.lorasf); ESP_LOGI(TAG, "loradr set to default %d", cfg.loradr);
saveConfig(); saveConfig();
} }

View File

@ -205,7 +205,7 @@ void draw_page(time_t t, uint8_t page) {
u8x8.setCursor(11, 3); u8x8.setCursor(11, 3);
if (cfg.adrmode) // if ADR=on then display SF value inverse if (cfg.adrmode) // if ADR=on then display SF value inverse
u8x8.setInverseFont(1); u8x8.setInverseFont(1);
u8x8.printf("%5s", getSfName(LMIC.rps)); u8x8.printf("%5s", getSfName(updr2rps(LMIC.datarate)));
if (cfg.adrmode) // switch off inverse if it was turned on if (cfg.adrmode) // switch off inverse if it was turned on
u8x8.setInverseFont(0); u8x8.setInverseFont(0);
#endif // HAS_LORA #endif // HAS_LORA

View File

@ -234,11 +234,15 @@ void onEvent(ev_t ev) {
sprintf(display_line6, " "); // clear previous lmic status sprintf(display_line6, " "); // clear previous lmic status
// set data rate adaptation according to saved setting // set data rate adaptation according to saved setting
LMIC_setAdrMode(cfg.adrmode); LMIC_setAdrMode(cfg.adrmode);
// set data rate and transmit power if we have no ADR // set data rate and transmit power to defaults only if we have no ADR
if (!cfg.adrmode) if (!cfg.adrmode)
switch_lora(cfg.lorasf, cfg.txpower); LMIC_setDrTxpow(assertDR(cfg.loradr), cfg.txpower);
// show current devaddr // show current devaddr
ESP_LOGI(TAG, "DEVaddr=%08X", LMIC.devaddr); ESP_LOGI(TAG, "DEVaddr=%08X", LMIC.devaddr);
ESP_LOGI(TAG, "Radio parameters %s / %s / %s",
getSfName(updr2rps(LMIC.datarate)),
getBwName(updr2rps(LMIC.datarate)),
getCrName(updr2rps(LMIC.datarate)));
break; break;
case EV_RFU1: case EV_RFU1:
@ -321,53 +325,6 @@ void onEvent(ev_t ev) {
} }
} }
// helper function to assign LoRa datarates to numeric spreadfactor values
void switch_lora(uint8_t sf, uint8_t tx) {
if (tx > 20)
return;
cfg.txpower = tx;
switch (sf) {
case 7:
LMIC_setDrTxpow(DR_SF7, tx);
cfg.lorasf = sf;
break;
case 8:
LMIC_setDrTxpow(DR_SF8, tx);
cfg.lorasf = sf;
break;
case 9:
LMIC_setDrTxpow(DR_SF9, tx);
cfg.lorasf = sf;
break;
case 10:
LMIC_setDrTxpow(DR_SF10, tx);
cfg.lorasf = sf;
break;
case 11:
#if defined(CFG_us915)
LMIC_setDrTxpow(DR_SF11CR, tx);
cfg.lorasf = sf;
break;
#else
LMIC_setDrTxpow(DR_SF11, tx);
cfg.lorasf = sf;
break;
#endif
case 12:
#if defined(CFG_us915)
LMIC_setDrTxpow(DR_SF12CR, tx);
cfg.lorasf = sf;
break;
#else
LMIC_setDrTxpow(DR_SF12, tx);
cfg.lorasf = sf;
break;
#endif
default:
break;
}
}
// LMIC send task // LMIC send task
void lora_send(void *pvParameters) { void lora_send(void *pvParameters) {
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
@ -698,4 +655,14 @@ const char *getSfName(rps_t rps) {
return t[getSf(rps)]; return t[getSf(rps)];
} }
const char *getBwName(rps_t rps) {
const char *const t[] = {"BW125", "BW250", "BW500", "BWrfu"};
return t[getBw(rps)];
}
const char *getCrName(rps_t rps) {
const char *const t[] = {"CR 4/5", "CR 4/6", "CR 4/7", "CR 4/8"};
return t[getCr(rps)];
}
#endif // HAS_LORA #endif // HAS_LORA

View File

@ -1,3 +1,5 @@
// clang-format off
// ----- Paxcounter user config file ------ // ----- Paxcounter user config file ------
// //
// --> adapt to your needs and use case <-- // --> adapt to your needs and use case <--
@ -46,7 +48,8 @@
#define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle
#define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results
#define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit
#define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs #define LORADRDEFAULT 5 // 0 .. 15, LoRaWAN datarate, according to regional LoRaWAN specs [default = 5]
#define LORATXPOWDEFAULT 14 // 0 .. 15, LoRaWAN TX power
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy #define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
#define SEND_QUEUE_SIZE 10 // maximum number of messages in payload send queue [1 = no queue] #define SEND_QUEUE_SIZE 10 // maximum number of messages in payload send queue [1 = no queue]

View File

@ -36,7 +36,7 @@ void PayloadConvert::addVoltage(uint16_t value) {
} }
void PayloadConvert::addConfig(configData_t value) { void PayloadConvert::addConfig(configData_t value) {
buffer[cursor++] = value.lorasf; buffer[cursor++] = value.loradr;
buffer[cursor++] = value.txpower; buffer[cursor++] = value.txpower;
buffer[cursor++] = value.adrmode; buffer[cursor++] = value.adrmode;
buffer[cursor++] = value.screensaver; buffer[cursor++] = value.screensaver;
@ -157,7 +157,7 @@ void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) {
void PayloadConvert::addVoltage(uint16_t value) { writeUint16(value); } void PayloadConvert::addVoltage(uint16_t value) { writeUint16(value); }
void PayloadConvert::addConfig(configData_t value) { void PayloadConvert::addConfig(configData_t value) {
writeUint8(value.lorasf); writeUint8(value.loradr);
writeUint8(value.txpower); writeUint8(value.txpower);
writeUint16(value.rssilimit); writeUint16(value.rssilimit);
writeUint8(value.sendcycle); writeUint8(value.sendcycle);

View File

@ -193,10 +193,22 @@ void set_monitor(uint8_t val[]) {
cfg.monitormode = val[0] ? 1 : 0; cfg.monitormode = val[0] ? 1 : 0;
} }
void set_lorasf(uint8_t val[]) { void set_loradr(uint8_t val[]) {
#if (HAS_LORA) #if (HAS_LORA)
ESP_LOGI(TAG, "Remote command: set LoRa SF to %d", val[0]); if (validDR(val[0])) {
switch_lora(val[0], cfg.txpower); cfg.loradr = val[0];
ESP_LOGI(TAG, "Remote command: set LoRa Datarate to %d", cfg.loradr);
LMIC_setDrTxpow(assertDR(cfg.loradr), cfg.txpower);
ESP_LOGI(TAG, "Radio parameters now %s / %s / %s",
getSfName(updr2rps(LMIC.datarate)),
getBwName(updr2rps(LMIC.datarate)),
getCrName(updr2rps(LMIC.datarate)));
} else
ESP_LOGI(
TAG,
"Remote command: set LoRa Datarate called with illegal datarate %d",
val[0]);
#else #else
ESP_LOGW(TAG, "Remote command: LoRa not implemented"); ESP_LOGW(TAG, "Remote command: LoRa not implemented");
#endif // HAS_LORA #endif // HAS_LORA
@ -247,8 +259,16 @@ void set_rgblum(uint8_t val[]) {
void set_lorapower(uint8_t val[]) { void set_lorapower(uint8_t val[]) {
#if (HAS_LORA) #if (HAS_LORA)
ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", val[0]); // set data rate and transmit power only if we have no ADR
switch_lora(cfg.lorasf, val[0]); if (!cfg.adrmode) {
cfg.txpower = val[0] & 0x0f;
ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", cfg.txpower);
LMIC_setDrTxpow(assertDR(cfg.loradr), cfg.txpower);
} else
ESP_LOGI(
TAG,
"Remote command: set LoRa TXPOWER, not executed because ADR is on");
#else #else
ESP_LOGW(TAG, "Remote command: LoRa not implemented"); ESP_LOGW(TAG, "Remote command: LoRa not implemented");
#endif // HAS_LORA #endif // HAS_LORA
@ -331,7 +351,7 @@ void set_flush(uint8_t val[]) {
static cmd_t table[] = { static cmd_t table[] = {
{0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true}, {0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true},
{0x03, set_gps, 1, true}, {0x04, set_display, 1, true}, {0x03, set_gps, 1, true}, {0x04, set_display, 1, true},
{0x05, set_lorasf, 1, true}, {0x06, set_lorapower, 1, true}, {0x05, set_loradr, 1, true}, {0x06, set_lorapower, 1, true},
{0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true}, {0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true},
{0x09, set_reset, 1, true}, {0x0a, set_sendcycle, 1, true}, {0x09, set_reset, 1, true}, {0x0a, set_sendcycle, 1, true},
{0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true}, {0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true},