MicroPython[ESP32]:使用lvgl设置温度仪表盘动画

NO.1
使用场景

温湿度显示

左侧的是小米温湿度器(成本30元)

右侧的是DIY的温度仪表盘(成本50元左右)

此图片的alt属性为空;文件名为image-761-1024x764.png

NO.2
文档汇总

官方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代码和效果(忽略横屏竖屏)

NO.3
问题汇总

官方的代码放到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))

此图片的alt属性为空;文件名为image-762-1024x554.png

参考网上的答案,做了以下修改

新建一个sacle主体对象,放到函数的第一个参数,其他不变

scale = meter.add_scale()
meter.set_scale_ticks(scale,40, 2, 10, lv.palette_main(lv.PALETTE.GREY))

可能是lvgl版本不同,也可能是别的原因

NO.4
步骤拆解

在模拟器中

公共方法

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)

此图片的alt属性为空;文件名为image-763.png

外圆设置

  1. 设置一个270度的圆

  2. 从下午3点刻度方向旋转135度

  3. 刻度范围设置为0-40

meter.set_scale_range ( 0 , 40 ,270,135 )

此图片的alt属性为空;文件名为image-764.png

设置刻度线

  1. 设置40个小刻度

  2. 设置刻度线宽2,长10

  3. 设置刻度线颜色为灰色

meter.set_scale_ticks(40, 2, 10, lv.palette_main(lv.PALETTE.GREY))

此图片的alt属性为空;文件名为image-765.png

设置分段线

  1. 设置分段线每5个小刻度为一个节点

  2. 设置分段线宽4,长15

  3. 设置分段线颜色为黑色

  4. 设置分段线与外圆刻盘的距离为10

此图片的alt属性为空;文件名为image-766.png

实例化一个指针

没什么样式效果,但是要放在代码里

indic = lv.meter_indicator_t()

设置刻度区间样式

在这里我设计的温度范围为0-40度

有以下几个区间

  1. 设置0-20摄氏度为低温的环境,颜色为蓝色

  2. 设置20-26摄氏度为舒适的环境,颜色为绿色

  3. 设置26-32摄氏度为炎热的环境,颜色为黄色

  4. 设置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)

此图片的alt属性为空;文件名为image-767.png

设置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)

此图片的alt属性为空;文件名为image-768.png

可以看到低温区域的边框和刻度线都是蓝色的了

其他的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)

最终效果

此图片的alt属性为空;文件名为image-769.png

添加指针

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)

NO.5
实时动画

以上内容是在浏览器网页模拟器实现的效果

实际的温度仪表盘应该显示当前温度,并且随着温度变化而动画到指定刻度

这里设置了以下实物效果

  1. 初始仪表盘动画为0-40度,动画时长2秒

  2. 3秒后,指针从40度(上一次结束位置),移动到20度,动画时长2秒

  3. 3秒后,指针从20度(上一次结束位置),移动到30度,动画时长2秒

可以看到动画是连续,当温度有变化时,指针总会从上次结束位置(之前的温度)移动到指定的位置(当前温度)

每次移动只需要重新执行一次动画,并且设置正确的刻度值即可

0为动画的起始值,40为动画结束值,每次动画自定义对应值

a.set_values(0, 40)
NO.6
Tips

温度数据请自行从温度传感器中获取,ESP32获取数字信号值

本文为温度仪表盘的第一版,完成了

  1. 温度最小最大区间和刻度设置

  2. 完成了区间和刻度样式区别

  3. 完成指针动画

后续可以优化的地方

  1. 添加标题文字,描述当前仪表盘的数值为温度

  2. 设置其他温度小部件,如折线图表,柱状温度等其他表盘形式

  3. 设置数字颜色,设置颜色渐变,长宽圆大小和粗细等样式调整

  4. 优化动画效果

  5. 和其他数据一同显示,比如湿度,时间等等等

END