From 7bf89d83d5ee86e8ced5fa42869b5896a74ba50f Mon Sep 17 00:00:00 2001 From: xiehanxin Date: Tue, 21 Feb 2023 15:07:14 +0800 Subject: [PATCH] add multiple antenna test example --- examples/wifi/antenna/CMakeLists.txt | 6 + examples/wifi/antenna/README.md | 133 ++++++++ .../antenna_soft_switch/CMakeLists.txt | 3 + .../antenna_soft_switch/antenna_switch.c | 302 ++++++++++++++++++ .../antenna_soft_switch/component.mk | 4 + .../include/antenna_switch.h | 54 ++++ examples/wifi/antenna/main/CMakeLists.txt | 3 + examples/wifi/antenna/main/Kconfig.projbuild | 47 +++ .../main/antenna_switch_example_main.c | 187 +++++++++++ .../pytest_wifi_antenna_soft_switch.py | 70 ++++ examples/wifi/antenna/sdkconfig.ci | 2 + .../wifi/antenna/sdkconfig.ci.esp32c2_xtal26m | 2 + 12 files changed, 813 insertions(+) create mode 100755 examples/wifi/antenna/CMakeLists.txt create mode 100755 examples/wifi/antenna/README.md create mode 100755 examples/wifi/antenna/components/antenna_soft_switch/CMakeLists.txt create mode 100755 examples/wifi/antenna/components/antenna_soft_switch/antenna_switch.c create mode 100755 examples/wifi/antenna/components/antenna_soft_switch/component.mk create mode 100755 examples/wifi/antenna/components/antenna_soft_switch/include/antenna_switch.h create mode 100755 examples/wifi/antenna/main/CMakeLists.txt create mode 100755 examples/wifi/antenna/main/Kconfig.projbuild create mode 100755 examples/wifi/antenna/main/antenna_switch_example_main.c create mode 100755 examples/wifi/antenna/pytest_wifi_antenna_soft_switch.py create mode 100755 examples/wifi/antenna/sdkconfig.ci create mode 100755 examples/wifi/antenna/sdkconfig.ci.esp32c2_xtal26m diff --git a/examples/wifi/antenna/CMakeLists.txt b/examples/wifi/antenna/CMakeLists.txt new file mode 100755 index 0000000000..8e3b360aad --- /dev/null +++ b/examples/wifi/antenna/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wifi_station) diff --git a/examples/wifi/antenna/README.md b/examples/wifi/antenna/README.md new file mode 100755 index 0000000000..cdc8bfd919 --- /dev/null +++ b/examples/wifi/antenna/README.md @@ -0,0 +1,133 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | + +# Wi-Fi antenna soft switch Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates how to use multi-antenna software switching for ESP. + +## How to use example + +### Configure the project + +Open the project configuration menu (`idf.py menuconfig`). + +In the `Example Configuration` menu: + +* Set the Wi-Fi configuration. + * Set `WiFi SSID`. + * Set `WiFi Password`. + +Optional: If you need, change the other options according to your requirements. + +### Build and Flash + +Build the project and flash it to the board, then run the monitor tool to view the serial output: + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for all the steps to configure and use the ESP-IDF to build projects. + +* [ESP-IDF Getting Started Guide on ESP32](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) +* [ESP-IDF Getting Started Guide on ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html) +* [ESP-IDF Getting Started Guide on ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html) + +## Example Output +Note that the output, in particular the order of the output, may vary depending on the environment. + +Console output if station connects to AP successfully: +``` +I (589) wifi station: ESP_WIFI_MODE_STA +I (599) wifi: wifi driver task: 3ffc08b4, prio:23, stack:3584, core=0 +I (599) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (599) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (629) wifi: wifi firmware version: 2d94f02 +I (629) wifi: config NVS flash: enabled +I (629) wifi: config nano formating: disabled +I (629) wifi: Init dynamic tx buffer num: 32 +I (629) wifi: Init data frame dynamic rx buffer num: 32 +I (639) wifi: Init management frame dynamic rx buffer num: 32 +I (639) wifi: Init management short buffer num: 32 +I (649) wifi: Init static rx buffer size: 1600 +I (649) wifi: Init static rx buffer num: 10 +I (659) wifi: Init dynamic rx buffer num: 32 +I (759) phy: phy_version: 4180, cb3948e, Sep 12 2019, 16:39:13, 0, 0 +I (769) wifi: mode : sta (30:ae:a4:d9:bc:c4) +I (769) wifi station: wifi_init_sta finished. +I (889) wifi: new:<6,0>, old:<1,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (889) wifi: state: init -> auth (b0) +I (899) wifi: state: auth -> assoc (0) +I (909) wifi: state: assoc -> run (10) +I (939) wifi: connected with #!/bin/test, aid = 1, channel 6, BW20, bssid = ac:9e:17:7e:31:40 +I (939) wifi: security type: 3, phy: bgn, rssi: -68 +I (949) wifi: pm start, type: 1 + +I (1029) wifi: AP's beacon interval = 102400 us, DTIM period = 3 +I (2089) esp_netif_handlers: sta ip: 192.168.77.89, mask: 255.255.255.0, gw: 192.168.77.1 +I (2089) wifi station: got ip:192.168.77.89 +I (2089) wifi station: connected to ap SSID:myssid password:mypassword +I (12268) wifi station: GPIO: [0].pin = 21, [1].pin = 22 +I (18568) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (19068) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (19568) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (20068) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (20568) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (21068) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (21568) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (22068) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (22568) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (23068) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +I (23568) wifi station: rx mode = 1, tx mode = 1, ant0_en = 0, ant1_en = 1 +``` + +Console output if the station failed to connect to AP: +``` +I (589) wifi station: ESP_WIFI_MODE_STA +I (599) wifi: wifi driver task: 3ffc08b4, prio:23, stack:3584, core=0 +I (599) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (599) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (629) wifi: wifi firmware version: 2d94f02 +I (629) wifi: config NVS flash: enabled +I (629) wifi: config nano formating: disabled +I (629) wifi: Init dynamic tx buffer num: 32 +I (629) wifi: Init data frame dynamic rx buffer num: 32 +I (639) wifi: Init management frame dynamic rx buffer num: 32 +I (639) wifi: Init management short buffer num: 32 +I (649) wifi: Init static rx buffer size: 1600 +I (649) wifi: Init static rx buffer num: 10 +I (659) wifi: Init dynamic rx buffer num: 32 +I (759) phy: phy_version: 4180, cb3948e, Sep 12 2019, 16:39:13, 0, 0 +I (759) wifi: mode : sta (30:ae:a4:d9:bc:c4) +I (769) wifi station: wifi_init_sta finished. +I (889) wifi: new:<6,0>, old:<1,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (889) wifi: state: init -> auth (b0) +I (1889) wifi: state: auth -> init (200) +I (1889) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (1889) wifi station: retry to connect to the AP +I (1899) wifi station: connect to the AP fail +I (3949) wifi station: retry to connect to the AP +I (3949) wifi station: connect to the AP fail +I (4069) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (4069) wifi: state: init -> auth (b0) +I (5069) wifi: state: auth -> init (200) +I (5069) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (5069) wifi station: retry to connect to the AP +I (5069) wifi station: connect to the AP fail +I (7129) wifi station: retry to connect to the AP +I (7129) wifi station: connect to the AP fail +I (7249) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (7249) wifi: state: init -> auth (b0) +I (8249) wifi: state: auth -> init (200) +I (8249) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (8249) wifi station: retry to connect to the AP +I (8249) wifi station: connect to the AP fail +I (10299) wifi station: connect to the AP fail +I (10299) wifi station: Failed to connect to SSID:myssid, password:mypassword +``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/wifi/antenna/components/antenna_soft_switch/CMakeLists.txt b/examples/wifi/antenna/components/antenna_soft_switch/CMakeLists.txt new file mode 100755 index 0000000000..1bf311fa71 --- /dev/null +++ b/examples/wifi/antenna/components/antenna_soft_switch/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "antenna_switch.c" + INCLUDE_DIRS "./include" + REQUIRES esp_wifi) diff --git a/examples/wifi/antenna/components/antenna_soft_switch/antenna_switch.c b/examples/wifi/antenna/components/antenna_soft_switch/antenna_switch.c new file mode 100755 index 0000000000..ffcf0fa927 --- /dev/null +++ b/examples/wifi/antenna/components/antenna_soft_switch/antenna_switch.c @@ -0,0 +1,302 @@ +/* Antenna soft switching 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 "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "freertos/queue.h" +#include "esp_wifi.h" +#include "esp_log.h" + +#include "antenna_switch.h" + +#define SOFT_SWITCHING_NAME "three ant auto" +#define SOFT_SWITCHING_PRIORITY 4 +#define SOFT_SWITCHING_STACK 4096 + +#define WAIT_TIME 60 /**< unit 100ms*/ +#define MONITOR_TIME 200 /**< unit 10ms*/ +#define QUEUE_LENGTH_RSSI_SINGLE 10 +#define QUEUE_LENGTH_RSSI_SUM 25 +#define RSSI_SINGLE_SIZE sizeof(int8_t) +#define RSSI_SUM_SIZE sizeof(int16_t) +#define RSSI_KD 0.01 + +static const char *TAG = "ANTENNA_SWITCH_EXAMPLE"; +static wifi_antenna_auto_switch_config_t wifi_three_ant_auto_get_config = { + .ant_num = 3, + .ant_zero = 0, + .ant_one = 1, + .ant_two = 3, + .ant_switch = 35 +}; +static TaskHandle_t antenna_task_handle; + +/**< Select the optimal antenna*/ +static void antenna_switch_function(const wifi_antenna_auto_switch_config_t *config) +{ + wifi_ant_config_t wifi_ant_config; + wifi_ap_record_t wifi_ap_record; + int16_t rssi_ant0 = INT16_MIN, rssi_ant1 = INT16_MIN, rssi_ant2 = INT16_MIN, rssi_max, rssi_min; + + if(config->ant_num < 2 || config->ant_num > 3) { + ESP_LOGE(TAG, "wifi_antenna_auto_switch_config_t parameter error"); + abort(); + } + + /**< Monitor antenna zero signal strength*/ + wifi_ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT0; + wifi_ant_config.rx_ant_default = WIFI_ANT_MODE_ANT0; + wifi_ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT0; + wifi_ant_config.enabled_ant0 = config->ant_zero; + wifi_ant_config.enabled_ant1 = config->ant_one; + ESP_ERROR_CHECK(esp_wifi_set_ant(&wifi_ant_config)); + /**< Wait for parameters to take effect*/ + vTaskDelay(100/portTICK_PERIOD_MS); + while(ESP_OK != esp_wifi_sta_get_ap_info(&wifi_ap_record)) { + /**< can't find AP*/ + vTaskDelay(100/portTICK_PERIOD_MS); + } + rssi_ant0 = 0; + rssi_max = wifi_ap_record.rssi; + rssi_min = wifi_ap_record.rssi; + for(int i = 0; i < MONITOR_TIME; i++) { + while(ESP_OK != esp_wifi_sta_get_ap_info(&wifi_ap_record)) { + /**< can't find AP*/ + vTaskDelay(100/portTICK_PERIOD_MS); + } + rssi_max = rssi_max > wifi_ap_record.rssi ? rssi_max : wifi_ap_record.rssi; + rssi_min = rssi_min < wifi_ap_record.rssi ? rssi_min : wifi_ap_record.rssi; + rssi_ant0 += wifi_ap_record.rssi; + vTaskDelay(10/portTICK_PERIOD_MS); + } + rssi_ant0 = rssi_ant0 - rssi_max - rssi_min; + ESP_LOGD(TAG, "The signal strength of the antenna zero :%d", rssi_ant0); + + /**< Monitor antenna one signal strength*/ + wifi_ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT1; + wifi_ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT1; + ESP_ERROR_CHECK(esp_wifi_set_ant(&wifi_ant_config)); + /**< Wait for parameters to take effect*/ + vTaskDelay(100/portTICK_PERIOD_MS); + while(ESP_OK != esp_wifi_sta_get_ap_info(&wifi_ap_record)) { + /**< can't find AP*/ + vTaskDelay(100/portTICK_PERIOD_MS); + } + rssi_ant1 = 0; + rssi_max = wifi_ap_record.rssi; + rssi_min = wifi_ap_record.rssi; + for(int i = 0; i < MONITOR_TIME; i++) { + while(ESP_OK != esp_wifi_sta_get_ap_info(&wifi_ap_record)) { + /**< can't find AP*/ + vTaskDelay(100/portTICK_PERIOD_MS); + } + rssi_max = rssi_max > wifi_ap_record.rssi ? rssi_max : wifi_ap_record.rssi; + rssi_min = rssi_min < wifi_ap_record.rssi ? rssi_min : wifi_ap_record.rssi; + rssi_ant1 += wifi_ap_record.rssi; + vTaskDelay(10/portTICK_PERIOD_MS); + } + rssi_ant1 = rssi_ant1 - rssi_max - rssi_min; + ESP_LOGD(TAG, "The signal strength of the antenna one :%d", rssi_ant1); + + if(config->ant_num == 3) { + /**< Monitor antenna two signal strength*/ + wifi_ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT1; + wifi_ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT1; + wifi_ant_config.enabled_ant1 = config->ant_two; + ESP_ERROR_CHECK(esp_wifi_set_ant(&wifi_ant_config)); + /**< Wait for parameters to take effect*/ + vTaskDelay(100/portTICK_PERIOD_MS); + while(ESP_OK != esp_wifi_sta_get_ap_info(&wifi_ap_record)) { + /**< can't find AP*/ + vTaskDelay(100/portTICK_PERIOD_MS); + } + rssi_ant2 = 0; + rssi_max = wifi_ap_record.rssi; + rssi_min = wifi_ap_record.rssi; + for(int i = 0; i < MONITOR_TIME; i++) { + while(ESP_OK != esp_wifi_sta_get_ap_info(&wifi_ap_record)) { + /**< can't find AP*/ + vTaskDelay(100/portTICK_PERIOD_MS); + } + rssi_max = rssi_max > wifi_ap_record.rssi ? rssi_max : wifi_ap_record.rssi; + rssi_min = rssi_min < wifi_ap_record.rssi ? rssi_min : wifi_ap_record.rssi; + rssi_ant2 += wifi_ap_record.rssi; + vTaskDelay(10/portTICK_PERIOD_MS); + } + rssi_ant2 = rssi_ant2 - rssi_max - rssi_min; + ESP_LOGD(TAG, "The signal strength of the antenna two :%d", rssi_ant2); + } + + if(rssi_ant0 >= rssi_ant1 && rssi_ant0 >= rssi_ant2) { + /**< antenna zero signal strength best*/ + ESP_LOGD(TAG, "Antenna soft switching selection ant0"); + wifi_ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT0; + wifi_ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT0; + wifi_ant_config.enabled_ant0 = config->ant_zero; + wifi_ant_config.enabled_ant1 = config->ant_one; + ESP_ERROR_CHECK(esp_wifi_set_ant(&wifi_ant_config)); + } + + if(rssi_ant1 > rssi_ant0 && rssi_ant1 > rssi_ant2) { + /**< antenna one signal strength best*/ + ESP_LOGD(TAG, "Antenna soft switching selection ant1"); + wifi_ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT1; + wifi_ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT1; + wifi_ant_config.enabled_ant0 = config->ant_zero; + wifi_ant_config.enabled_ant1 = config->ant_one; + ESP_ERROR_CHECK(esp_wifi_set_ant(&wifi_ant_config)); + } + + if(rssi_ant2 > rssi_ant0 && rssi_ant2 > rssi_ant1) { + /**< antenna two signal strength best*/ + ESP_LOGD(TAG, "Antenna soft switching selection ant2"); + wifi_ant_config.rx_ant_mode = WIFI_ANT_MODE_ANT1; + wifi_ant_config.tx_ant_mode = WIFI_ANT_MODE_ANT1; + wifi_ant_config.enabled_ant0 = config->ant_zero; + wifi_ant_config.enabled_ant1 = config->ant_two; + ESP_ERROR_CHECK(esp_wifi_set_ant(&wifi_ant_config)); + } +} + +/**< Kalman filter function*/ +static int16_t KalmanFilter(int16_t inData) +{ + static float kalman = 0; + static float p = 10; + /**< Process noise*/ + float q = 0.01; + /**< Measurement noise*/ + float r = 0.2; + /**< Kalman gain*/ + float kg = 0; + + p += q; + /**< Calculate the Kalman gain*/ + kg = p / ( p + r ); + /**< Calculate the estimated value of this filtering*/ + kalman = kalman + (kg * (inData - kalman)); + /**< Updated measurement variance*/ + p = (1 - kg) * p; + + return (int16_t)(kalman + 0.5); +} + +static void antenna_soft_switching_task(void *arg) +{ + QueueHandle_t xQueue_rssi_single_handle, xQueue_rssi_sum_handle; + wifi_ap_record_t wifi_ap_record; + int8_t rssi_data_in = 0, rssi_data_out = 0; + int16_t rssi_sum = 0, rssi_last_sum = 0, rssi_save_sum = 0; + int8_t rssi_flag = 0; + uint16_t queue_rssi_single_size = 0, queue_rssi_sum_size = 0; + BaseType_t ret; + + wifi_antenna_auto_switch_config_t *config = ( wifi_antenna_auto_switch_config_t *)arg; + + xQueue_rssi_single_handle = xQueueCreate(QUEUE_LENGTH_RSSI_SINGLE, RSSI_SINGLE_SIZE); + xQueue_rssi_sum_handle = xQueueCreate(QUEUE_LENGTH_RSSI_SUM, RSSI_SUM_SIZE); + + while(true) { + while(ESP_OK != esp_wifi_sta_get_ap_info(&wifi_ap_record)) { + /**< can't find AP*/ + vTaskDelay(100/portTICK_PERIOD_MS); + } + /**< Filter the current rssi*/ + rssi_data_in = KalmanFilter(wifi_ap_record.rssi); + + /**< Save real-time rssi single*/ + if (xQueueSend(xQueue_rssi_single_handle, (void *)&rssi_data_in, ( TickType_t ) 0) == pdPASS ) { + rssi_sum += rssi_data_in; + queue_rssi_single_size++; + ESP_LOGD(TAG, "rssi_data_in:%d", rssi_data_in); + } + + /**< Rssi single queue full*/ + if(queue_rssi_single_size >= RSSI_SINGLE_SIZE) { + xQueueReceive( xQueue_rssi_single_handle, &rssi_data_out, ( TickType_t ) 0); + queue_rssi_single_size--; + rssi_sum -= rssi_data_out; + /**< Save real-time rssi sum*/ + if( xQueueSend(xQueue_rssi_sum_handle, (void *)&rssi_sum, ( TickType_t ) 0) == pdPASS ) { + queue_rssi_sum_size++; + } + + /**< Rssi sum queue full*/ + if (queue_rssi_sum_size >= RSSI_SUM_SIZE) { + xQueueReceive( xQueue_rssi_sum_handle, &rssi_last_sum, ( TickType_t ) 0); + queue_rssi_sum_size--; + if (abs(rssi_last_sum - rssi_sum)> ((config->ant_switch) * 2 / 3 ) && rssi_flag == 0) { + rssi_save_sum = rssi_last_sum; + rssi_flag = 1; + ESP_LOGD(TAG, "Start listening rssi change"); + } + if(rssi_flag > 0) { + rssi_flag++; + /**< Wait for 6 seconds to check whether the environment is normal*/ + if (rssi_flag > WAIT_TIME) { + ESP_LOGD(TAG, "End of listening rssi"); + /**< Ambient noise factor: abs(rssi_last_sum - rssi_sum) * RSSI_KD*/ + int16_t ans = abs(rssi_save_sum - rssi_sum) - abs(rssi_last_sum - rssi_sum) * RSSI_KD; + rssi_flag = 0; + if(ans > (config->ant_switch)) { + /**< Determine that the signal has changed*/ + queue_rssi_sum_size = 0; + queue_rssi_single_size = 0; + ESP_LOGD(TAG, "monitor result:%d > %d", ans, (config->ant_switch)); + /**< Select the optimal antenna*/ + antenna_switch_function(config); + /**< Wait for parameters to take effect*/ + vTaskDelay(100 / portTICK_PERIOD_MS); + do + { + /**< Clear the rssi single queue*/ + ret = xQueueReceive(xQueue_rssi_single_handle, &rssi_data_out, 0); + } while (ret != pdFALSE); + do + { + /**< Clear the rssi sum queue*/ + ret = xQueueReceive(xQueue_rssi_sum_handle, &rssi_data_out, 0); + } while (ret != pdFALSE); + } + } + } + } + } + vTaskDelay(100 / portTICK_PERIOD_MS); + } +} + +esp_err_t esp_wifi_set_ant_soft_switch(const wifi_antenna_auto_switch_config_t *config) +{ + BaseType_t ret; + + /**< Refresh configuration parameters*/ + wifi_three_ant_auto_get_config = *config; + /**< Select the optimal antenna*/ + antenna_switch_function(config); + + ret = xTaskCreatePinnedToCore(antenna_soft_switching_task, SOFT_SWITCHING_NAME, SOFT_SWITCHING_STACK, (void *)config, SOFT_SWITCHING_PRIORITY, &antenna_task_handle, portNUM_PROCESSORS - 1); + if (ret != pdPASS) { + ESP_LOGE(TAG, "create task %s failed", SOFT_SWITCHING_NAME); + return ESP_FAIL; + } + + return ESP_OK; +} + +esp_err_t esp_wifi_get_ant_soft_switch_config(wifi_antenna_auto_switch_config_t *config) +{ + *config = wifi_three_ant_auto_get_config; + + return ESP_OK; +} + +void esp_deinit_ant_soft_switch(void) +{ + vTaskDelete(antenna_task_handle); +} diff --git a/examples/wifi/antenna/components/antenna_soft_switch/component.mk b/examples/wifi/antenna/components/antenna_soft_switch/component.mk new file mode 100755 index 0000000000..a98f634eae --- /dev/null +++ b/examples/wifi/antenna/components/antenna_soft_switch/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/wifi/antenna/components/antenna_soft_switch/include/antenna_switch.h b/examples/wifi/antenna/components/antenna_soft_switch/include/antenna_switch.h new file mode 100755 index 0000000000..d3aa655b19 --- /dev/null +++ b/examples/wifi/antenna/components/antenna_soft_switch/include/antenna_switch.h @@ -0,0 +1,54 @@ +/* + * Design of antenna soft switching : 2023.02.21 + * + * version:v1.0 + */ +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief WiFi antenna auto switch configuration + * + */ +typedef struct { + uint8_t ant_num; /**< WiFi use antenna numbers 2 or 3*/ + uint8_t ant_zero; /**< WiFi antenna zero select*/ + uint8_t ant_one; /**< WiFi antenna one select*/ + uint8_t ant_two; /**< WiFi antenna two select*/ + int16_t ant_switch; /**< WiFi antenna auto switch sensitive*/ +} wifi_antenna_auto_switch_config_t; + +/** + * @brief Set antenna auto configuration + * + * @param config Antenna auto configuration. + * + * @return + * - ESP_OK: succeed + * - ESP_FAIL: error + */ +esp_err_t esp_wifi_set_ant_soft_switch(const wifi_antenna_auto_switch_config_t *config); + +/** + * @brief Get antenna auto configuration + * + * @param config Antenna auto configuration. + * + * @return + * - ESP_OK: succeed + */ +esp_err_t esp_wifi_get_ant_soft_switch_config(wifi_antenna_auto_switch_config_t *config); + +/** + * @brief Delete antenna soft switching task + */ +void esp_deinit_ant_soft_switch(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/wifi/antenna/main/CMakeLists.txt b/examples/wifi/antenna/main/CMakeLists.txt new file mode 100755 index 0000000000..1968071ab9 --- /dev/null +++ b/examples/wifi/antenna/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "antenna_switch_example_main.c" + REQUIRES nvs_flash esp_wifi antenna_soft_switch) + diff --git a/examples/wifi/antenna/main/Kconfig.projbuild b/examples/wifi/antenna/main/Kconfig.projbuild new file mode 100755 index 0000000000..a43c1b8f53 --- /dev/null +++ b/examples/wifi/antenna/main/Kconfig.projbuild @@ -0,0 +1,47 @@ +menu "Example Configuration" + + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + + config ESP_MAXIMUM_RETRY + int "Maximum retry" + default 5 + help + Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. + + choice ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD + prompt "WiFi Scan auth mode threshold" + default ESP_WIFI_AUTH_WPA2_PSK + help + The weakest authmode to accept in the scan mode. + This value defaults to ESP_WIFI_AUTH_WPA2_PSK incase password is present and ESP_WIFI_AUTH_OPEN is used. + Please select ESP_WIFI_AUTH_WEP/ESP_WIFI_AUTH_WPA_PSK incase AP is operating in WEP/WPA mode. + + config ESP_WIFI_AUTH_OPEN + bool "OPEN" + config ESP_WIFI_AUTH_WEP + bool "WEP" + config ESP_WIFI_AUTH_WPA_PSK + bool "WPA PSK" + config ESP_WIFI_AUTH_WPA2_PSK + bool "WPA2 PSK" + config ESP_WIFI_AUTH_WPA_WPA2_PSK + bool "WPA/WPA2 PSK" + config ESP_WIFI_AUTH_WPA3_PSK + bool "WPA3 PSK" + config ESP_WIFI_AUTH_WPA2_WPA3_PSK + bool "WPA2/WPA3 PSK" + config ESP_WIFI_AUTH_WAPI_PSK + bool "WAPI PSK" + endchoice + +endmenu diff --git a/examples/wifi/antenna/main/antenna_switch_example_main.c b/examples/wifi/antenna/main/antenna_switch_example_main.c new file mode 100755 index 0000000000..ed50441bb5 --- /dev/null +++ b/examples/wifi/antenna/main/antenna_switch_example_main.c @@ -0,0 +1,187 @@ +/* WiFi station 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 "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_wifi.h" + +#include "lwip/err.h" +#include "lwip/sys.h" +#include "antenna_switch.h" + +/* The examples use WiFi configuration that you can set via project configuration menu + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY + +#if CONFIG_ESP_WIFI_AUTH_OPEN +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN +#elif CONFIG_ESP_WIFI_AUTH_WEP +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP +#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK +#endif + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t s_wifi_event_group; + +/* The event group allows multiple bits for each event, but we only care about two events: + * - we are connected to the AP with an IP + * - we failed to connect after the maximum amount of retries */ +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + +static const char *TAG = "multi-antenna example"; + +static int s_retry_num = 0; + + +static void event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } else { + xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + } + ESP_LOGI(TAG,"connect to the AP fail"); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); + s_retry_num = 0; + xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } +} + +void wifi_init_sta(void) +{ + s_wifi_event_group = xEventGroupCreate(); + + ESP_ERROR_CHECK(esp_netif_init()); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &event_handler, + NULL, + &instance_any_id)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, + &event_handler, + NULL, + &instance_got_ip)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_ESP_WIFI_SSID, + .password = EXAMPLE_ESP_WIFI_PASS, + /* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8). + * If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value + * to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to + * WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards. + */ + .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD, + .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + + /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum + * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */ + EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, + WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually + * happened. */ + if (bits & WIFI_CONNECTED_BIT) { + ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); + } else if (bits & WIFI_FAIL_BIT) { + ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); + } else { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } +} + +void app_main(void) +{ + //Initialize NVS + 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); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); + wifi_init_sta(); + + wifi_ant_gpio_config_t ant_gpio_config = { + // ESP32-WROOM-DA boards default antenna pins + .gpio_cfg[0] = {.gpio_select = 1, .gpio_num = 21}, + .gpio_cfg[1] = {.gpio_select = 1, .gpio_num = 22}, + }; + ESP_ERROR_CHECK(esp_wifi_set_ant_gpio(&ant_gpio_config)); + ESP_ERROR_CHECK(esp_wifi_get_ant_gpio(&ant_gpio_config)); + ESP_LOGI(TAG, "GPIO: [0].pin = %d, [1].pin = %d",ant_gpio_config.gpio_cfg[0].gpio_num, ant_gpio_config.gpio_cfg[1].gpio_num); + + wifi_antenna_auto_switch_config_t wifi_antenna_auto_switch_config; + wifi_antenna_auto_switch_config.ant_num = 3; + wifi_antenna_auto_switch_config.ant_zero = 0; + wifi_antenna_auto_switch_config.ant_one = 1; + wifi_antenna_auto_switch_config.ant_two = 3; + wifi_antenna_auto_switch_config.ant_switch = 35; + ESP_ERROR_CHECK(esp_wifi_set_ant_soft_switch(&wifi_antenna_auto_switch_config)); + + while(true) { + wifi_ant_config_t ant_config; + esp_wifi_get_ant(&ant_config); + ESP_LOGI(TAG, "rx mode = %d, tx mode = %d, ant0_en = %d, ant1_en = %d",ant_config.rx_ant_mode, ant_config.tx_ant_mode, ant_config.enabled_ant0, ant_config.enabled_ant1); + vTaskDelay(500 / portTICK_PERIOD_MS); + } +} diff --git a/examples/wifi/antenna/pytest_wifi_antenna_soft_switch.py b/examples/wifi/antenna/pytest_wifi_antenna_soft_switch.py new file mode 100755 index 0000000000..8761adf282 --- /dev/null +++ b/examples/wifi/antenna/pytest_wifi_antenna_soft_switch.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import os.path +from typing import Tuple + +import pytest +from pytest_embedded_idf.dut import IdfDut + +# @pytest.mark.supported_targets +# This test should support all targets, even between different target types +# For now our CI only support multi dut with esp32 +# If you want to enable different target type, please use the following param +# @pytest.mark.parametrize( +# 'count, app_path, target', [ +# (2, +# f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}', +# 'esp32|esp32s2'), +# ], +# indirect=True, +# ) + + +@pytest.mark.esp32 +@pytest.mark.esp32c3 +@pytest.mark.esp32s3 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, app_path', [ + (2, + f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}'), + ], indirect=True +) +def test_wifi_getting_started(dut: Tuple[IdfDut, IdfDut]) -> None: + softap = dut[0] + station = dut[1] + + ssid = softap.app.sdkconfig.get('ESP_WIFI_SSID') + password = softap.app.sdkconfig.get('ESP_WIFI_PASSWORD') + assert station.app.sdkconfig.get('ESP_WIFI_SSID') == ssid + assert station.app.sdkconfig.get('ESP_WIFI_PASSWORD') == password + + tag = 'wifi station' + station.expect(f'{tag}: got ip:', timeout=60) + station.expect(f'{tag}: connected to ap SSID:{ssid} password:{password}', timeout=60) + softap.expect('station .+ join, AID=', timeout=60) + + +@pytest.mark.esp32c2 +@pytest.mark.wifi_two_dut +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, config, baud, app_path', [ + (2, 'esp32c2_xtal26m', '74880', + f'{os.path.join(os.path.dirname(__file__), "softAP")}|{os.path.join(os.path.dirname(__file__), "station")}'), + ], indirect=True +) +def test_wifi_getting_started_esp32c2_xtal_26mhz(dut: Tuple[IdfDut, IdfDut]) -> None: + softap = dut[0] + station = dut[1] + + ssid = softap.app.sdkconfig.get('ESP_WIFI_SSID') + password = softap.app.sdkconfig.get('ESP_WIFI_PASSWORD') + assert station.app.sdkconfig.get('ESP_WIFI_SSID') == ssid + assert station.app.sdkconfig.get('ESP_WIFI_PASSWORD') == password + + tag = 'wifi station' + station.expect(f'{tag}: got ip:', timeout=60) + station.expect(f'{tag}: connected to ap SSID:{ssid} password:{password}', timeout=60) + softap.expect('station .+ join, AID=', timeout=60) diff --git a/examples/wifi/antenna/sdkconfig.ci b/examples/wifi/antenna/sdkconfig.ci new file mode 100755 index 0000000000..b416e9f87c --- /dev/null +++ b/examples/wifi/antenna/sdkconfig.ci @@ -0,0 +1,2 @@ +CONFIG_ESP_WIFI_SSID="ssid_${IDF_TARGET}_${CI_PIPELINE_ID}" +CONFIG_ESP_WIFI_PASSWORD="password_${IDF_TARGET}_${CI_PIPELINE_ID}" diff --git a/examples/wifi/antenna/sdkconfig.ci.esp32c2_xtal26m b/examples/wifi/antenna/sdkconfig.ci.esp32c2_xtal26m new file mode 100755 index 0000000000..172f022b67 --- /dev/null +++ b/examples/wifi/antenna/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y