1. 烧录问题

1.1 permission denied

在环境搭建好之后,编译出工程 bin 文件,下一步便是烧录到开发板了
将开发板通过USB连接到虚拟机
ls /dev/tty* 看到有 /dev/ttyUSB0 即连接成功

但是在 idf.py -p /dev/ttyUSB0 flash 时却出错了

esp32S3移植lvgl esp32 v3_单片机


通过命令 ls -lh /dev/ttyUSB0

esp32S3移植lvgl esp32 v3_单片机_02


可知此时权限为 660

寻找解决方法后:
sudo chmod 777 /dev/ttyUSB0

再次执行
idf.py -p /dev/ttyUSB0 flash 成功

但是这种设置在重启后又得重新设置,

于是执行
sudo usermod -aG dialout usrname ,注销后重新登陆即可。
( 1. dialout 是串口设备所在的组
2. usrname为你想要使用 /dev/ttyUSB0 的用户名,可以使用 whoami 查看)

执行 sudo usermod -aG dialout usrname 前:

esp32S3移植lvgl esp32 v3_数据_03


执行 sudo usermod -aG dialout usrname 后:

esp32S3移植lvgl esp32 v3_单片机_04

1.2 flash 报错 MD5

(1)
执行语句:esptool.py --port /dev/ttyUSB0 write_flash_status --non-volatile 0
再次flash解决
(2)
又一次遇到了相同的问题,使用方法(1)无法解决,
最终发现是买的flash大小不合适,更换flash解决
(note:想要4MBflash,淘宝直接搜索4Mflash,搜到的都是4Mb(512kB)的,)

1.3 flash 报错 timed out

esp32S3移植lvgl esp32 v3_esp32S3移植lvgl_05


虽然烧录不进,但是通过espefuse.py summary查看芯片信息正常

解决:后重新焊接了一次串口线和flash,问题解决,猜测应该是flash没焊接好.

2. 编译找不到头文件

2.1 头文件在 esp-idf/components/ 目录下

esp32S3移植lvgl esp32 v3_esp32S3移植lvgl_06


根据日志可知 nvs_flash.h 存在问题

在 esp-idf 文件夹下执行 :

find ./ -name nvs_flash.h

esp32S3移植lvgl esp32 v3_初始化_07


可知该文件位置 :components/nvs_flash于是在 project_dir(项目目录)/main/ 下CMakeLists.txt文件中添加此文件路径

esp32S3移植lvgl esp32 v3_esp32S3移植lvgl_08

2.2 头文件在 esp-idf/examples/ 目录下 (未解决)

esp32S3移植lvgl esp32 v3_初始化_09


根据日志可知 protocol_examples_common.h 存在问题

在 esp-idf 文件夹下执行 :

find ./ -name protocol_examples_common.h

esp32S3移植lvgl esp32 v3_数据_10


可知该文件位置 :examples/common_components/protocol…于是打算搜索其他使用过该头文件的例程看配置:

esp32S3移植lvgl esp32 v3_数据_11


找到 tcp_server 例程使用到了该头文件

并且尝试编译了 tcp_server例程发现编译成功,于是查找该例程配置:

esp32S3移植lvgl esp32 v3_串口_12


打开该CMakeLists.txt文件:

esp32S3移植lvgl esp32 v3_串口_13


发现此处正好有protocol_examples_common.h对应的路径,于是把该部分添加到了自己项目中对应的位置

esp32S3移植lvgl esp32 v3_单片机_14

再查看其他文件,发现并没有其他特别的地方

于是再次编译,结果发现还是报相同的错误

esp32S3移植lvgl esp32 v3_串口_15


于是我很懵逼,不知道为什么例程不会报错,我编译就会报错。。。

后了解到该组件目录(examples/common_components/protocol_examples_common)
是为了简化例程代码才具有的,并不适合用于正式工程
于是就把该头文件注释掉了,再次编译发现编译通过了
( 发现自己的工程中以前使用到该头文件内容的代码早被注释掉,没有使用了,只是头文件没删掉,因此现在把头文件也去掉。
不过相同的代码之前在release_v4.3版本编译没事,这次把整个项目文件移植到stable_v4.4就出现这个问题,也没搞清楚怎么回事,只能在此稍做记录一下)

3. 移植openssl 一些文件到components/openssl目录

在项目中编译报错:

esp32S3移植lvgl esp32 v3_esp32S3移植lvgl_16


解决 : 找到报错地方 注释掉

4. 串口使用时的一些问题

在项目中,需要使用到UART0来与MCU进行通信,配置好UART0后,发现通信过程中数据与自己代码传输的有些出入,TX发送了很多无关的数据,后来发现log等输出都是默认输出到UART0的,在查找相关资料后找到3个可以改动的地方如下:

  1. TOP /Bootloader config /Bootloader log verbosity
  2. TOP /Component config /Common ESP-related /channel for console output
  3. TOP /Component config /Log output /Dafault log verbosity

我将上述三处地方都改动后再次用串口查看TX数据,发现数据正常了
此时

  1. NO OUTPUT
  2. NONE
  3. NO OUTPUT

那么具体每个选项造成的影响呢?经过测试如下
4.1

  1. INFO
  2. NONE
  3. NO OUTPUT
    测试发现数据正常,所以无用数据应该不是该处影响

4.2

  1. INFO
  2. NONE
  3. INFO

esp32S3移植lvgl esp32 v3_串口_17

测试发现数据正常,所以无用数据应该不是该处影响

4.3

  1. INFO
  2. UART0
  3. INFO

此时发现uart0 可以看到日志打印,但由于配置了UART0用于通信,导致日志停止如下

esp32S3移植lvgl esp32 v3_esp32S3移植lvgl_18


查看串口数据:

esp32S3移植lvgl esp32 v3_单片机_19


在发送所需数据时前面多了很多其他数据,且在通信时TX不应发送数据时也会不断弹出大量数据

4.3

  1. INFO
  2. UART1
  3. INFO

    自定义UART1,将输出传入UART1
    发现现象与4.3相同,查看UART1输出,发现无输出

经仔细检查后发现,sdkconfig中CONFIG_CONSOLE_UART_NUM为0,所以日志依旧输出向串口0
手动改动sdkconfig CONFIG_CONSOLE_UART_NUM = 1后,再次编译又会变回0,于是找到menucinfig 定义文件添加上对串口号的选择项使我们在menuconfig中可以选择自定义串口号来改变CONFIG_CONSOLE_UART_NUM(文件位置:esp-idf/components/esp_common/Kconfig)

成功后 CONFIG_CONSOLE_UART_NUM变为1,在代码中对串口1初始化后,发现日志可以正常输出向串口1了,且串口0通信正常;之后尝试在代码中关闭了串口1初始化后,发现不能输出日志了。

note:需要有日志打印,TOP /Component config /Log output 处不能关闭

5. 使用esp-mqtt时动态设置uri

5.1 初始测试使用静态uri:(uri改变需要改代码)
		esp_mqtt_client_config_t     mqtt_cfg = { .uri = "xxxxxx"};
		esp_mqtt_client_handle_t    client = esp_mqtt_client_init(&mqtt_cfg);
		esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
 		esp_mqtt_client_start(client);
 		成功初始化,没有问题,后想使用接收到的指定uri "yyyyyy"

5.2 使用动态uri:(uri改变不需要改代码,健壮性更好)
		char mqtt_url[64] = {0};
		get_info_from_nvs(mqtt_url);	//将nvs中的uri放入mqtt_uri
		esp_mqtt_client_config_t     mqtt_cfg ;		
		mqtt_cfg.uri = mqtt_url;
		esp_mqtt_client_handle_t    client = esp_mqtt_client_init(&mqtt_cfg);
		esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
 	  esp_mqtt_client_start(client);
	
	运行至 esp_mqtt_client_init(&mqtt_cfg)
	报错如下:

esp32S3移植lvgl esp32 v3_单片机_20

进行修改: 
	esp_mqtt_client_config_t   mqtt_cfg ;
	改为-> 
	esp_mqtt_client_config_t  mqtt_cfg = {.uri = NULL,};   
	或者  esp_mqtt_client_config_t  mqtt_cfg = {0};

修改后运行正常

使用 esp_mqtt_client_set_uri()也可以
		char mqtt_url[64] = {0};
		get_info_from_nvs(mqtt_url);	//将nvs中的uri放入mqtt_uri
		esp_mqtt_client_config_t  mqtt_cfg = {.uri = NULL,}; 		
		esp_mqtt_client_handle_t    client = esp_mqtt_client_init(&mqtt_cfg);
		esp_mqtt_client_set_uri(client,mqtt_url);
		esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
 	    esp_mqtt_client_start(client);

note: 不能写为:esp_mqtt_client_config_t mqtt_cfg ;

6. sta模式转ap模式

正常sta模式配置:

void Wifi_init_sta(void)
	{
		//创建一个新的事件组
	    s_wifi_event_group = xEventGroupCreate();

		//初始化tcp/ip协议栈(LwIP)
	    ESP_ERROR_CHECK(esp_netif_init());

		//创建默认事件循环(初始化wifi事件处理)
	    ESP_ERROR_CHECK(esp_event_loop_create_default());

		//创建有TCP/IP堆栈的默认网络接口实例绑定station 
	    sta_netif = esp_netif_create_default_wifi_sta();

		//初始化wifi
	    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配置
	    wifi_config_t wifi_config = {
	        .sta = {
	          //  .ssid = sta_addr,					
	          //  .password = sta_password,					
	            /* Setting a password implies station will connect to all security modes including WEP/WPA.
	             * However these modes are deprecated and not advisable to be used. Incase your Access point
	             * doesn't support WPA2, these mode can be enabled by commenting below line */
		     	.threshold.authmode = WIFI_AUTH_WPA2_PSK,
	
	            .pmf_cfg = {
	                .capable = true,
	                .required = false
	            },
	        },
	    };
		strcpy((char *)wifi_config.sta.ssid,ssid);
		strcpy((char *)wifi_config.sta.password,password);
	
	    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
	    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );

		//启动wifi
	    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,
	            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 & CONNECTED_BIT) {
	        ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
	                 ssid, password);
	    } else if (bits & WIFI_FAIL_BIT) {
	        ESP_LOGE(TAG, "Failed to connect to SSID:%s, password:%s",
	                 ssid, password);
	    } else {
	        ESP_LOGE(TAG, "UNEXPECTED EVENT");
	    }

	    /* The event will not be processed after unregister */
	    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
	    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
	    vEventGroupDelete(s_wifi_event_group);
}

正常ap模式配置:

void Wifi_init_sta(void)
	{
		uint8_t ApMac[6] = {0};
	    ESP_ERROR_CHECK(esp_netif_init());		//初始化tcp/ip协议栈(LwIP)
	    ESP_ERROR_CHECK(esp_event_loop_create_default());	//创建默认事件循环(初始化wifi事件处理)
	    esp_netif_create_default_wifi_ap();	 创建具有TCP / IP堆栈的默认网络接口实例绑定AP
	
		//初始化wifi
	    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
	    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
	
	    
		//将事件处理程序注册到系统事件循环(wifi事件族)
	    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
	                                                        ESP_EVENT_ANY_ID,
	                                                        &wifi_event_handler,
	                                                        NULL,
	                                                        NULL));
	     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
	     esp_wifi_get_mac( ESP_IF_WIFI_AP , ApMac );//获取DHCP分配的IP接口的mac

		//wifi配置
	    wifi_config_t wifi_config = {
	        .ap = {
	            //.ssid = AP_ESP_WIFI_SSID,
	            //.ssid_len = strlen(AP_ESP_WIFI_SSID)+5,
	            .channel = AP_ESP_WIFI_CHANNEL,
	            .password = AP_ESP_WIFI_PASS,
	            .max_connection = AP_MAX_STA_CONN,
	            //.authmode = WIFI_AUTH_WPA_WPA2_PSK
	            .authmode = WIFI_AUTH_OPEN                 //wifi安全类型
	        },
	    };
	
	    sprintf((char *)wifi_config.ap.ssid,"%s_%02X%02X",AP_ESP_WIFI_SSID,ApMac[4],ApMac[5]);
	    
	    if (strlen(AP_ESP_WIFI_PASS) == 0) 
	    {
	        wifi_config.ap.authmode = WIFI_AUTH_OPEN;
	    }
	
	    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));

		//启动wifi
	    ESP_ERROR_CHECK(esp_wifi_start());
	    
	    ESP_LOGI(TAG, "wifi_init_softap finished.  SSID:%s  password:%s  channel:%d",
	             wifi_config.ap.ssid, AP_ESP_WIFI_PASS, AP_ESP_WIFI_CHANNEL);
}

在sta模式时想要切换为ap模式而不重启:

  1. 首先将sta的一些wifi配置取消掉
    esp_wifi_disconnect();
    esp_wifi_stop();
    esp_wifi_deinit();
    //s_wifi_event_group = NULL;
  2. 按照 ap 模式进行配置
  3. 发现运行在 ESP_ERROR_CHECK(esp_event_loop_create_default()); 时报错重启
  4. 于是将ap配置的 ESP_ERROR_CHECK(esp_event_loop_create_default()) 删除,发现成功开启ap模式

note: 刚开始配置sta时也调用了esp_event_loop_create_default(),
可能
esp_wifi_disconnect();
esp_wifi_stop();
esp_wifi_deinit();
并不会取消esp_event_loop_create_default()操作,于是再次配置ap时又调用esp_event_loop_create_default()导致报错

7. 代码烧录后无法正常启动

7.1 出各种错重启,0xf,0x7,0x3等,烧录时有时也报错无法正常进行

esp32S3移植lvgl esp32 v3_单片机_21

esp32S3移植lvgl esp32 v3_数据_22

esp32S3移植lvgl esp32 v3_初始化_23

esp32S3移植lvgl esp32 v3_数据_24


经查,连接芯片的gnd引脚很多金属丝松动,只连上少许,使用新的导线重连gnd,问题解决7.2 模组本来正常,在测试过程中出了问题,monitor也看不到日志了,于是重新烧录并查看日志,烧录成功后,monitor 发现找不到分区表一直重启

esp32S3移植lvgl esp32 v3_数据_25


不知道是什么原因导致的,该怎么解决,可能是模组被玩坏了吧,只能换个模组了

esp32S3移植lvgl esp32 v3_初始化_26


esp32S3移植lvgl esp32 v3_单片机_27

esp32S3移植lvgl esp32 v3_单片机_28


发现模组出了问题后,每次烧录后日志也有些区别,但是应用程序都跑不起来

(这次出问题时,在模组串口与MCU通信时,额外加了个串口线连接电脑查看通信内容,可能是TX也接上了导致芯片烧了)

7.3 烧录成功后,报错重启(SPI_FAST_FLASH_BOOT)

esp32S3移植lvgl esp32 v3_数据_29


该flash: 25L3206e(4MB) ,换成华邦 W25Q32BVSIG(4MB)

8. 软件中获取设备启动方式

芯片控制继电器工作,当上电时继电器总会吸合,想让芯片启动时判断是否为上电启动,上电启动的话软件控制继电器断开,其他启动方式不做处理

esp32S3移植lvgl esp32 v3_初始化_30


根据重启日志进行查询

grep -nr POWERON …/esp-idf/

esp32S3移植lvgl esp32 v3_esp32S3移植lvgl_31


再次查询

grep -nr POWERON_RESET …/esp-idf/

。。。经过不断查找结果如下

  1. 添加头文件 #include “esp32c3/rom/rtc.h”
  2. 软件获取启动方式:
    RESET_REASON reason = rtc_get_reset_reason(0);
    结果如下:

    当reason == 1时可知是上电启动