得捷电子 Follow me 第2期任务提交汇总
[复制链接]
大家好,10月份收到了这块板子,但是直到最近才有空把它拿出来摆弄摆弄。 论坛的朋友们大都使用了CircuitPython完成这块Adafruit ESP32-S3 TFT FeatherCircuitPython的任务,但是笔者平时习惯了用C/C++来写代码, 所以还是挑选了esp-idf+lvgl的方案, 虽然的确也遇到了一些问题,但是作为第一次写esp32来说,我觉得还是比较容易上手的。
因为使用的esp-idf的方案, 首先需要配置环境, 我使用的是Mac+VSCode+esp-idf插件的方式配置的, 总体来说还是非常顺利的。按照官方的教程直接操作就好了。具体过程可以参考官方教程: https://docs.espressif.com/projects/esp-idf/zh_CN/v5.1/esp32s3/get-started/index.html#get-started-how-to-get-esp-idf
工程创建好之后首先要解决的是屏幕显示的问题,最终我使用了github上 的代码成功点亮屏幕。
任务一、控制屏幕显示中文(必做任务)
首先为了能够显示中文, 我们需要把我们的中文字库转换, 转换使用的lvgl提供的工具: https://lvgl.io/tools/fontconverter,其中range范围参考https://jrgraphix.net/research/unicode.php
从这里我们能够获取到转换好的字库的C数组
声明字体库
LV_FONT_DECLARE(font_OPPOSans_L_16);
static const lv_font_t *main_font = &font_OPPOSans_L_16;
// 使用字体库并创建要显示的标签
lv_obj_t *lab_task = lv_label_create(parent);
lv_obj_set_style_text_font(lab_task, main_font, LV_PART_MAIN);
lv_label_set_text_fmt(lab_task, "得捷电子Follow me第2期 | 任务1-完成屏幕的控制,并且能显示中文");
lv_obj_set_width(lab_task, lv_obj_get_width(lv_obj_get_parent(parent)));
lv_label_set_long_mode(lab_task, LV_LABEL_LONG_SCROLL_CIRCULAR);
lv_obj_align(lab_task, LV_ALIGN_BOTTOM_MID, 0, 0);
任务2:网络功能使用(必做任务)
完成网络功能的使用,能够创建热点和连接到WiFi
// 配置热点的参数,设置热点的类型等。。。。
wifi_config_t wifi_config = {
.ap = {
.ssid = FOLLOME2_ESP_WIFI_SSID,
.ssid_len = strlen(FOLLOME2_ESP_WIFI_SSID),
.channel = FOLLOME2_ESP_WIFI_CHANNEL,
.password = FOLLOME2_ESP_WIFI_PASS,
.max_connection = FOLLOME2_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA2_PSK,
.pmf_cfg = {
.required = true,
},
},
};
//
netif = esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
netif = esp_netif_create_default_wifi_ap();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
esp_netif_ip_info_t ip_info;
esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"), &ip_info);
char ip_addr[16];
inet_ntoa_r(ip_info.ip.addr, ip_addr, 16);
任务3:控制WS2812B(必做任务)
使用按键控制板载Neopixel LED的显示和颜色切换
配置WS2812B
#define NEOPIX_GPIO GPIO_NUM_33
#define NEOPIX_PWR_GPIO GPIO_NUM_34
gpio_config_t io_conf = {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1ULL<<NEOPIX_PWR_GPIO),
.intr_type = GPIO_INTR_DISABLE,
.pull_down_en = 0,
.pull_up_en = 0,
};
err = gpio_config(&io_conf);
if (err != ESP_OK) {
ESP_LOGE(TAG, "configure GPIO for NEOPIX_PWR failed");
}
// 设置LED电源的GPIO引脚的电平为高电平(1)
err = gpio_set_level(NEOPIX_PWR_GPIO, 1);
// 配置LED灯带
led_strip_config_t strip_config = {
.strip_gpio_num = NEOPIX_GPIO, // LED数据线的GPIO引脚。
.max_leds = 1, // LED灯带上LED的数量,这里设置为1。
.led_pixel_format = LED_PIXEL_FORMAT_GRB, // LED的像素格式为GRB。
.led_model = LED_MODEL_WS2812, // LED灯带的型号。
.flags.invert_out = false, // 输出信号是否翻转,这里设置为不翻转。
};
// 配置RMT(Remote Control)控制器。
led_strip_rmt_config_t rmt_config = {
.clk_src = RMT_CLK_SRC_DEFAULT, // 时钟源设置为默认值。
.resolution_hz = 10 * 1000 * 1000, // RMT的分辨率为10MHz。
.flags.with_dma = false, // whether to enable the DMA feature
};
// 初始化LED灯带设备,并将配置参数传递给它。
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
设置LED灯带上的第0个像素的颜色,并刷新LED灯带
led_strip_set_pixel(led_strip, 0, r, g, b);
led_strip_refresh(led_strip);
任务4:从下方5个分任务中选择1个感兴趣的完成即可(必做任务)
■ 分任务1:日历&时钟——完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息
建议搭配器件:Adafruit ESP32-S3 TFT Feather
配置网络接入点,把网络切换成WIFI_MODE_STA模式,
配置sntp同步时间
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
esp_sntp_setservername(0, "ntp.aliyun.com");
esp_sntp_setservername(1, "time.asia.apple.com");
esp_sntp_setservername(2, "pool.ntp.org");
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
esp_sntp_init();
天气从http://d1.weather.com.cn/weather_index/{city code}.html获取,需要添加referer
类似curl http://d1.weather.com.cn/weather_index/101020100.html -e http://www.weather.com.cn/
// 配置请求
char *response = calloc(8192, sizeof(char));
esp_http_client_config_t config = {
.url = WEATHER_URL,
.event_handler = _http_event_handler,
.crt_bundle_attach = esp_crt_bundle_attach,
.buffer_size = 8192 * sizeof(char),
.user_data = response,
.user_agent = USER_AGENT
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_header(client, "Referer", WEATHER_REFERER);
esp_err_t err = esp_http_client_perform(client);
// 获取请求返回内容
int64_t len = esp_http_client_get_content_length(client);
ESP_LOGI(TAG, "HTTPS Status = %d, content_length = %"PRId64,
esp_http_client_get_status_code(client),
len
);
response[len] = '\0';
ESP_LOGI(TAG, "Response: %s", response);
esp_http_client_cleanup(client);
// 解析请求转json
char *json = NULL;
jparse_ctx_t *jctx = NULL;
char* pStart = strstr(response, "var dataSK =");
pStart += 12;
char* pEnd = strstr(pStart, "};");
pEnd += 1;
int len = pEnd - pStart;
json = malloc(len + 1);
memcpy(json, pStart, len);
json[len] = '\0';
free(response);
response = NULL;
jctx = (jparse_ctx_t *)malloc(sizeof(jparse_ctx_t));
int ret = json_parse_start(jctx, json, strlen(json));
if (ret != OS_SUCCESS) {
ESP_LOGE(TAG, "json_parse_start failed\n");
goto exception;
}
视频: https://training.eeworld.com.cn/video/38432
代码包: https://download.eeworld.com.cn/detail/jakeli/629880
|