基于ESP32S3芯片的机器人控制器设计与实现
一、系统架构概览整个系统采用事件驱动 多任务协作的方式主要包含以下模块模块功能Wi-Fi 管理自动连接、断线重连、WPS 配网、NVS 持久化存储网络通信TCP可靠控制 UDP低延迟指令双通道任务调度FreeRTOS 任务划分控制指令、ADC 采集、UART 监听等外设驱动ADC摇杆/电池、UART1关节反馈、GPIOWPS 按键协议封装自定义机器人控制协议心跳、动作、基准匹配等系统启动后优先完成 Wi-Fi 连接随后并行启动多个任务形成“感知-决策-执行-反馈”闭环二、Wi-Fi 连接与容错机制1. 智能配网策略系统支持两种配网方式静态配置通过EXAMPLE_ESP_WIFI_SSID和EXAMPLE_ESP_WIFI_PASS编译时写入。动态 WPS用户按下物理按键触发 WPS自动获取 AP 凭据。// WPS 成功后保存 SSID密码可选 board_write_string(wifi_name, (char*)event-ssid);2. 无限重连机制通过设置EXAMPLE_ESP_MAXIMUM_RETRY 0xFFFFFFFF实现永不放弃重连if (s_retry_num EXAMPLE_ESP_MAXIMUM_RETRY) { esp_wifi_connect(); s_retry_num; }三、TCP/UDP 双通道通信设计为什么需要双通道协议优势适用场景TCP可靠、有序、保序心跳包、基准参数查询、关键控制指令UDP低延迟、无连接开销实时动作指令如舵机角度、电机速度1. TCP 客户端可靠控制通道连接到固定 IP192.168.28.1:19345接收服务器下发的控制指令如cmd_echo_resolve()解析断开后自动重建连接2. UDP 客户端实时指令通道发送至同一 IP 的192.168.28.1:19346用于发送ROBOT_MOVE_CTL、ROBOT_ACTION_CTL等高频指令3. 任务协同misc_task_demonstrate从队列读取指令优先通过 TCP 发送四、FreeRTOS 多任务调度系统创建了四个核心任务优先级由board_priority.h定义任务功能周期tcp_udp_client_connect_task管理网络连接持续运行misc_task_demonstrate处理控制指令、发送心跳100ms心跳 300msadc_sample_task采集摇杆、电池电压事件驱动ADC DMA 完成中断唤醒uart1_event_task监听关节反馈数据事件驱动UART 中断结语这份机器人控制器代码展现了嵌入式系统开发的范式以可靠性为核心兼顾实时性与可维护性。通过 Wi-Fi 双通道通信、WPS 配网、多任务协同等设计为中小型机器人提供了低成本、高灵活性的控制方案。代码如下/* BSD Socket API 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 string.h #include sys/param.h #include freertos/FreeRTOS.h #include freertos/event_groups.h #include freertos/task.h #include esp_system.h #include esp_wifi.h #include esp_mac.h #include esp_event.h #include esp_log.h #include nvs_flash.h #include esp_netif.h #include protocol_examples_common.h #include arpa/inet.h #include unistd.h #include lwip/err.h #include lwip/sockets.h #include lwip/sys.h #include lwip/netdb.h #include lwip/dns.h #include lwip/ip_addr.h #include board_version.h #include board_priority.h #include board_utils.h #include board_xor_enc.h #include board_hp_check.h #include board_sta_wps.h #include board_ap_wps.h #include board_gpio_out.h #include board_gpio_in.h #include board_nvs.h #include board_led.h #include board_motor.h #include board_i2c.h #include board_adc.h #include board_uart0.h #include board_uart1.h #include board_mavlink.h #include board_queue.h #include board_servo_ctl.h #include board_map_joint.h #include board_scan_wifi.h #include board_com_check.h #include board_boot_verify.h #include board_protocol.h #include board_robot_ctl_protocol.h /* The examples use WiFi configuration that you can set via project configuration menu If youd 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 R0X-G28 #define EXAMPLE_ESP_WIFI_PASS 12345678 //连接不上需要一直尝试连接断开了也需要一直尝试连接 #define EXAMPLE_ESP_MAXIMUM_RETRY (0xFFFFFFFF)//(10) /* 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 BOT-CONTROLLER-TAG; #define HOST_IP_ADDR 192.168.28.1 #define TCP_PORT (19345) #define UDP_PORT (19346) #ifndef PIN2STR #define PIN2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7] #define PINSTR %c%c%c%c%c%c%c%c #endif static wifi_config_t wps_ap_creds[MAX_WPS_AP_CRED]; static int s_ap_creds_num 0; //wifi重新连接次数累计 static int s_retry_num 0; /** * -1:断开 * 0:正在连接 * 1:连接上 * */ int global_wifi_connect -1; //udp服务端地址 static struct sockaddr_in dest_addr; //全局udp服务端连接句柄 static int global_udp_sock -1; //全部tcp服务端连接句柄 static int global_tcp_sock -1; //全部tcp客户端连接状态 static int global_tcp_connect 0; //获取机器的benchmark状态 int global_is_got_benchmark 0; //采集的多通道adc static int adc_voltages[SAMPLE_CHANNELS_SIZE] {0}; static void do_udpsock_write(uint8_t*buf,uint8_t len) { if(global_udp_sock 0) return; // send() can return less bytes than supplied length. // Walk-around for robust implementation. int to_write len; while (to_write 0) { int written sendto(global_udp_sock, buf (len - to_write), to_write, 0, (struct sockaddr *)dest_addr, sizeof(dest_addr)); if (written 0) { ESP_LOGE(TAG, udp Error occurred during sending: errno %d, errno); // Failed to retransmit, giving up return; } to_write - written; } } static void udp_client_close(void) { if (global_udp_sock 0) { ESP_LOGE(TAG, udp Shutting down socket and restarting...); shutdown(global_udp_sock, 0); close(global_udp_sock); global_udp_sock -1; } } //tcp数据发送 static void do_tcpsock_write(uint8_t*buf,uint8_t len) { // printf(buf is:); // print0x(buf,len); // printf(global_sock_handle%d\n,global_sock_handle); if(global_tcp_sock 0) return; // send() can return less bytes than supplied length. // Walk-around for robust implementation. int to_write len; while (to_write 0) { int written send(global_tcp_sock, buf (len - to_write), to_write, 0); if (written 0) { ESP_LOGE(TAG, tcp Error occurred during sending: errno %d, errno); // Failed to retransmit, giving up return; } to_write - written; } } static void tcp_client_close(void) { if (global_tcp_sock 0) { ESP_LOGE(TAG, tcp Shutting down socket and restarting...); shutdown(global_tcp_sock, 0); close(global_tcp_sock); global_tcp_sock -1; } } static void udp_client_init(void *pvParameters) { char host_ip[] HOST_IP_ADDR; int addr_family 0; int ip_protocol 0; #if defined(CONFIG_EXAMPLE_IPV4) dest_addr.sin_addr.s_addr inet_addr(host_ip); dest_addr.sin_family AF_INET; dest_addr.sin_port htons(UDP_PORT); addr_family AF_INET; ip_protocol IPPROTO_IP; #elif defined(CONFIG_EXAMPLE_IPV6) struct sockaddr_in6 dest_addr { 0 }; inet6_aton(HOST_IP_ADDR, dest_addr.sin6_addr); dest_addr.sin6_family AF_INET6; dest_addr.sin6_port htons(PORT); dest_addr.sin6_scope_id esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE); addr_family AF_INET6; ip_protocol IPPROTO_IPV6; #elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN) struct sockaddr_storage dest_addr { 0 }; ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_DGRAM, ip_protocol, addr_family, dest_addr)); #endif global_udp_sock socket(addr_family, SOCK_DGRAM, ip_protocol); if (global_udp_sock 0) { ESP_LOGE(TAG, Unable to create udp socket: errno %d, errno); vTaskDelay(100 / portTICK_PERIOD_MS);//100ms return; } ESP_LOGI(TAG, udp Socket created, sending to %s:%d, HOST_IP_ADDR, UDP_PORT); } /** * 处理所有的非实时任务(慢速指令),遥控下发周期杂项任务 * */ static void misc_task_demonstrate(void* arg) { uint8_t reusebuf[128]; uint8_t reusebuflen 0; uint32_t base_cnt 0; uint8_t*sendata NULL; uint8_t sendatalen 0; for(;;) { //100ms loop if(board_queue_recv(reusebuf, reusebuflen)) { do_tcpsock_write(reusebuf, reusebuflen); } //300ms loop if(!(base_cnt % 3) global_tcp_connect) { if(!global_is_got_benchmark) { sendata ROBOT_GET_BENCHMARK(sendatalen); } else { sendata ROBOT_HEARTPACKET_CTL(sendatalen); } board_queue_send(sendata, sendatalen); } // //for test udp // if(!(base_cnt % 5) global_tcp_connect) // { // sendata ROBOT_MOVE_CTL(1,30,2,90,sendatalen); // print0x(sendata,sendatalen); // //board_queue_send(sendata, sendatalen); // do_udpsock_write(sendata, sendatalen); // // vTaskDelay(10 / portTICK_PERIOD_MS); // // uint8_t servo_data[] {0x12,0x88,0x57,0x99}; // sendata ROBOT_ACTION_CTL(1000,servo_data,sizeof(servo_data),sendatalen); // print0x(sendata,sendatalen); // //board_queue_send(sendata, sendatalen); // do_udpsock_write(sendata, sendatalen); // // } base_cnt; //100ms vTaskDelay(100 / portTICK_PERIOD_MS); } } /** * adc采集任务比如按键,摇杆,电池等 * */ static void adc_sample_task(void* arg) { int i; esp_err_t ret; uint32_t ret_num 0; //读取一帧采集数据,每四个字节解析一次 uint8_t result[EXAMPLE_READ_LEN] {0xCC}; //每个通道一次采集的数据就是 EXAMPLE_READ_LEN / 4 / SAMPLE_CHANNELS_SIZE uint32_t chan_sum[SAMPLE_CHANNELS_SIZE] {0x00}; uint32_t chan_sum_cnt[SAMPLE_CHANNELS_SIZE] {0x00}; /** * 注意s_task_handle必须保证初始化和执行读取在同一个线程中 * 否则ulTaskNotifyTake接收不到事件 * */ board_adc_init_and_start(); while(1) { //wifi没有连接上就处于空闲等待状态 if(global_wifi_connect 0) { vTaskDelay(100 / portTICK_PERIOD_MS);//100ms continue; } ulTaskNotifyTake(pdTRUE, portMAX_DELAY); while (1) { ret adc_continuous_read(adc_handle, result, EXAMPLE_READ_LEN, ret_num, 0); if(ret ESP_OK) { for (i 0; i ret_num; i SOC_ADC_DIGI_RESULT_BYTES) { //每四个字节一个结果,结果中包含channel和data adc_digi_output_data_t *p (void*)result[i]; uint32_t chan_num EXAMPLE_ADC_GET_CHANNEL(p); uint32_t data EXAMPLE_ADC_GET_DATA(p); /* Check the channel number validation, the data is invalid if the channel num exceed the maximum channel */ if (chan_num SOC_ADC_CHANNEL_NUM(EXAMPLE_ADC_UNIT)) { chan_sum[chan_num - 1] data; chan_sum_cnt[chan_num - 1]; } } ////////一次采集读取完成 for(i 0;i SAMPLE_CHANNELS_SIZE;i) { adc_cali_raw_to_voltage(adc_cali_handel[i], chan_sum[i] / chan_sum_cnt[i], adc_voltages[i]); //复位累加计和 chan_sum[i] chan_sum_cnt[i] 0; } // for(i 0;i SAMPLE_CHANNELS_SIZE;i) // { // printf(adc_voltages[%d]%d\n,i,adc_voltages[i]); // } } else if (ret ESP_ERR_TIMEOUT) { break; } } } } static void uart1_event_task(void *pvParameters) { uart_event_t event; size_t buffered_size; uint8_t* dtmp (uint8_t*) malloc(RD_BUF_SIZE); for(;;) { //Waiting for UART event. if(xQueueReceive(uart1_queue, (void * )event, (TickType_t)portMAX_DELAY)) { //bzero(dtmp, RD_BUF_SIZE); //ESP_LOGI(UART1_TAG, uart[%d] event:, EX_UART_NUM); switch(event.type) { //Event of UART receving data /*Wed better handler data event fast, there would be much more data events than other types of events. If we take too much time on data event, the queue might be full.*/ case UART_DATA: //ESP_LOGI(UART1_TAG, [UART DATA]: %d, event.size); uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY); //ESP_LOGI(UART1_TAG, [DATA EVT]:); //uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size); print0x(dtmp,event.size); break; //Event of HW FIFO overflow detected case UART_FIFO_OVF: ESP_LOGI(UART1_TAG, hw fifo overflow); // If fifo overflow happened, you should consider adding flow control for your application. // The ISR has already reset the rx FIFO, // As an example, we directly flush the rx buffer here in order to read more data. uart_flush_input(EX_UART_NUM); xQueueReset(uart1_queue); break; //Event of UART ring buffer full case UART_BUFFER_FULL: ESP_LOGI(UART1_TAG, ring buffer full); // If buffer full happened, you should consider increasing your buffer size // As an example, we directly flush the rx buffer here in order to read more data. uart_flush_input(EX_UART_NUM); xQueueReset(uart1_queue); break; //Event of UART RX break detected case UART_BREAK: ESP_LOGI(UART1_TAG, uart rx break); break; //Event of UART parity check error case UART_PARITY_ERR: ESP_LOGI(UART1_TAG, uart parity error); break; //Event of UART frame error case UART_FRAME_ERR: ESP_LOGI(UART1_TAG, uart frame error); break; //UART_PATTERN_DET case UART_PATTERN_DET: uart_get_buffered_data_len(EX_UART_NUM, buffered_size); int pos uart_pattern_pop_pos(EX_UART_NUM); ESP_LOGI(UART1_TAG, [UART PATTERN DETECTED] pos: %d, buffered size: %d, pos, buffered_size); if (pos -1) { // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not // record the position. We should set a larger queue size. // As an example, we directly flush the rx buffer here. uart_flush_input(EX_UART_NUM); } else { uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS); uint8_t pat[PATTERN_CHR_NUM 1]; memset(pat, 0, sizeof(pat)); uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS); ESP_LOGI(UART1_TAG, read data: %s, dtmp); ESP_LOGI(UART1_TAG, read pat : %s, pat); } break; //Others default: ESP_LOGI(UART1_TAG, uart event type: %d, event.type); break; } } } free(dtmp); dtmp NULL; vTaskDelete(NULL); } /**tcp udp网络通信双通道管理和控制 * */ static void tcp_udp_client_connect_task(void *pvParameters) { unsigned char rx_buffer[128]; char host_ip[] HOST_IP_ADDR; int addr_family 0; int ip_protocol 0; int len; while (1) { //wifi没有连接上就处于空闲等待状态 if(global_wifi_connect 0) { vTaskDelay(100 / portTICK_PERIOD_MS);//100ms continue; } global_tcp_connect 0; global_is_got_benchmark 0; udp_client_init(pvParameters); #if defined(CONFIG_EXAMPLE_IPV4) struct sockaddr_in dest_addr; inet_pton(AF_INET, host_ip, dest_addr.sin_addr); dest_addr.sin_family AF_INET; dest_addr.sin_port htons(TCP_PORT); addr_family AF_INET; ip_protocol IPPROTO_IP; #elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN) struct sockaddr_storage dest_addr { 0 }; ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_STREAM, ip_protocol, addr_family, dest_addr)); #endif global_tcp_sock socket(addr_family, SOCK_STREAM, ip_protocol); if (global_tcp_sock 0) { ESP_LOGE(TAG, tcp nable to create socket: errno %d, errno); vTaskDelay(100 / portTICK_PERIOD_MS);//100ms continue; } ESP_LOGI(TAG, tcp Socket created, connecting to %s:%d, host_ip, TCP_PORT); int err connect(global_tcp_sock, (struct sockaddr *)dest_addr, sizeof(dest_addr)); if (err ! 0) { ESP_LOGE(TAG, tcp Socket unable to connect: errno %d, errno); tcp_client_close(); vTaskDelay(100 / portTICK_PERIOD_MS);//100ms continue; } global_tcp_connect 1; ESP_LOGI(TAG, tcp Successfully connected); while (1) { // int err send(sock, payload, strlen(payload), 0); // if (err 0) { // ESP_LOGE(TAG, Error occurred during sending: errno %d, errno); // break; // } len recv(global_tcp_sock, rx_buffer, sizeof(rx_buffer) - 1, 0); // Error occurred during receiving if (len 0) { ESP_LOGE(TAG, tcp recv failed: errno %d, errno); break; } else if(0 len) { ESP_LOGE(TAG, tcp server force closed!); break; } // Data received else { //rx_buffer[len] 0; // Null-terminate whatever we received and treat like a string //ESP_LOGI(TAG, tcp Received %d bytes from %s:, len, host_ip); //ESP_LOGI(TAG, %s, rx_buffer); cmd_echo_resolve(rx_buffer,len); } } global_tcp_connect 0; tcp_client_close(); udp_client_close(); } } 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) { global_wifi_connect -1; esp_wifi_connect(); } else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_DISCONNECTED) { if(!board_gpio_get_wps_key_status()) { /** * 这种基于事件的重连方式不错 * */ if (s_retry_num EXAMPLE_ESP_MAXIMUM_RETRY) { global_wifi_connect 0; esp_wifi_connect(); s_retry_num; ESP_LOGI(TAG, retry to connect to the AP); } else { global_wifi_connect -1; xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } ESP_LOGI(TAG,connect to the AP fail); } } else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_CONNECTED) { //此处获取bssid,wifi aps wlan mac wifi_event_sta_connected_t* event (wifi_event_sta_connected_t*) event_data; //printf(get aps bssid:); //print0x(event-bssid,sizeof(event-bssid)); uint16_t chs Crc_Calculate(event-bssid, sizeof(event-bssid)); set_send_mavlink_protocol_crc(chs 8,chs 0xFF); //printf(aps mac chs%04X\n,chs); /** * 很奇怪在WIFI_EVENT_STA_WPS_ER_SUCCESS中获取不到wifi ssid和passwd, * 反正wps配对成功后会连接成功,在此时保存连接信息即可,可惜没有passwd不过使用公用的也可以 * */ //save wifi info //board_write_string(wifi_name, (char*)event-ssid); //board_write_string(wifi_passwd, EXAMPLE_ESP_WIFI_PASS); char str[32] {0}; size_t str_len sizeof(str); esp_err_t err; err board_read_string(wifi_name, str, str_len); if(err ESP_OK str_len 0) { str[str_len] 0; //和已经保存的ssid不一致才需要重新保存 if(strcmp((char*)event-ssid,(char*)str)) { board_write_string(wifi_name, (char*)event-ssid); printf(wifi name differ,need save!\n); } } else { //没有保存ssid就立即保存 if(ESP_ERR_NVS_NOT_FOUND err) { board_write_string(wifi_name, (char*)event-ssid); printf(wifi name not found,need save!\n); } } } 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); global_wifi_connect 1; } //wps连接 switch (event_id) { case WIFI_EVENT_STA_WPS_ER_SUCCESS: ESP_LOGI(TAG, WIFI_EVENT_STA_WPS_ER_SUCCESS); { wifi_event_sta_wps_er_success_t *evt (wifi_event_sta_wps_er_success_t *)event_data; int i; if (evt) { s_ap_creds_num evt-ap_cred_cnt; for (i 0; i s_ap_creds_num; i) { memcpy(wps_ap_creds[i].sta.ssid, evt-ap_cred[i].ssid, sizeof(evt-ap_cred[i].ssid)); memcpy(wps_ap_creds[i].sta.password, evt-ap_cred[i].passphrase, sizeof(evt-ap_cred[i].passphrase)); } /* If multiple AP credentials are received from WPS, connect with first one */ ESP_LOGI(TAG, Connecting to SSID: %s, Passphrase: %s, wps_ap_creds[0].sta.ssid, wps_ap_creds[0].sta.password); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, wps_ap_creds[0]) ); } //此处已经说明只有一个ap wps则没有event data直接连接即可 /* * If only one AP credential is received from WPS, there will be no event data and * esp_wifi_set_config() is already called by WPS modules for backward compatibility * with legacy apps. So directly attempt connection here. */ ESP_ERROR_CHECK(esp_wifi_wps_disable()); sta_wps_set_er_status(true); esp_wifi_connect(); } break; case WIFI_EVENT_STA_WPS_ER_FAILED: ESP_LOGI(TAG, WIFI_EVENT_STA_WPS_ER_FAILED); sta_wps_restart(); break; case WIFI_EVENT_STA_WPS_ER_TIMEOUT: ESP_LOGI(TAG, WIFI_EVENT_STA_WPS_ER_TIMEOUT); sta_wps_restart(); break; case WIFI_EVENT_STA_WPS_ER_PIN: ESP_LOGI(TAG, WIFI_EVENT_STA_WPS_ER_PIN); /* display the PIN code */ wifi_event_sta_wps_er_pin_t* event (wifi_event_sta_wps_er_pin_t*) event_data; printf(display pincode%s\n,(char*)event-pin_code); break; default: break; } } 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 WIFI_AUTH_WPA3_PSK, .sae_pwe_h2e WPA3_SAE_PWE_BOTH, .sae_h2e_identifier , }, }; /** * 获取已经保存的wifipassword * */ char str[32] {0}; size_t str_len sizeof(str); esp_err_t err; err board_read_string(wifi_name, str, str_len); if(err ESP_OK str_len 0) { str[str_len] 0; strcpy((char*)wifi_config.sta.ssid,str); printf(get saved wifi_name%s\n,str); memset(str,0,sizeof(str)); str_len sizeof(str); } err board_read_string(wifi_passwd, str, str_len); if(err ESP_OK str_len 0) { str[str_len] 0; strcpy((char*)wifi_config.sta.password,str); printf(get saved wifi_passwd%s\n,str); } ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, wifi_config) ); //禁止modem休眠,降低延迟 ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); ESP_ERROR_CHECK(esp_wifi_start() ); ESP_LOGI(TAG, wifi_init_sta finished.); //不需要堵塞等候连接不过没有连接堵塞在这里也不搓也没必要后续初始化和任务启动,只需要wps已经启动即可 /* 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); ESP_LOGI(TAG, connected to ap SSID:%s password:%s, wifi_config.sta.ssid, wifi_config.sta.password); } 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) { /** * 可以屏蔽app启动后log,但是启动前包括bootloader,freertos的还需要menuconfig * */ //esp_log_level_set(TAG, ESP_LOG_NONE); //ESP_ERROR_CHECK(nvs_flash_init()); //ESP_ERROR_CHECK(esp_netif_init()); //ESP_ERROR_CHECK(esp_event_loop_create_default()); /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. * Read Establishing Wi-Fi or Ethernet Connection section in * examples/protocols/README.md for more information about this function. */ //ESP_ERROR_CHECK(example_connect()); //Initialize NVS //flash模拟eeprom 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); board_boot_verify(); //wps key start gpio_in_init(); //uart1关节采集 uart1_init(); //wifi一直连接直到成功为止,会堵塞后面的 wifi_init_sta(); board_queue_init(); //#ifdef CONFIG_EXAMPLE_IPV4 // xTaskCreate(tcp_server_task, tcp_server, 4096, (void*)AF_INET, TCP_SERVER_TASK_PRIORITY, NULL); //#endif ////#ifdef CONFIG_EXAMPLE_IPV6 //// xTaskCreate(tcp_server_task, tcp_server, 4096, (void*)AF_INET6, 5, NULL); ////#endif // //#ifdef CONFIG_EXAMPLE_IPV4 // xTaskCreate(udp_server_task, udp_server, 4096, (void*)AF_INET, UDP_SERVER_TASK_PRIORITY, NULL); //#endif ////#ifdef CONFIG_EXAMPLE_IPV6 //// xTaskCreate(udp_server_task, udp_server, 4096, (void*)AF_INET6, 5, NULL); ////#endif // xTaskCreate(tcp_udp_client_connect_task, tcp_udp_client_connect_task, 4096, NULL, TCP_CLIENT_TASK_PRIORITY, NULL); xTaskCreate(misc_task_demonstrate, misc_task_demonstrate, 4096, NULL, MISC_TASK_PRIORITY, NULL); xTaskCreate(adc_sample_task, adc_sample_task, 4096, NULL, ADC_SAMPLE_TASK_PRIORITY, NULL); xTaskCreate(uart1_event_task, uart1_event_task, 4096, NULL, UART1_EVENT_TASK_PRIORITY, NULL); }