基于树莓派RP2040利用MMA7660重力感应传感器制作一个水平仪
基于树莓派RP2040,使用micropython编程语言,利用MMA7660重力感应传感器和ST7789LCD显示器制作一个水平仪
标签
嵌入式系统
显示
2022寒假在家练
杨老基
更新2022-03-03
北京理工大学
955

1 项目介绍

基于树莓派RP2040,使用micropython编程语言,利用MMA7660重力感应传感器和ST7789LCD显示器制作一个水平仪。在LCD屏上显示一款水平仪,通过一个滚动的小球或气泡,来显示当前板子的倾斜度,当板子处于水平位置的时候,小球停在屏幕的正中间,倾斜板子,小球偏移,并能够显示偏移的角度(二维信息)。

 

2 设计思路(框图)

我的设计思路是先分别测试实现显示器和重力传感器的功能。导入MMA7660固件,调用machine库中的I2C函数,通过查阅电路图获取引脚信息,使用getSample函数获取重力传感器的参数。导入ST7789固件,使用矩形填充函数在设计完UI界面后,我将重力传感器的参数导入,然后将这个参数转为坐标,该坐标为圆心绘制圆,以实现滚动小球的功能。

FnOvkVfe7rAzNPNiQqOSpCG-yswx

 

3 简单的硬件介绍

我使用的硬件有,两块亚克力板,一根USB数据线,基于树莓派RP2040的嵌入式系统学习板,其中使用到了RP2040微控制器、MMA7660重力感应传感器和ST7789LCD显示器。

 

4 实现的功能及图片展示

4.1 实现滚动小球的功能

使用getSample函数获取重力传感器的参数后,即为倾斜的角度,然后将这个参数转为坐标,设置半径,该坐标为圆心绘制圆,并将其显示在屏幕上。

FpMyE73KoeWCoLrloKmpsJRsGNb4FiUH-XmxUJ05_2CuYEg8Ca23L3IGFoQ1FN7Viggzldrp_aoiabX-Np-uFuY01ViMyMMbJtkQIR7frNVbygFC

 

4.2 显示倾斜角度和标尺的功能

倾斜板子,小球偏移,并将倾斜的角度显示在屏幕右上方。

FuFveaMQIk_I73eW_18nRRIxc2F4

 

5 主要代码片段及说明

 

先导入仓库中的board文件、st7789和mma7660固件以及字体文件,通过查看电路图获取对应引脚信息。

 

5.1 实现UI界面设计和RGB色彩显示功能

 

导入ST7789固件后,可以看到已经预设了几种颜色参数。

 

BLACK = const(0x0000)

BLUE = const(0x001F)

RED = const(0xF800)

GREEN = const(0x07E0)

CYAN = const(0x07FF)

MAGENTA = const(0xF81F)

YELLOW = const(0xFFE0)

WHITE = const(0xFFFF)

 

在主模块中,从ST7789导入需要使用到的颜色作为color参数。

 

from st7789 import BLUE, WHITE, RED

 

绘制UI界面时,可以使用ST7789中的矩形填充函数,

 

    def fill_rect(self, x, y, width, height, color):

        self.set_window(x, y, x + width - 1, y + height - 1)

        chunks, rest = divmod(width * height, _BUFFER_SIZE)

        pixel = _encode_pixel(color)

        self.dc.on()

        if chunks:

            data = pixel * _BUFFER_SIZE

            for _ in range(chunks):

                self.write(None, data)

        if rest:

            self.write(None, pixel * rest)

 

通过设置左上角坐标,长宽参数,即可绘制主屏幕、垂直副轴和水平副轴。然后使用text函数显示标尺刻度,UI界面即可设计完成。

 

display.fill(BLUE)

display.fill_rect(10, 50, 180, 180, WHITE)

display.fill_rect(10, 10, 180, 30, WHITE)

display.fill_rect(200, 50, 30, 180, WHITE)

 

    display.text(font1,"""-90""".format(a), 15, 145, BLUE, WHITE)

    display.text(font1,"""-45""".format(a), 55, 145, BLUE, WHITE)

    display.text(font1,"""0""".format(a), 105, 145, BLUE, WHITE)

    display.text(font1,"""45""".format(a), 135, 145, BLUE, WHITE)

    display.text(font1,"""90""".format(a), 170, 145, BLUE, WHITE)

    display.text(font1,"""90""".format(a), 105, 55, BLUE, WHITE)

    display.text(font1,"""45""".format(a), 105, 90, BLUE, WHITE)

    display.text(font1,"""-45""".format(a), 105, 175, BLUE, WHITE)

    display.text(font1,"""-90""".format(a), 105, 215, BLUE, WHITE)

 

5.2 获取MMA7660重力感应传感器参数

 

通过查看电路图获取对应引脚信息,分别使用machine库中的I2C和SPI函数将两个固件的总线导入。

 

i2c1 = I2C(1, scl=Pin(pin_cfg.i2c1_scl), sda=Pin(pin_cfg.i2c1_sda))

acc = MMA7660(i2c1)

acc.on(True)

 

st7789_res = 0

st7789_dc  = 1

disp_width = 240

disp_height = 240

CENTER_Y = int(disp_width/2)

CENTER_X = int(disp_height/2)

print(uos.uname())

spi_sck=machine.Pin(2)

spi_tx=machine.Pin(3)

spi0=machine.SPI(0,baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)

display = st7789.ST7789(spi0, disp_width, disp_width,

                          reset=machine.Pin(st7789_res, machine.Pin.OUT),

                          dc=machine.Pin(st7789_dc, machine.Pin.OUT),

                          xstart=0, ystart=0, rotation=0)

 

进入while true循环后,使用getSample函数获得重力传感器的参数,将其转换为坐标,使用ST7789的text函数将其显示在屏幕右上方。

 

    display.text(font1,"""X:{0}""".format(a), 200, 10, BLUE, WHITE)

    display.text(font1,"""Y:{0}""".format(c), 200, 20, BLUE, WHITE)

    display.text(font1,"""Z:{0}""".format(r[2]), 200, 30, BLUE, WHITE)

 

然后以该坐标为圆心,设置半径,根据圆的极坐标公式分别绘制主界面和垂直、水平轴的滚动小球。

 

    for theta in range(60):

        x = int(a + 100 + 14 * math.cos(theta))

        y = int(b + 140 + 14 * math.sin(theta))

        display.fill_rect(x, y, 3, 3, RED)

        x = int(a + 100 + 14 * math.cos(theta))

        y = int(24 + 14 * math.sin(theta))

        display.fill_rect(x, y, 3, 3, RED)

        x = int(214 + 14 * math.cos(theta))

        y = int(b + 140 + 14 * math.sin(theta))

        display.fill_rect(x, y, 3, 3, RED)

 

最后使用矩形绘制函数不断刷新界面即可。

 

    display.fill_rect(a + 85, b + 125, 33, 33, WHITE)

    display.fill_rect(a + 85, 10, 32, 30, WHITE)

    display.fill_rect(200, b + 125, 30, 32, WHITE)

    display.fill_rect(200, 10, 40, 30, WHITE)

    display.fill_rect(99, 50, 3, 180, BLUE)

    display.fill_rect(10, 139, 180, 3, BLUE)

    

    display.fill_rect(54, 10, 3, 30, BLUE)

    display.fill_rect(99, 10, 3, 30, BLUE)

    display.fill_rect(144, 10, 3, 30, BLUE)

    

    display.fill_rect(200, 94, 30, 3, BLUE)

    display.fill_rect(200, 139, 30, 3, BLUE)

    display.fill_rect(200, 184, 30, 3, BLUE)

 

6 遇到的主要难题及解决方法

 

6.1 如何在屏幕上绘制圆

 

可以通过math库使用圆的极坐标公式绘制,也可以使用ST7789的blit_buffer函数导入圆的图片文件。

        x = int(a + 100 + 14 * math.cos(theta))

        y = int(b + 140 + 14 * math.sin(theta))

 

6.2 如何刷新屏幕

 

通过使用ST7789的矩形填充函数,每绘制一次就在圆球所在区域进行局部刷新,然后重新绘制坐标线和圆,不断重复上述步骤。

 

6.3 屏幕刷新速度过慢的问题

 

屏幕刷新速度过慢可能是因为使用数学函数绘制的问题,可除了上述使用局部刷新的方法之外,通过使用矩形填充函数绘制4乘4矩形代替绘制单个像素点,可提升刷新速度。

 

6.4 心得体会

 

虽然我已经是一名大三的学生,但是在此之前我完全没有接触过和该项目有关的软硬件知识。由于我所学的专业是通信工程,在此之前只浅显地接触过C语言,而且对什么是嵌入式、库、调用和python等知识不甚了解。因此,在刚开始着手进行项目时,我因为对这个树莓派RP2040一无所知,在畏难情绪影响下,我并没有打算脚踏实地从头开始学起,而是盘算着走个捷径。因此我在网上查找这十个项目的源代码,希望能自己拼接一下就能在板卡上跑起来,然后直接提交了事。然而,因为缺乏相关知识,我甚至不知道如何运行程序,看着IED上的不断报错,我觉得自己不能再浪费时间。我下定决心从头学习一遍

考虑到我使用的语言是micropython,所以我打算先从头开始,学习一遍python语言。我大概花了两三天左右学完了python,了解了python的调用方法,比如python的调用路径存放在sys.path变量里面等等知识,虽然我们现在所做的项目并没有用到这些。在学完python后,我确定了选择水平仪作为我的项目,根据该项目的要求,我又研究了该树莓派平台一些硬件的使用,譬如RP2040、ST7789和MMA7660的使用,在分别测试其功能后,我将各个模块拼接了起来,并最终完成了该项目。

 

7 未来的计划或建议等

我已经成功实现了水平仪的滚动小球和倾斜角度显示的功能,但目前的缺点是刷新速度太慢,滚动惯性不灵敏等问题,我计划下一步优化绘制和刷新方式,增加过滤器,提升刷新率和小球滚动效果,并更换UI界面为图片,不再使用函数绘制,以提高美观性。

 

附件下载
杨丰珲_北京理工大学_基于树莓派RP2040利用MMA7660重力感应传感器制作一个水平仪_代码.rar
团队介绍
个人姓名:杨丰珲 学校:北京理工大学
团队成员
杨老基
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号