项目描述及需要实现的功能
本次活动给出的可选任务如下:
任务一: 利用扩展接口,自由选择连接三到五个传感器,并将采集的数据显示在LCD屏幕上,并解释数据的含义。
任务二: 制作一个自动联网的天气预报仪,在设计界面显示温湿度、天气情况、空气质量以及未来三天内的天气变化。
任务三: 使用麦克风采集使用者说话口型并识别,同时在屏幕上画出对应的表情。
活动期间,本人对任务二进行了实现,使用Wio Terminal构建了能够自动联网的天气预报仪。支持通过网络查询指定地点的天气信息、温湿度信息和空气质量并展示,同时能够通过该设备查看未来的天气变化,最终效果如下图所示:
设计方案
本应用设计思路较为清晰,主要有以下三个主要步骤:
-
设备联网
-
从云端获取数据
-
处理数据并进行展示
Wio Terminal具有丰富的板载资源,自带彩色显示屏和WiFi模块,单凭一个开发平台便能完成全部任务,不需要搭配额外硬件模块。得益于arduino生态和seeed官方的软件支持,可以在Arduino平台上找到绝大部分可以完成上述任务的第三方库,加快了整体开发流程。本项目使用的第三方库有:
-
rpcWifi,提供联网支持
-
ArduinoJson,用于对云端数据进行解析
-
seeed官方构建的LVGL库,用于图形界面展示数据
目前网上已有多个平台提供天气API接口,本项目中选择的平台是心知天气,选用其他平台同样可完成本项目。用户需要注册平台账号,获取访问API接口所需的认证信息,接下来便可查阅API文档设计自己的请求地址。
实现要点
在访问网络之前,需要更新Wio Terminal的无线核心固件,确保能够执行最新版本的代码,官方文档中有详细做法Overview - Seeed Wiki (seeedstudio.com),具体联网代码为:
WiFi.mode(WIFI_STA);
WiFi.disconnect();
Serial.println("Connecting to WiFi..");
WiFi.begin(ssid, password);
API请求地址设计和数据处理都相对简单,如果有网络开发基础的话能够快速上手,接下来简单介绍一下LVGL相关内容。LVGL在工作时,需要创建缓存区用于刷新LVGL图形数据,并且启动相对底层的屏幕刷新函数。为满足显示要求,本项目中设计了两个界面用于显示数据。默认情况下,LVGL需要手动编写代码,指明每个界面元素所处位置等元素信息,实现起来相对繁琐。但最近LVGL官方提供了EdgeLine工具,可以直接拖动组件进行界面设计,能够有效提高开发效率。需要注意的是,该工具仍处于测试阶段,软件的响应速度较慢。另外,较大的字体需要在lvgl_conf.h
中手动开启支持,在设计时需要注意。
由软件自动生成的部分界面代码为:
Screen1 = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_size(Screen1, LV_HOR_RES, LV_VER_RES);
Object1 = lv_obj_create(Screen1, NULL);
lv_obj_set_click(Object1, false);
lv_obj_set_hidden(Object1, false);
lv_obj_clear_state(Object1, LV_STATE_DISABLED);
lv_obj_set_size(Object1, 122, 165); // force: 14
lv_obj_align(Object1, Screen1, LV_ALIGN_IN_TOP_LEFT, 14, 60); // force: 122
lv_obj_set_drag(Object1, false);
lv_obj_set_style_local_bg_color(
Object1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
lv_color_hex(37 * 256 * 256 + 135 * 256 + 236));
lv_obj_set_style_local_bg_opa(Object1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
255);
lv_obj_set_style_local_bg_grad_dir(Object1, LV_BTN_PART_MAIN,
LV_STATE_DEFAULT, LV_GRAD_DIR_VER);
Object2 = lv_obj_create(Screen1, NULL);
lv_obj_set_click(Object2, false);
lv_obj_set_hidden(Object2, false);
lv_obj_clear_state(Object2, LV_STATE_DISABLED);
lv_obj_set_size(Object2, 151, 165); // force: 70
lv_obj_align(Object2, Screen1, LV_ALIGN_CENTER, 70, 23); // force: 151
lv_obj_set_drag(Object2, false);
lv_obj_set_style_local_bg_color(
Object2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
lv_color_hex(37 * 256 * 256 + 135 * 256 + 236));
lv_obj_set_style_local_bg_opa(Object2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
255);
lv_obj_set_style_local_bg_grad_dir(Object2, LV_BTN_PART_MAIN,
LV_STATE_DEFAULT, LV_GRAD_DIR_VER);
title = lv_label_create(Screen1, NULL);
lv_label_set_long_mode(title, LV_LABEL_LONG_EXPAND);
lv_label_set_align(title, LV_LABEL_ALIGN_CENTER);
lv_label_set_text(title, "Wio Weather Reporter");
lv_obj_set_size(title, 250, 24); // force: 38
lv_obj_set_click(title, false);
lv_obj_set_hidden(title, false);
lv_obj_clear_state(title, LV_STATE_DISABLED);
lv_obj_set_drag(title, false);
lv_obj_set_style_local_text_font(title, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
&lv_font_montserrat_22);
lv_obj_align(title, Screen1, LV_ALIGN_IN_TOP_LEFT, 38, 21); // force: 250
为了达到切换两个界面的目的,在程序循环中增加了按键检测代码,如果按键被按下则调整上层界面的隐藏属性。
if (digitalRead(WIO_KEY_A) == LOW) {
Serial.println("A Key pressed");
if (flag == 1) {
lv_obj_set_hidden(screen, true);
flag = 0;
} else {
lv_obj_set_hidden(screen, false);
flag = 1;
}
}
总结体会
-
感谢Funpack活动提供的学习机会
-
Wio Terminal的开发真的很便捷
-
初次上手LVGL,界面做的不是很好,今后可以多多了解,做出更棒的界面
参考:
lvgl学习之屏幕与刷新hebao0的博客-CSDN博客lvgl 局部刷新
Get Started with Wio Terminal - Seeed Wiki (seeedstudio.com)