温湿度显示
左侧的是小米温湿度器(成本30元)
右侧的是DIY的温度仪表盘(成本50元左右)
官方DEMO
https://docs.lvgl.io/master/examples.html#simple-meter
仪表盘文档地址
https://docs.lvgl.io/master/API/widgets/meter/lv_meter.html#_CPPv424lv_meter_set_scale_ticksP8lv_obj_t8uint16_t8uint16_t8uint16_t10lv_color_t
复刻DEMO代码和效果(忽略横屏竖屏)
官方的代码放到ESP32中,会出现报错
提示参数少了
Double buffer
ILI9341 initialization completed
Traceback (most recent call last):
File "<stdin>", line 37, in <module>
TypeError: function takes 6 positional arguments but 5 were given
描述set_scale_ticks这个函数应该有6个参数,但是只给了5个
meter.set_scale_ticks(41, 2, 10, lv.palette_main(lv.PALETTE.GREY))
参考网上的答案,做了以下修改
新建一个sacle主体对象,放到函数的第一个参数,其他不变
scale = meter.add_scale()
meter.set_scale_ticks(scale,40, 2, 10, lv.palette_main(lv.PALETTE.GREY))
可能是lvgl版本不同,也可能是别的原因
在模拟器中
公共方法
import utime as time
def set_value(indic, v):
meter.set_indicator_value(indic, v)
实例化一个仪表盘(小部件)
设置尺寸为200×200,并且设置样式居中显示
meter = lv.meter(lv.scr_act())
meter.center()
meter.set_size(200, 200)
外圆设置
-
设置一个270度的圆
-
从下午3点刻度方向旋转135度
-
刻度范围设置为0-40
meter.set_scale_range ( 0 , 40 ,270,135 )
设置刻度线
-
设置40个小刻度
-
设置刻度线宽2,长10
-
设置刻度线颜色为灰色
meter.set_scale_ticks(40, 2, 10, lv.palette_main(lv.PALETTE.GREY))
设置分段线
-
设置分段线每5个小刻度为一个节点
-
设置分段线宽4,长15
-
设置分段线颜色为黑色
-
设置分段线与外圆刻盘的距离为10
实例化一个指针
没什么样式效果,但是要放在代码里
indic = lv.meter_indicator_t()
设置刻度区间样式
在这里我设计的温度范围为0-40度
有以下几个区间
-
设置0-20摄氏度为低温的环境,颜色为蓝色
-
设置20-26摄氏度为舒适的环境,颜色为绿色
-
设置26-32摄氏度为炎热的环境,颜色为黄色
-
设置32-40摄氏度为高温的环境,颜色为红色
设置0-20外圆边框颜色和区域
indic = meter.add_arc(3, lv.palette_main(lv.PALETTE.BLUE), 0)
meter.set_indicator_start_value(indic, 0)
meter.set_indicator_end_value(indic, 20)
设置0-20刻度颜色和长宽
indic = meter.add_scale_lines(lv.palette_main(lv.PALETTE.BLUE), lv.palette_main(lv.PALETTE.BLUE), False, 0)
meter.set_indicator_start_value(indic, 0)
meter.set_indicator_end_value(indic, 20)
可以看到低温区域的边框和刻度线都是蓝色的了
其他的3个区域参考上述,修改区间值和颜色值即可
indic = meter.add_arc(3, lv.palette_main(lv.PALETTE.GREEN), 0)
meter.set_indicator_start_value(indic, 20)
meter.set_indicator_end_value(indic, 26)
indic = meter.add_scale_lines(lv.palette_main(lv.PALETTE.GREEN), lv.palette_main(lv.PALETTE.GREEN), False, 0)
meter.set_indicator_start_value(indic, 20)
meter.set_indicator_end_value(indic, 26)
indic = meter.add_arc(3, lv.palette_main(lv.PALETTE.YELLOW), 0)
meter.set_indicator_start_value(indic, 26)
meter.set_indicator_end_value(indic, 32)
indic = meter.add_scale_lines(lv.palette_main(lv.PALETTE.YELLOW), lv.palette_main(lv.PALETTE.YELLOW), False, 0)
meter.set_indicator_start_value(indic, 26)
meter.set_indicator_end_value(indic, 32)
indic = meter.add_arc(3, lv.palette_main(lv.PALETTE.ORANGE), 0)
meter.set_indicator_start_value(indic, 32)
meter.set_indicator_end_value(indic, 40)
indic = meter.add_scale_lines(lv.palette_main(lv.PALETTE.RED), lv.palette_main(lv.PALETTE.RED), False, 0)
meter.set_indicator_start_value(indic, 32)
meter.set_indicator_end_value(indic, 40)
最终效果
添加指针
indic = meter.add_needle_line(scale,4, lv.palette_main(lv.PALETTE.GREY), -10)
设置动画
设置指针从0向40刻度滑动
注释的代码表示动画效果不重复,只执行一次
a = lv.anim_t()
a.init()
a.set_var(indic)
a.set_values(0, 40)
a.set_time(2000)
# a.set_repeat_delay(100)
# a.set_playback_time(500)
# a.set_playback_delay(100)
# a.set_repeat_count(lv.ANIM_REPEAT_INFINITE)
a.set_repeat_count(1)
a.set_custom_exec_cb(lambda a,val: set_value(indic,val))
lv.anim_t.start(a)
以上内容是在浏览器网页模拟器实现的效果
实际的温度仪表盘应该显示当前温度,并且随着温度变化而动画到指定刻度
这里设置了以下实物效果
-
初始仪表盘动画为0-40度,动画时长2秒
-
3秒后,指针从40度(上一次结束位置),移动到20度,动画时长2秒
-
3秒后,指针从20度(上一次结束位置),移动到30度,动画时长2秒
可以看到动画是连续,当温度有变化时,指针总会从上次结束位置(之前的温度)移动到指定的位置(当前温度)
每次移动只需要重新执行一次动画,并且设置正确的刻度值即可
0为动画的起始值,40为动画结束值,每次动画自定义对应值
a.set_values(0, 40)
温度数据请自行从温度传感器中获取,ESP32获取数字信号值
本文为温度仪表盘的第一版,完成了
-
温度最小最大区间和刻度设置
-
完成了区间和刻度样式区别
-
完成指针动画
后续可以优化的地方
-
添加标题文字,描述当前仪表盘的数值为温度
-
设置其他温度小部件,如折线图表,柱状温度等其他表盘形式
-
设置数字颜色,设置颜色渐变,长宽圆大小和粗细等样式调整
-
优化动画效果
-
和其他数据一同显示,比如湿度,时间等等等
END