2022暑假在家一起练 - 基于rp2040的计算器实现
使用rp2040游戏机板卡制作一个可切换功能的计算器,用LCD做界面,用4向摇杆和两个按键做输入,用姿态传感器切换功能。
标签
RP2040
2022暑假在家练
Wcy
更新2022-09-02
北京理工大学
772

内容介绍

1 项目需求

目标:制作一个可切换功能的计算器

具体要求:

用LCD做界面,用4向摇杆和两个按键做输入,用姿态传感器切换功能,制作一款具有四种计算功能、通过姿态传感器可以切换功能的计算器,比如下图中的三个功能,再增加一个程序员常用到的制式转换器。

制作者可以自己定义4种不同的功能,旋转板子可以切换到不同功能的界面,用四向摇杆和按键搭配进行计算。

2 完成的功能及达到的性能

2.1 按键界面显示

点击运行,经过开屏动画后屏幕默认出现以下界面。

右上角黑框用于显示数字和字符;

黄色小点作用类似于鼠标,受摇杆控制;

白色字符均可以按下,显示在右上输出框。

FprPOWuXYE7dyvvMZfUytbM2NKxn

2.2 切换界面

陀螺仪用于读取板卡姿态,以控制计算器的界面切换。

事先摆好姿态,再按下B键,计算机切换到相应界面,并不再随姿态变化;

四种界面如下:

普通模式:左前角在下

FtTiRf9hsHhcGSAgwaFEqQr-a5uA

制式转换模式:右后角在下

FgU-cn4RDNeJbzRfrGc6W5GsUBJF

幂与指数模式:左后角在下

FlpRK24IVSTNyXuSKB15RDbnfTwj

三角函数模式:右前角在下

FhYsVNbHipVlIhDS-mYMgG24XG04

2.3 按键与摇杆输入

摇杆控制光标移动;

按下A键,对光标所在的按键进行操作;

“=”键按下,计算结果并输出到右上角输出框;

“ac”键按下,清空输出框;

其它键按下,输入字符到输出框里。

2.4 输入与计算

由于使用了python内置库中的eval()函数,其功能是执行字符串表达式并返回字符串的值,因此在输入上与普通计算机有所不同:

普通四则运算与普通计算机一致;

计算幂函数和指数函数时请参考以下格式,输入“5**2”表示求5的平方;

计算三角函数和其他函数时引入了内置math库,输入参考以下案例:

三角函数输入示例:

    按下cos出现'math.cos(',

    再按数字出现'math.cos(pi',

    再按括号出现'math.cos(pi)',此时按’=’方可准确计算,注意为弧度制。

FiS5zTjD8M2qIvgA-BL0BwFLkF0f

关于进制转换,参考以下案例:

    选择想要的进制转换,例如db为dec->bin

    按下db1,'bin('

    按下数字,'bin(5'

    按下db2,'bin(5)',此时按’=’方可准确计算。

Fhn3Btm1AEF7O7h79sNd5lpMwbgr

3 实现思路

通过ADC读取电位计上的电压分压,确定摇杆x、y轴的位移,进而移动光标;

通过I2C协议获取陀螺仪重力感应传感器参数,并转化为x、y方向的偏移坐标,进而用板卡姿态决定计算界面的显示;

将界面上的字符str_display与实际的字符内容str_value联系起来,按下A键即输入到输出框。

4 实现过程

4.1 程序流程图

FpwT5cG9ZrYNLOPOEILIAsbiqMrC

4.2 界面显示

通过spi协议,导入ST7789固件,在LCD屏上绘制图形界面。

class LCDdisplay:
    def __init__(self):
        print('display the mode')
    def mode1(self):
		display.fill_rect(0, 49, 240, 191, 0x0000)
		display.fill_rect(0, 0, 47, 50, 0x0000)
		display.hline(0, 192, 240, 0xFFFF)
		display.hline(0, 144, 240, 0xFFFF)
		display.hline(0, 96, 240, 0xFFFF)
		display.hline(0, 48, 240, 0xFFFF)
		display.vline(60, 0, 240, 0xFFFF)
		display.vline(120, 48, 192, 0xFFFF)
		display.vline(180, 48, 192, 0xFFFF)

		display.text(font2, "=", 25, 200)
		display.text(font2, "0", 85, 200)
		display.text(font2, ".", 145, 200)
		display.text(font2, "+", 205, 200)
…………

4.3 界面切换

获取MMA7660重力感应传感器参数:通过I2C协议获取陀螺仪重力感应传感器参数,并转化为x、y方向的偏移坐标,进而用板卡姿态决定计算界面的显示;

#陀螺仪驱动
i2c1 = I2C(1, scl=Pin(11), sda=Pin(10))
attitude = MMA7660(i2c1)
attitude.on(True)
#姿态接收
attitude_receive = bytearray(3)
r = [0 for x in range(3)]
#返回二补数
def twos_compliment(n, nbits):
    sign_bit = 1 << nbits - 1
    sign = 1 if n & sign_bit == 0 else -1
    val = n & ~sign_bit if sign > 0 else sign * ((sign_bit << 1) - n)
return val
…………
attitude.getSample(attitude_receive)
        #转换为陀螺仪偏移坐标
        for i in range(3):
            r[i] = twos_compliment(attitude_receive[i], 6)
        x_bias = -(r[1]*4)
        y_bias = r[0]*4-20
        utime.sleep(0.5)

        if x_bias>0 and y_bias>0:
#x>0,y>0,mode1
            my_display.mode1()
            mode_num = 1
…………

4.4 光标移动

通过ADC读取电位计上的电压分压,确定摇杆x、y轴的位移,进而移动光标。

#定义光标对象
class Cursor:
    def __init__(self,x_coord,y_coord):
        self.x_coord = x_coord
        self.y_coord = y_coord
#使用前给x_coord和y_coord赋初值
    def cursor_move(self):
        xValue = xAxis.read_u16()
        yValue = yAxis.read_u16()
        if xValue <= 600 and self.x_coord>60:
            self.x_coord = self.x_coord-60
        elif xValue >= 60000 and self.x_coord<179:
            self.x_coord = self.x_coord+60
        if yValue <= 600 and ((self.x_coord<60 and self.y_coord>48) or (self.x_coord>60 and self.y_coord>96)):
            self.y_coord = self.y_coord-48
        elif yValue >= 60000 and self.y_coord<192:
            self.y_coord = self.y_coord+48
…………
#光标的初始坐标与绘制
display.fill_rect(85, 152, 5, 5, 0xFFE0)
#光标移动
    my_cursor.cursor_move()
    if xBefore == my_cursor.x_coord and yBefore == my_cursor.y_coord:
        display.fill_rect(my_cursor.x_coord, my_cursor.y_coord, 5, 5, 0xFFE0)
    else:
    #将原光标涂黑去除,绘制新光标
        display.fill_rect(xBefore, yBefore, 5, 5, 0x0000)
        display.fill_rect(my_cursor.x_coord, my_cursor.y_coord, 5, 5, 0xFFE0)

4.5 计算实现

对输入的字符串“formula”用内置的eval()函数计算并返回结果,并在输出框中显示。

solution = eval(self.formula)
                display.fill_rect(62, 0, 175, 47, 0x0000)
                display.text(font2, str(solution), 62, 0)

5 遇到的主要难题

5.1 按钮的坐标

按钮坐标、光标坐标、界面显示需要一一对应,即一个坐标值对应着一个字符,同时对应着字符的功能。为了将显示的字符与字符的实际内容对应,我创建了字典dict,以字符坐标为key,以实际内容为value,一一对应;但是还有光标坐标的问题,于是我利用字符格子的规则排列,给光标坐标赋初值,并且每次移动固定的数值,光标坐标就能始终与字符坐标对应。因为用了这种处理,我只能将每个界面的板式做的一样。

5.2 字符输入与计算的问题

普通计算机上的字符输入非常自由,可以在任意位置输入,也可以删去字符,数学函数的使用也很便捷;但是,首先我使用了eval()函数对字符串做统一处理,算式中会出现math.cos(pi)之类的字样;其次,插入字符和删除字符设计麻烦的字符串操作,因此没有做成。

5.3 字符显示的问题

输入的字符串过长时,输出框不能完全显示,我的想法是计算字符串长度与输出框长度比较,再缩小字符,未能实现;另外,在绘制光标时,我将其绘制在了不会遮挡字符的黑色背景上,每次移动时只需要重绘黑色背景和绘制新光标,因此光标的移动有很大局限性,而且不能连续移动。

6 未来的计划建议

主要是解决以上遇到的难题,比如:

自己编写数学函数,从而简化输入的字符,也更符合常规;

添加普通计算器会有的移动光标和删去字符的功能;

改善字符串过长二不能完整显示的问题;

做一个自由移动的光标,等等。

附件下载

Calculator.rar

团队介绍

北京理工大学 王承佑
团队成员
Wcy

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号