From 76a79940b3222bbf60efd08f27e23ec7c1f8bf29 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 14:52:18 +0200 Subject: [PATCH 1/6] MAC command up/down evaluation --- include/lorawan.h | 3 ++- src/lorawan.cpp | 52 +++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/include/lorawan.h b/include/lorawan.h index 9094c132..74a67c04 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -47,7 +47,8 @@ void lora_queuereset(void); void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, size_t nMsg); void myTxCallback(void *pUserData, int fSuccess); -void mac_decode(const uint8_t cmd[], const uint8_t cmdlength); +void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], + const uint8_t tablesize); #if (TIME_SYNC_LORAWAN) void user_request_network_time_callback(void *pVoidUserUTCTime, diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 9c3e5664..9ad8675a 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -24,8 +24,7 @@ TaskHandle_t lmicTask = NULL, lorasendTask = NULL; // table of LORAWAN MAC messages sent by the network to the device // format: opcode, cmdname (max 19 chars), #bytes params // source: LoRaWAN 1.1 Specification (October 11, 2017) - -static mac_t table[] = { +static const mac_t MACdn_table[] = { {0x01, "ResetConf", 1}, {0x02, "LinkCheckAns", 2}, {0x03, "LinkADRReq", 4}, {0x04, "DutyCycleReq", 1}, {0x05, "RXParamSetupReq", 4}, {0x06, "DevStatusReq", 0}, @@ -35,8 +34,15 @@ static mac_t table[] = { {0x0D, "DeviceTimeAns", 5}, {0x0E, "ForceRejoinReq", 2}, {0x0F, "RejoinParamSetupReq", 1}}; -static const uint8_t cmdtablesize = - sizeof(table) / sizeof(table[0]); // number of commands in MAC table +// table of LORAWAN MAC messages sent by the device to the network +static const mac_t MACup_table[] = { + {0x01, "ResetInd", 1}, {0x02, "LinkCheckReq", 0}, + {0x03, "LinkADRAns", 1}, {0x04, "DutyCycleAns", 0}, + {0x05, "RXParamSetupAns", 1}, {0x06, "DevStatusAns", 2}, + {0x07, "NewChannelAns", 1}, {0x08, "RxTimingSetupAns", 0}, + {0x09, "TxParamSetupAns", 0}, {0x0A, "DlChannelAns", 1}, + {0x0B, "RekeyInd", 1}, {0x0C, "ADRParamSetupAns", 0}, + {0x0D, "DeviceTimeReq", 0}, {0x0F, "RejoinParamSetupAns", 1}}; class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t { @@ -568,26 +574,26 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, // display type of received data if (nMsg) - ESP_LOGI(TAG, "Received %u bytes of payload on port %u", nMsg, port); + ESP_LOGI(TAG, "Received %u byte(s) of payload on port %u", nMsg, port); else if (port) ESP_LOGI(TAG, "Received empty message on port %u", port); // list MAC messages, if any - /* uint8_t nMac = pMsg - &LMIC.frame[0]; if (port != MACPORT) --nMac; if (nMac) { - ESP_LOGI(TAG, "Received %u byte MAC message", nMac); + ESP_LOGI(TAG, "%u byte(s) downlink MAC commands", nMac); // NOT WORKING YET - // whe need to strip some protocol overhead from LMIC.frame to unwrap the - // MAC command - mac_decode(LMIC.frame, nMac); - */ + // whe need to unwrap the MAC command from LMIC.frame here + // mac_decode(LMIC.frame, nMac, MACdn_table, sizeof(MACdn_table) / + // sizeof(MACdn_table[0])); + } if (LMIC.pendMacLen) { - ESP_LOGI(TAG, "Received %u byte MAC message", LMIC.pendMacLen); - mac_decode(LMIC.pendMacData, LMIC.pendMacLen); + ESP_LOGI(TAG, "%u byte(s) uplink MAC commands", LMIC.pendMacLen); + mac_decode(LMIC.pendMacData, LMIC.pendMacLen, MACup_table, + sizeof(MACup_table) / sizeof(MACup_table[0])); } switch (port) { @@ -623,32 +629,34 @@ void myTxCallback(void *pUserData, int fSuccess) { } // decode LORAWAN MAC message -void mac_decode(const uint8_t cmd[], const uint8_t cmdlength) { +void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], + const uint8_t tablesize) { - if (!cmdlength) + if (!cmdlen) return; - uint8_t foundcmd[cmdlength], cursor = 0; + uint8_t foundcmd[cmdlen], cursor = 0; - while (cursor < cmdlength) { + while (cursor < cmdlen) { + + int i = tablesize; // number of commands in table - int i = cmdtablesize; while (i--) { if (cmd[cursor] == table[i].opcode) { // lookup command in opcode table cursor++; // strip 1 byte opcode - if ((cursor + table[i].params) <= cmdlength) { + if ((cursor + table[i].params) <= cmdlen) { memmove(foundcmd, cmd + cursor, table[i].params); // strip opcode from cmd array cursor += table[i].params; - ESP_LOGD(TAG, "Network command %s", table[i].cmdname); + ESP_LOGD(TAG, "MAC command %s", table[i].cmdname); } else - ESP_LOGD(TAG, "MAC message 0x%02X with missing parameter(s)", + ESP_LOGD(TAG, "MAC command 0x%02X with missing parameter(s)", table[i].opcode); break; // command found -> exit table lookup loop } // end of command validation } // end of command table lookup loop if (i < 0) { // command not found -> skip it - ESP_LOGD(TAG, "Unknown MAC message 0x%02X", cmd[cursor]); + ESP_LOGD(TAG, "Unknown MAC command 0x%02X", cmd[cursor]); cursor++; } } // command parsing loop From 15389516f52a8bee8a8d169dc0965dbc23c4bdaf Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 15:02:43 +0200 Subject: [PATCH 2/6] added setting for wifi power save off --- src/wifiscan.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 12ec9c82..6951ad6a 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -71,6 +71,7 @@ void wifi_sniffer_init(void) { ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); // no modem power saving ESP_ERROR_CHECK(esp_wifi_start()); // channel switch throws error without ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set frame filter ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler)); From 506b1f4f7e7b8155dbb49ac036e8cff33132c49d Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 17:00:00 +0200 Subject: [PATCH 3/6] remove clock error setting, using interrupt timing --- src/lmic_config.h | 2 +- src/lorawan.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lmic_config.h b/src/lmic_config.h index 0f1f426b..06a4da4c 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -37,7 +37,7 @@ // so consuming more power. You may sharpen (reduce) this value if you are // limited on battery. // ATTN: VALUES > 7 WILL CAUSE RECEPTION AND JOIN PROBLEMS WITH HIGH SF RATES -#define CLOCK_ERROR_PROCENTAGE 7 +//#define CLOCK_ERROR_PROCENTAGE 7 // Set this to 1 to enable some basic debug output (using printf) about // RF settings used during transmission and reception. Set to 2 to diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 9ad8675a..1e8c641f 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -541,11 +541,13 @@ void lmictask(void *pvParameters) { os_init(); // initialize lmic run-time environment LMIC_reset(); // initialize lmic MAC LMIC_setLinkCheckMode(0); - // This tells LMIC to make the receive windows bigger, in case your clock is - // faster or slower. This causes the transceiver to be earlier switched on, - // so consuming more power. You may sharpen (reduce) CLOCK_ERROR_PERCENTAGE - // in src/lmic_config.h if you are limited on battery. +// This tells LMIC to make the receive windows bigger, in case your clock is +// faster or slower. This causes the transceiver to be earlier switched on, +// so consuming more power. You may sharpen (reduce) CLOCK_ERROR_PERCENTAGE +// in src/lmic_config.h if you are limited on battery. +#ifdef CLOCK_ERROR_PROCENTAGE LMIC_setClockError(MAX_CLOCK_ERROR * CLOCK_ERROR_PROCENTAGE / 100); +#endif // Set the data rate to Spreading Factor 7. This is the fastest supported // rate for 125 kHz channels, and it minimizes air time and battery power. // Set the transmission power to 14 dBi (25 mW). From 0dea735bfb8335bd8d3d8ad697f0a9327f3a9444 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 18:02:27 +0200 Subject: [PATCH 4/6] lmic_config.h sanitized --- src/lmic_config.h | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/lmic_config.h b/src/lmic_config.h index 06a4da4c..788a07e1 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -2,19 +2,16 @@ // COUNTRY SETTINGS // --> please check with you local regulations for ISM band frequency use! -// -// CFG_eu868 EU 863-870 MHz -// CFG_us915 US 902-928 MHz -// CFG_au921 Australia 915-928 MHz -// CFG_as923 Asia 923 MHz -// CFG_in866 India 865-867 MHz -#define CFG_eu868 1 -//#define CFG_us915 1 -//#define CFG_in866 1 -//#define CFG_au921 1 -//#define CFG_as923 1 -//#define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */ +#define CFG_eu868 1 // Europe (high band) +//#define CFG_eu433 1 // Europe (low band) +//#define CFG_us915 1 // USA, Canada and South America +//#define CFG_in866 1 // India +//#define CFG_au921 1 // Australia +//#define CFG_as923 1 // Asia +//#define CFG_cn783 1 // China (high band) +//#define CFG_cn490 1 // China (low band) +//#define CFG_kr920 1 // Korea // LMIC LORAWAN STACK SETTINGS // --> adapt to your device only if necessary @@ -26,12 +23,6 @@ // time sync via LoRaWAN network, note: not supported by TTNv2 // #define LMIC_ENABLE_DeviceTimeReq 1 -// 16 μs per tick -// LMIC requires ticks to be 15.5μs - 100 μs long -#define US_PER_OSTICK_EXPONENT 4 -#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT) -#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK) - // This tells LMIC to make the receive windows bigger, in case your clock is // faster or slower. This causes the transceiver to be earlier switched on, // so consuming more power. You may sharpen (reduce) this value if you are @@ -51,6 +42,11 @@ // current implementation only works on AVR, though. //#define LMIC_PRINTF_TO Serial +// Change the SPI clock speed if you encounter errors +// communicating with the radio. +// The standard range is 125kHz-8MHz, but some boards can go faster. +//#define LMIC_SPI_FREQ 1E6 + // Any runtime assertion failures are printed to this serial port (or // any other Print object). If this is unset, any failures just silently // halt execution. @@ -92,7 +88,7 @@ // implementation is optimized for speed on 32-bit processors using // fairly big lookup tables, but it takes up big amounts of flash on the // AVR architecture. -//#define USE_ORIGINAL_AES +#define USE_ORIGINAL_AES // // This selects the AES implementation written by Ideetroon for their // own LoRaWAN library. It also uses lookup tables, but smaller @@ -100,4 +96,4 @@ // also about twice as slow as the original). // #define USE_IDEETRON_AES // -#define USE_MBEDTLS_AES +//#define USE_MBEDTLS_AES From 738543b5299521109e23522ce51767e0386f210f Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 19:12:23 +0200 Subject: [PATCH 5/6] i2scan.cpp bugfix bus select --- src/i2cscan.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp index c57d0604..ea7e83ce 100644 --- a/src/i2cscan.cpp +++ b/src/i2cscan.cpp @@ -22,8 +22,12 @@ int i2c_scan(void) { for (addr = 8; addr <= 119; addr++) { - // scan i2c bus with no more to 100KHz +// scan i2c bus with no more to 100KHz +#ifdef HAS_DISPLAY + Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 100000); +#else Wire.begin(SDA, SCL, 100000); +#endif Wire.beginTransmission(addr); Wire.write(addr); i2c_ret = Wire.endTransmission(); @@ -87,7 +91,7 @@ void AXP192_init(void) { axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); axp.setDCDC1Voltage(3300); axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); - //axp.setChgLEDMode(AXP20X_LED_OFF); + // axp.setChgLEDMode(AXP20X_LED_OFF); axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); #ifdef PMU_INT From a1b7c102d026103b5cb4e6251d473d2257d6cada Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 19:52:25 +0200 Subject: [PATCH 6/6] power.cpp added, i2cscan adapted --- include/i2cscan.h | 12 +++++++---- include/main.h | 9 ++++---- include/power.h | 13 ++++++++++++ src/i2cscan.cpp | 52 +---------------------------------------------- src/main.cpp | 18 +++++++++------- src/power.cpp | 42 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+), 66 deletions(-) create mode 100644 include/power.h create mode 100644 src/power.cpp diff --git a/include/i2cscan.h b/include/i2cscan.h index b834b34f..38487e76 100644 --- a/include/i2cscan.h +++ b/include/i2cscan.h @@ -2,11 +2,15 @@ #define _I2CSCAN_H #include -#ifdef HAS_PMU -#include "axp20x.h" -#endif + +#define SSD1306_PRIMARY_ADDRESS (0x3D) +#define SSD1306_SECONDARY_ADDRESS (0x3C) +#define BME_PRIMARY_ADDRESS (0x77) +#define BME_SECONDARY_ADDRESS (0x76) +#define AXP192_PRIMARY_ADDRESS (0x34) +#define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) +#define QUECTEL_GPS_PRIMARY_ADDRESS (0x10) int i2c_scan(void); -void AXP192_init(void); #endif \ No newline at end of file diff --git a/include/main.h b/include/main.h index ddc49d5d..4b5617cb 100644 --- a/include/main.h +++ b/include/main.h @@ -1,12 +1,13 @@ #ifndef _MAIN_H #define _MAIN_H -#include // needed for reading ESP32 chip attributes -#include // needed for Wifi event handler +#include // needed for reading ESP32 chip attributes +#include // needed for Wifi event handler #include // needed for timers -#include // needed for showing coex sw version +#include // needed for showing coex sw version #include "globals.h" +#include "power.h" #include "i2cscan.h" #include "blescan.h" #include "wifiscan.h" @@ -17,7 +18,7 @@ #include "irqhandler.h" #include "led.h" #include "spislave.h" -#if(HAS_LORA) +#if (HAS_LORA) #include "lorawan.h" #endif #include "timekeeper.h" diff --git a/include/power.h b/include/power.h new file mode 100644 index 00000000..f557edb4 --- /dev/null +++ b/include/power.h @@ -0,0 +1,13 @@ +#ifndef _POWER_H +#define _POWER_H + +#include +#include "i2cscan.h" + +#ifdef HAS_PMU +#include +#endif + +void AXP192_init(void); + +#endif \ No newline at end of file diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp index ea7e83ce..e3deb9f0 100644 --- a/src/i2cscan.cpp +++ b/src/i2cscan.cpp @@ -5,14 +5,6 @@ // Local logging tag static const char TAG[] = __FILE__; -#define SSD1306_PRIMARY_ADDRESS (0x3D) -#define SSD1306_SECONDARY_ADDRESS (0x3C) -#define BME_PRIMARY_ADDRESS (0x77) -#define BME_SECONDARY_ADDRESS (0x76) -#define AXP192_PRIMARY_ADDRESS (0x34) -#define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) -#define QUECTEL_GPS_PRIMARY_ADDRESS (0x10) - int i2c_scan(void) { int i2c_ret, addr; @@ -49,9 +41,6 @@ int i2c_scan(void) { case AXP192_PRIMARY_ADDRESS: ESP_LOGI(TAG, "0x%X: AXP192 power management", addr); -#ifdef HAS_PMU - AXP192_init(); -#endif break; case QUECTEL_GPS_PRIMARY_ADDRESS: @@ -72,43 +61,4 @@ int i2c_scan(void) { ESP_LOGI(TAG, "I2C scan done, %u devices found.", devices); return devices; -} - -#ifdef HAS_PMU - -void AXP192_init(void) { - - AXP20X_Class axp; - - if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) - ESP_LOGI(TAG, "AXP192 PMU initialization failed"); - else { - - axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); - axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); - axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); - axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); - axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); - axp.setDCDC1Voltage(3300); - axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); - // axp.setChgLEDMode(AXP20X_LED_OFF); - axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); - -#ifdef PMU_INT - pinMode(PMU_INT, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(PMU_INT), - [] { - ESP_LOGI(TAG, "Power source changed"); - /* put your code here */ - }, - FALLING); - axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | - AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, - 1); - axp.clearIRQ(); -#endif // PMU_INT - - ESP_LOGI(TAG, "AXP192 PMU initialized."); - } -} -#endif // HAS_PMU \ No newline at end of file +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0dc90395..3a466e68 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -169,6 +169,17 @@ void setup() { ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); #endif +// setup power on boards with power management logic +#ifdef EXT_POWER_SW + pinMode(EXT_POWER_SW, OUTPUT); + digitalWrite(EXT_POWER_SW, EXT_POWER_ON); + strcat_P(features, " VEXT"); +#endif +#ifdef HAS_PMU + AXP192_init(); + strcat_P(features, " PMU"); +#endif + i2c_scan(); #endif // verbose @@ -189,13 +200,6 @@ void setup() { strcat_P(features, " PSRAM"); #endif -// set external power mode -#ifdef EXT_POWER_SW - pinMode(EXT_POWER_SW, OUTPUT); - digitalWrite(EXT_POWER_SW, EXT_POWER_ON); - strcat_P(features, " VEXT"); -#endif - #ifdef BAT_MEASURE_EN pinMode(BAT_MEASURE_EN, OUTPUT); #endif diff --git a/src/power.cpp b/src/power.cpp new file mode 100644 index 00000000..3a492256 --- /dev/null +++ b/src/power.cpp @@ -0,0 +1,42 @@ +// Basic config +#include "globals.h" +#include "power.h" + +#ifdef HAS_PMU + +void AXP192_init(void) { + + AXP20X_Class axp; + + if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) + ESP_LOGI(TAG, "AXP192 PMU initialization failed"); + else { + + axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); + axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); + axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + axp.setDCDC1Voltage(3300); + axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); + // axp.setChgLEDMode(AXP20X_LED_OFF); + axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); + +#ifdef PMU_INT + pinMode(PMU_INT, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(PMU_INT), + [] { + ESP_LOGI(TAG, "Power source changed"); + /* put your code here */ + }, + FALLING); + axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | + AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, + 1); + axp.clearIRQ(); +#endif // PMU_INT + + ESP_LOGI(TAG, "AXP192 PMU initialized."); + } +} +#endif // HAS_PMU \ No newline at end of file