From 79bb61b64cfa3b0a72f196e7a38ae827e3e6e8ab Mon Sep 17 00:00:00 2001 From: "pedro.minatel" Date: Wed, 9 Jun 2021 15:24:59 +0100 Subject: [PATCH] Added FTM (initiator and responder) examples on WiFi library --- .../WiFi/examples/FTM/ftm_initiator/README.md | 106 +++++++++ .../FTM/ftm_initiator/ftm_initiator.ino | 216 ++++++++++++++++++ .../WiFi/examples/FTM/ftm_responder/README.md | 95 ++++++++ .../FTM/ftm_responder/ftm_responder.ino | 94 ++++++++ 4 files changed, 511 insertions(+) create mode 100644 libraries/WiFi/examples/FTM/ftm_initiator/README.md create mode 100644 libraries/WiFi/examples/FTM/ftm_initiator/ftm_initiator.ino create mode 100644 libraries/WiFi/examples/FTM/ftm_responder/README.md create mode 100644 libraries/WiFi/examples/FTM/ftm_responder/ftm_responder.ino diff --git a/libraries/WiFi/examples/FTM/ftm_initiator/README.md b/libraries/WiFi/examples/FTM/ftm_initiator/README.md new file mode 100644 index 00000000000..7539e76c0a9 --- /dev/null +++ b/libraries/WiFi/examples/FTM/ftm_initiator/README.md @@ -0,0 +1,106 @@ +# Wi-Fi FTM Initiator Arduino Example + +This example demonstrates how to use the Fine Timing Measurement (FTM) to calculate the distace from the Access Point and the device. This is calculated by the Wi-Fi Round Trip Time (Wi-Fi RTT) introduced on the [IEEE Std 802.11-2016](https://en.wikipedia.org/wiki/IEEE_802.11mc) standard. + +This example was based on the [ESP-IDF FTM](https://github.com/espressif/esp-idf/tree/master/examples/wifi/ftm). See the README file for more details about on how to use this feature. + +Some usages for this feature includes: + +* Indoor positioning systems. +* Navigation. +* Device Location. +* Smart Devices. +* Alarms. + +# Supported Targets + +Currently, this example supports the following targets: + +| Supported Targets | ESP32-S2 | ESP32-C3 | +| ----------------- | -------- | -------- | + +## How to Use Example + +In order to use the FTM, you will need a Responder or Wi-Fi router with FTM capabilities. If you don't own one, you can use a second ESP32-S2 or ESP32-C3 to simulate one. +See the **Responder** example to prepare the environment. + +* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). + +### Configure the Project + +To configure this project, you can change the following configuration related to FTM feature: + +```c +// Change the SSID and PASSWORD here if needed +#define WIFI_FTM_SSID "WiFi_FTM_Responder" // SSID +#define WIFI_FTM_PASS "ftm_responder" // Password +// FTM settings (minimal) +//Num of FTM frames requested in terms of 4 or 8 bursts (allowed values - 0 (No pref), 16, 24, 32, 64) +#define FTM_FRAME_COUNT 32 +// Requested time period between consecutive FTM bursts in 100’s of milliseconds +#define FTM_BURST_PERIOD 2 +``` + +* Change the Wi-Fi `SSID` and `PASSWORD` as the same as the Responder/Router. +* Change `FTM_FRAME_COUNT` with the number of frames requested to the Responder. +* Change `FTM_BURST_PERIOD` with the time between each FTM burst. + +To see more details about FTM, please see the [ESP-IDF docs](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/network/esp_wifi.html). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. + +#### Using Platform IO + +* Select the COM port: `Devices` or setting the `upload_port` option on the `platformio.ini` file. + +## Log Output + +Expected log output: + +``` +ESP-ROM:esp32s2-rc4-20191025 +Build:Oct 25 2019 +rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) +SPIWP:0xee +mode:DIO, clock div:1 +load:0x3ffe6100,len:0x4b0 +load:0x4004c000,len:0xa6c +load:0x40050000,len:0x25c4 +entry 0x4004c198 +Starting the FTM Initiatorsta connecting...Connected to WiFi_FTM_Responder +Requesting FTM session with Frm Count - 32 Burst Period 200 +Estimated RTT (ns) 57 Estimated Distance (in meters) 8.58 +Requesting FTM session with Frm Count - 32 Burst Period 200 +Estimated RTT (ns) 59 Estimated Distance (in meters) 8.97 +... +``` + +## Troubleshooting + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source.*** + +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persist, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/WiFi/examples/FTM/ftm_initiator/ftm_initiator.ino b/libraries/WiFi/examples/FTM/ftm_initiator/ftm_initiator.ino new file mode 100644 index 00000000000..6c1f21ede9b --- /dev/null +++ b/libraries/WiFi/examples/FTM/ftm_initiator/ftm_initiator.ino @@ -0,0 +1,216 @@ +/* Wi-Fi FTM Initiator Arduino Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include +#include "nvs_flash.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "esp_event.h" +#include "esp_err.h" +#include "esp_wifi.h" + +/* + * THIS FEATURE IS SUPPORTED ONLY BY ESP32-S2 AND ESP32-C3 + */ + +// Change the SSID and PASSWORD here if needed +#define WIFI_FTM_SSID "WiFi_FTM_Responder" // SSID +#define WIFI_FTM_PASS "ftm_responder" // Password +// FTM settings (minimal) +//Num of FTM frames requested in terms of 4 or 8 bursts (allowed values - 0 (No pref), 16, 24, 32, 64) +#define FTM_FRAME_COUNT 32 +// Requested time period between consecutive FTM bursts in 100’s of milliseconds +#define FTM_BURST_PERIOD 2 + +static bool s_reconnect = true; +static EventGroupHandle_t wifi_event_group; +const int CONNECTED_BIT = BIT0; +const int DISCONNECTED_BIT = BIT1; + +static EventGroupHandle_t ftm_event_group; +const int FTM_REPORT_BIT = BIT0; +const int FTM_FAILURE_BIT = BIT1; +static uint32_t g_rtt_est, g_dist_est; + +/* Handler for the Wi-Fi connection to the Responder */ +static void wifi_connected_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + wifi_event_sta_connected_t *event = (wifi_event_sta_connected_t *)event_data; + + Serial.print("Connected to "); + Serial.println(WIFI_FTM_SSID); + + xEventGroupClearBits(wifi_event_group, DISCONNECTED_BIT); + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); +} + +/* Wi-Fi disconnect handler */ +static void wifi_disconnect_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + if (s_reconnect) { + Serial.println("STA disconnect, s_reconnect..."); + esp_wifi_connect(); + } else { + Serial.println("STA disconnect"); + } + + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + xEventGroupSetBits(wifi_event_group, DISCONNECTED_BIT); +} + +/* FTM report handler with the calculated data from the round trip */ +static void ftm_report_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + wifi_event_ftm_report_t *event = (wifi_event_ftm_report_t *) event_data; + + if (event->status == FTM_STATUS_SUCCESS) { + g_rtt_est = event->rtt_est; + g_dist_est = event->dist_est; + xEventGroupSetBits(ftm_event_group, FTM_REPORT_BIT); + } else { + Serial.print("FTM procedure with Peer failed! Status: "); + Serial.println(event->status); + xEventGroupSetBits(ftm_event_group, FTM_FAILURE_BIT); + } +} + +// Wi-Fi initialization with FTM handler register +void wifi_init(void) +{ + esp_log_level_set("wifi", ESP_LOG_ERROR); + static bool initialized = false; + + if (initialized) { + return; + } + + ESP_ERROR_CHECK(esp_netif_init()); + wifi_event_group = xEventGroupCreate(); + ftm_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_create_default() ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + WIFI_EVENT_STA_CONNECTED, + &wifi_connected_handler, + NULL, + NULL)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + WIFI_EVENT_STA_DISCONNECTED, + &wifi_disconnect_handler, + NULL, + NULL)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + WIFI_EVENT_FTM_REPORT, + &ftm_report_handler, + NULL, + NULL)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) ); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + initialized = true; +} + +/* */ +static bool wifi_connect(const char *ssid, const char *pass) +{ + int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 0); + + wifi_config_t wifi_config = { 0 }; + + strlcpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); + if (pass) { + strlcpy((char *) wifi_config.sta.password, + pass, + sizeof(wifi_config.sta.password)); + } + + if (bits & CONNECTED_BIT) { + s_reconnect = false; + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + ESP_ERROR_CHECK( esp_wifi_disconnect() ); + xEventGroupWaitBits(wifi_event_group, DISCONNECTED_BIT, 0, 1, portTICK_RATE_MS); + } + + s_reconnect = true; + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config((wifi_interface_t)ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK( esp_wifi_connect() ); + + Serial.println("STA connecting..."); + xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 5000 / portTICK_RATE_MS); + return true; +} + +static int app_get_ftm(void) +{ + wifi_ftm_initiator_cfg_t ftmi_cfg = { + .frm_count = FTM_FRAME_COUNT, + .burst_period = FTM_BURST_PERIOD, + }; + + Serial.print("Requesting FTM session with Frm Count - "); + Serial.print(ftmi_cfg.frm_count); + Serial.print(" Burst Period "); + Serial.println(ftmi_cfg.burst_period*100); + + // Request FTM session with the Responder + if (ESP_OK != esp_wifi_ftm_initiate_session(&ftmi_cfg)) { + Serial.println("Failed to start FTM session"); + return 0; + } + + EventBits_t bits = xEventGroupWaitBits(ftm_event_group, FTM_REPORT_BIT | FTM_FAILURE_BIT, + pdFALSE, pdFALSE, portMAX_DELAY); + /* Processing data from FTM session */ + if (bits & FTM_REPORT_BIT) { + /* The estimated distance in meters may vary depending on some factors (see README file) */ + Serial.print("Estimated RTT (ns) "); + Serial.print(g_rtt_est); // Estimated round trip time + Serial.print(" Estimated Distance (in meters) "); + Serial.print(g_dist_est / 100); // Estimated distance in meters + Serial.print("."); + Serial.println(g_dist_est % 100); // Estimated distance in meters + xEventGroupClearBits(ftm_event_group, FTM_REPORT_BIT); + } else { + Serial.print("Error getting FTM!"); + } + return 0; +} + +void setup() { + + Serial.begin(115200); + Serial.println("Starting the FTM Initiator"); + + // NVS initialization for the Wi-Fi (needed!) + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK( ret ); + + // Wi-Fi Initialization + wifi_init(); + // Connect to STA with FTM Enabled + wifi_connect(WIFI_FTM_SSID, WIFI_FTM_PASS); + // Get FTM first time + app_get_ftm(); +} + +void loop() { + +} diff --git a/libraries/WiFi/examples/FTM/ftm_responder/README.md b/libraries/WiFi/examples/FTM/ftm_responder/README.md new file mode 100644 index 00000000000..7d5d771818f --- /dev/null +++ b/libraries/WiFi/examples/FTM/ftm_responder/README.md @@ -0,0 +1,95 @@ +# Wi-Fi FTM Responder Arduino Example + +This example demonstrates how to use the Fine Timing Measurement (FTM) to calculate the distace from the Access Point and the device. This is calculated by the Wi-Fi Round Trip Time (Wi-Fi RTT) introduced on the [IEEE Std 802.11-2016](https://en.wikipedia.org/wiki/IEEE_802.11mc) standard. + +This example will simulate the Router with FTM capability. + +This example was based on the [ESP-IDF FTM](https://github.com/espressif/esp-idf/tree/master/examples/wifi/ftm). See the README file for more details about on how to use this feature. + +Some usages for this feature includes: + +* Indoor positioning systems. +* Navigation. +* Device Location. +* Smart Devices. +* Alarms. + +# Supported Targets + +Currently, this example supports the following targets: + +| Supported Targets | ESP32-S2 | ESP32-C3 | +| ----------------- | -------- | -------- | + +## How to Use Example + +See the **Initiator** example to prepare the environment. + +* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide). + +### Configure the Project + +To configure this project, you can change the following configuration related to STA: + +```c +// Change the SSID and PASSWORD here if needed +#define WIFI_FTM_SSID "WiFi_FTM_Responder" // SSID +#define WIFI_FTM_PASS "ftm_responder" // Password +``` + +* Change the Wi-Fi `SSID` and `PASSWORD` as the same as the Initiator. + +To see more details about FTM, please see the [ESP-IDF docs](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/network/esp_wifi.html). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. + +#### Using Platform IO + +* Select the COM port: `Devices` or setting the `upload_port` option on the `platformio.ini` file. + +## Log Output + +Expected log output: + +``` +Build:Oct 25 2019 +rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT) +SPIWP:0xee +mode:DIO, clock div:1 +load:0x3ffe6100,len:0x4b0 +load:0x4004c000,len:0xa6c +load:0x40050000,len:0x25c4 +entry 0x4004c198 +Starting the FTM Responder +Starting SoftAP with FTM Responder support. +``` + +## Troubleshooting + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source.*** + +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persist, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/WiFi/examples/FTM/ftm_responder/ftm_responder.ino b/libraries/WiFi/examples/FTM/ftm_responder/ftm_responder.ino new file mode 100644 index 00000000000..3528c5175dd --- /dev/null +++ b/libraries/WiFi/examples/FTM/ftm_responder/ftm_responder.ino @@ -0,0 +1,94 @@ +/* Wi-Fi FTM Responder Arduino Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include +#include "nvs_flash.h" +#include "freertos/FreeRTOS.h" +#include "esp_err.h" +#include "esp_wifi.h" + +// Change the SSID and PASSWORD here if needed +#define WIFI_FTM_SSID "WiFi_FTM_Responder" +#define WIFI_FTM_PASS "ftm_responder" + +static bool s_reconnect = true; + +void initialise_wifi(void) +{ + esp_log_level_set("wifi", ESP_LOG_ERROR); + static bool initialized = false; + + if (initialized) { + return; + } + + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK( esp_event_loop_create_default() ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) ); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + initialized = true; +} + +static bool start_ftm_responder(const char* ssid, const char* pass) +{ + + wifi_config_t wifi_config_resp; + + wifi_config_resp.ap.ssid_len = 0; + wifi_config_resp.ap.max_connection = 4; + wifi_config_resp.ap.authmode = WIFI_AUTH_WPA2_PSK; + wifi_config_resp.ap.ftm_responder = true; + + s_reconnect = false; + strlcpy((char*) wifi_config_resp.ap.ssid, ssid, sizeof(wifi_config_resp.ap.ssid)); + if (pass) { + if (strlen(pass) != 0 && strlen(pass) < 8) { + s_reconnect = true; + Serial.println("Password less than 8 chars!"); + return false; + } + strlcpy((char*) wifi_config_resp.ap.password, pass, sizeof(wifi_config_resp.ap.password)); + } + + if (strlen(pass) == 0) { + wifi_config_resp.ap.authmode = WIFI_AUTH_OPEN; + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); + ESP_ERROR_CHECK(esp_wifi_set_config((wifi_interface_t)ESP_IF_WIFI_AP, &wifi_config_resp)); + Serial.println("Starting SoftAP with FTM Responder support."); + return true; +} + +void setup() { + + Serial.begin(115200); + Serial.println("Starting the FTM Responder"); + + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK( ret ); + // WiFi initialization with default configuration + initialise_wifi(); + // Start the AP with FTM Responder capability + start_ftm_responder(WIFI_FTM_SSID, WIFI_FTM_PASS); +} + +void loop() { + // put your main code here, to run repeatedly: +}