多功能

例程

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import lvgl as lv
import lvgl_helper as lv_h
import touchscreen as ts
import lcd
import time

lcd.init()
ts.init()
lv.init()

disp_buf1 = lv.disp_buf_t()
buf1_1 = bytearray(320*10)
lv.disp_buf_init(disp_buf1, buf1_1, None, len(buf1_1)//4)
disp_drv = lv.disp_drv_t()
lv.disp_drv_init(disp_drv)
disp_drv.buffer = disp_buf1
disp_drv.flush_cb = lv_h.flush
disp_drv.hor_res = 320
disp_drv.ver_res = 240
lv.disp_drv_register(disp_drv)

indev_drv = lv.indev_drv_t()
lv.indev_drv_init(indev_drv)
indev_drv.type = lv.INDEV_TYPE.POINTER
indev_drv.read_cb = lv_h.read
lv.indev_drv_register(indev_drv)

class Page_Buttons:
    def __init__(self, app, page):
        self.app = app
        self.page = page

        # counter button
        self.counter_btn = lv.btn(page)
        self.counter_btn.set_size(100,60)
        self.counter_btn.align(page, lv.ALIGN.CENTER, 0, 0)
        self.counter_label = lv.label(self.counter_btn)
        self.counter_label.set_text('Count')
        self.counter_btn.set_event_cb(self.on_counter_btn)
        self.counter = 0

    def on_counter_btn(self, obj, event):
        if event == lv.EVENT.CLICKED:
            self.counter += 1
            self.counter_label.set_text(str(self.counter))

class Page_Slider:
    def __init__(self, app, page):
        self.app = app
        self.page = page

        # slider
        self.slider = lv.slider(page)
        self.slider.align(page, lv.ALIGN.CENTER, 0, -10)
        self.slider_label = lv.label(page)
        self.slider_label.align(self.slider, lv.ALIGN.OUT_LEFT_MID, -10, 0)
        self.slider.set_event_cb(self.on_slider_changed)
        self.on_slider_changed(None)

    def on_slider_changed(self, obj=None, event=-1):
        self.slider_label.set_text(str(self.slider.get_value()))


class Anim(lv.anim_t):
    def __init__(self, obj, val, size, exec_cb, path_cb, time=500, playback = False, ready_cb=None):
        super().__init__()
        lv.anim_init(self)
        lv.anim_set_time(self, time, 0)
        lv.anim_set_values(self, val, val+size)
        if callable(exec_cb):
            lv.anim_set_custom_exec_cb(self, exec_cb)
        else:
            lv.anim_set_exec_cb(self, obj, exec_cb)
        lv.anim_set_path_cb(self, path_cb )
        if playback: lv.anim_set_playback(self, 0)
        if ready_cb: lv.anim_set_ready_cb(self, ready_cb)
        lv.anim_create(self)

class AnimatedChart(lv.chart):
    def __init__(self, parent, val, size):
        super().__init__(parent)
        self.val = val
        self.size = size
        self.max = 2000
        self.min = 500
        self.factor = 100
        self.anim_phase1()

    def anim_phase1(self):
        Anim(
            self,
            self.val,
            self.size,
            lambda a, val: self.set_range(0, val),
            lv.anim_path_ease_in,
            ready_cb=lambda a:self.anim_phase2(),
            time=(self.max * self.factor) // 100)

    def anim_phase2(self):
        Anim(
            self,
            self.val+self.size,
            -self.size,
            lambda a, val: self.set_range(0, val),
            lv.anim_path_ease_out,
            ready_cb=lambda a:self.anim_phase1(),
            time=(self.min * self.factor) // 100)


class Page_Chart():
    def __init__(self, app, page):
        self.app = app
        self.page = page
        self.chart = AnimatedChart(page, 100, 1000)
        self.chart.set_width(page.get_width() - 100)
        self.chart.set_height(page.get_height() - 30)
        self.chart.align(page, lv.ALIGN.CENTER, 0, 0)
        self.series1 = self.chart.add_series(lv.color_hex(0xFF0000))
        self.chart.set_type(self.chart.TYPE.POINT | self.chart.TYPE.LINE)
        self.chart.set_series_width(3)
        self.chart.set_range(0,100)
        self.chart.init_points(self.series1, 10)
        self.chart.set_points(self.series1, [10,20,30,20,10,40,50,80,95,80])
        self.chart.set_x_tick_texts('a\nb\nc\nd\ne', 2, lv.chart.AXIS.DRAW_LAST_TICK)
        self.chart.set_x_tick_length(10, 5)
        self.chart.set_y_tick_texts('1\n2\n3\n4\n5', 2, lv.chart.AXIS.DRAW_LAST_TICK)
        self.chart.set_y_tick_length(10, 5)
        self.chart.set_div_line_count(3, 3)
        self.chart.set_margin(30)

        self.slider = lv.slider(page)
        self.slider.align(self.chart, lv.ALIGN.OUT_RIGHT_TOP, 10, 0)
        self.slider.set_width(30)
        self.slider.set_height(self.chart.get_height())
        self.slider.set_range(10, 200)
        self.slider.set_value(self.chart.factor, 0)
        self.slider.set_event_cb(self.on_slider_changed)

    # Create a slider that controls the chart animation speed
    def on_slider_changed(self, obj=None, event=-1):
        self.chart.factor = self.slider.get_value()


class Screen_Main(lv.obj):
    def __init__(self, app, *args, **kwds):
        self.app = app
        super().__init__(*args, **kwds)

        self.tabview = lv.tabview(self)
        self.tabview.set_style(lv.tabview.STYLE.BG, lv.style_plain_color)
        self.page_buttons = Page_Buttons(self.app, self.tabview.add_tab('Button'))
        self.page_slider = Page_Slider(self.app, self.tabview.add_tab('Slider'))
        self.page_chart = Page_Chart(self.app, self.tabview.add_tab('Chart'))


screen_main = Screen_Main(lv.obj())
lv.scr_load(screen_main)

tim = time.ticks_ms()
while True:
    if time.ticks_ms()-tim > 5:
        tim = time.ticks_ms()
        lv.task_handler()
        lv.tick_inc(5)

实验准备

  1. 野火K210 AI视觉相机 连接到 CanMV IDE

  2. 执行程序

运行结果

1.运行程序后,可以看到 野火K210 AI视觉相机 会显示下面内容

野火logo

2.点击两下 button 按键后,可以看到 button 变成 1 再由 1 变成 2

野火logo

3.按住屏幕的右边缘向左边滑动或者点击 slider 按键,切换带滑块页面

野火logo

4.按住白色小方块,往右边拖,可以看到下面内容

野火logo

5.按住屏幕的右边缘向左边滑动或者点击 chart 按键,切换带图表页面,此时图表里面的内容会上下运动

野火logo

6.按住右边的小滑块,往上推,可以看到图表里的变化趋势变得很慢

野火logo

7.按住右边的小滑块,往下拉,可以看到图表里的变化趋势变得很快

野火logo

讲解

1
2
3
4
5
import lvgl as lv
import lvgl_helper as lv_h
import touchscreen as ts
import lcd
import time
  • 这些库提供了LVGL框架、LCD显示、触摸屏支持和一些辅助函数

1
2
3
lcd.init()
ts.init()
lv.init()
  • 这三行代码分别初始化了LCD显示、触摸屏和LVGL库。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
disp_buf1 = lv.disp_buf_t()
buf1_1 = bytearray(320*10)
lv.disp_buf_init(disp_buf1, buf1_1, None, len(buf1_1)//4)
disp_drv = lv.disp_drv_t()
lv.disp_drv_init(disp_drv)
disp_drv.buffer = disp_buf1
disp_drv.flush_cb = lv_h.flush
disp_drv.hor_res = 320
disp_drv.ver_res = 240
lv.disp_drv_register(disp_drv)
  • 这些代码创建了一个显示缓冲区disp_buf1,并设置了一个显示驱动程序disp_drv,包括缓冲区、刷新回调函数、水平分辨率和垂直分辨率。

1
2
3
4
5
indev_drv = lv.indev_drv_t()
lv.indev_drv_init(indev_drv)
indev_drv.type = lv.INDEV_TYPE.POINTER
indev_drv.read_cb = lv_h.read
lv.indev_drv_register(indev_drv)
  • 这些代码创建并初始化了一个输入设备驱动程序对象indev_drv,用于处理触摸屏输入。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Page_Buttons:
    def __init__(self, app, page):
        self.app = app
        self.page = page

        # counter button
        self.counter_btn = lv.btn(page)
        self.counter_btn.set_size(100,60)
        self.counter_btn.align(page, lv.ALIGN.CENTER, 0, 0)
        self.counter_label = lv.label(self.counter_btn)
        self.counter_label.set_text('Count')
        self.counter_btn.set_event_cb(self.on_counter_btn)
        self.counter = 0

    def on_counter_btn(self, obj, event):
        if event == lv.EVENT.CLICKED:
            self.counter += 1
            self.counter_label.set_text(str(self.counter))
  • 定义了按钮页面,具体可参照上面章节的内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Page_Slider:
    def __init__(self, app, page):
        self.app = app
        self.page = page

        # slider
        self.slider = lv.slider(page)
        self.slider.align(page, lv.ALIGN.CENTER, 0, -10)
        self.slider_label = lv.label(page)
        self.slider_label.align(self.slider, lv.ALIGN.OUT_LEFT_MID, -10, 0)
        self.slider.set_event_cb(self.on_slider_changed)
        self.on_slider_changed(None)

    def on_slider_changed(self, obj=None, event=-1):
        self.slider_label.set_text(str(self.slider.get_value()))
  • 定义了滑块页面,具体可参照上面章节的内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
class Anim(lv.anim_t):
    def __init__(self, obj, val, size, exec_cb, path_cb, time=500, playback = False, ready_cb=None):
        super().__init__()
        lv.anim_init(self)
        lv.anim_set_time(self, time, 0)
        lv.anim_set_values(self, val, val+size)
        if callable(exec_cb):
            lv.anim_set_custom_exec_cb(self, exec_cb)
        else:
            lv.anim_set_exec_cb(self, obj, exec_cb)
        lv.anim_set_path_cb(self, path_cb )
        if playback: lv.anim_set_playback(self, 0)
        if ready_cb: lv.anim_set_ready_cb(self, ready_cb)
        lv.anim_create(self)

class AnimatedChart(lv.chart):
    def __init__(self, parent, val, size):
        super().__init__(parent)
        self.val = val
        self.size = size
        self.max = 2000
        self.min = 500
        self.factor = 100
        self.anim_phase1()

    def anim_phase1(self):
        Anim(
            self,
            self.val,
            self.size,
            lambda a, val: self.set_range(0, val),
            lv.anim_path_ease_in,
            ready_cb=lambda a:self.anim_phase2(),
            time=(self.max * self.factor) // 100)

    def anim_phase2(self):
        Anim(
            self,
            self.val+self.size,
            -self.size,
            lambda a, val: self.set_range(0, val),
            lv.anim_path_ease_out,
            ready_cb=lambda a:self.anim_phase1(),
            time=(self.min * self.factor) // 100)

class Page_Chart():
    def __init__(self, app, page):
        self.app = app
        self.page = page
        self.chart = AnimatedChart(page, 100, 1000)
        self.chart.set_width(page.get_width() - 100)
        self.chart.set_height(page.get_height() - 30)
        self.chart.align(page, lv.ALIGN.CENTER, 0, 0)
        self.series1 = self.chart.add_series(lv.color_hex(0xFF0000))
        self.chart.set_type(self.chart.TYPE.POINT | self.chart.TYPE.LINE)
        self.chart.set_series_width(3)
        self.chart.set_range(0,100)
        self.chart.init_points(self.series1, 10)
        self.chart.set_points(self.series1, [10,20,30,20,10,40,50,80,95,80])
        self.chart.set_x_tick_texts('a\nb\nc\nd\ne', 2, lv.chart.AXIS.DRAW_LAST_TICK)
        self.chart.set_x_tick_length(10, 5)
        self.chart.set_y_tick_texts('1\n2\n3\n4\n5', 2, lv.chart.AXIS.DRAW_LAST_TICK)
        self.chart.set_y_tick_length(10, 5)
        self.chart.set_div_line_count(3, 3)
        self.chart.set_margin(30)

        self.slider = lv.slider(page)
        self.slider.align(self.chart, lv.ALIGN.OUT_RIGHT_TOP, 10, 0)
        self.slider.set_width(30)
        self.slider.set_height(self.chart.get_height())
        self.slider.set_range(10, 200)
        self.slider.set_value(self.chart.factor, 0)
        self.slider.set_event_cb(self.on_slider_changed)

    # Create a slider that controls the chart animation speed
    def on_slider_changed(self, obj=None, event=-1):
        self.chart.factor = self.slider.get_value()
  • 定义了图标页面,具体可参照上面章节的内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Screen_Main(lv.obj):
    def __init__(self, app, *args, **kwds):
        self.app = app
        super().__init__(*args, **kwds)

        self.tabview = lv.tabview(self)
        self.tabview.set_style(lv.tabview.STYLE.BG, lv.style_plain_color)
        self.page_buttons = Page_Buttons(self.app, self.tabview.add_tab('Button'))
        self.page_slider = Page_Slider(self.app, self.tabview.add_tab('Slider'))
        self.page_chart = Page_Chart(self.app, self.tabview.add_tab('Chart'))
  • 这个类创建了一个标签视图,它包含三个标签页,每个标签页有不同的组件。

1
2
screen_main = Screen_Main(lv.obj())
lv.scr_load(screen_main)
  • 这行代码创建了一个主屏幕对象,并将其加载到LVGL的屏幕上。

1
2
3
4
5
6
tim = time.ticks_ms()
while True:
    if time.ticks_ms()-tim > 5:
        tim = time.ticks_ms()
        lv.task_handler()
        lv.tick_inc(5)
  • 最后,这段代码进入了一个无限循环。循环中,它每隔5毫秒调用lv.task_handler()来处理LVGL的任务,并使用lv.tick_inc(5)来通知LVGL时间已经过去了5毫秒,这样可以更新屏幕和其他LVGL相关的任务。