用基于树莓派RP2040核心设计控制LCD和电脑界面的“鼠标”
利用板上的四向摇杆和按键设计一款“鼠标” 在240*240的LCD屏幕内可以通过该鼠标进行菜单选择和参数控制(在屏幕上要有上图中图形化的箭头形状) 通过USB端口可以控制PC屏幕上的光标移动和点击操作,行使电脑鼠标的功能
标签
2022寒假在家一起练
树莓RP2040
嵌入式系统开发平台
摇杆鼠标项目
mini城
更新2022-03-04
北京科技大学
787

项目总结报告

 

项目描述

Fu40tyN6ZcwObaH0wiVruUl-llvr

 

设计思路

  • 引用Pin、SPI、ADC、hid、st7789、mma7660、time、machine、board

先读取摇杆xy轴参数,为了保证参数的准确性,需要将原始参数简化或减去无位移状态时显示的参数,然后 将处理后的数据提供给hid库move方法控制电脑鼠标位移,之后读取按钮a按钮b参数,判断a和b按钮是否闭 合实现鼠标左右键功能;读取按钮start参数,判断start按钮是否闭合来控制鼠标滚轮功能开启关闭,最后 通过select按钮暂停或退出。

  • 通过st7789画出箭头形状,创建箭头函数,用xy轴控制箭头位置,然后读取摇杆xy轴参数,将原始参数简化或减去无位移状态时显示的参数,将处理后的数据提供给箭头函数,达到控制箭头移动的目的。最后通过 select按钮暂停或退出。

FuMtRSQnSiS-b3dXFa4MZxCYXukX

 

硬件介绍

  • 采用树莓派Pico核心芯片RP2040,双核Arm Cortex M0+内核,频率133MHz,264KB内存,可编程IO接口,温度传感器,240*240分辨率的彩色IPS LCD,四向摇杆,2个轻触按键,三轴姿态传感器,红外接收管,红外发射管,蜂鸣器,双排16Pin连接器,一个USB Type C接口同时也用于供电

实现的功能

引用库和模块:machine、hid、st7789、board、mma7660、time、uos、fonts

1.电脑鼠标控制

利用开发板上的四向摇杆来控制电脑鼠标进行上下左右等8个方向的位移,通过判断摇杆xy轴数据变化读取参 数并处理,将处理后的数据用于鼠标的位移。

利用开发板上的A、B按键实现了电脑鼠标的左右按键功能,按钮A控制鼠标右键,按钮B控制鼠标左键,通过 判断按钮A、按钮B的value()返回参数(0或1),按钮返回1为release,返回0为press,按钮B同按键A。

利用开发板上的姿态传感器硬件实现电脑鼠标的滚轮功能,通过判断按钮Select返回参数(0或1)控制滚轮功能 是否启用,启用之后正反向旋转控制滚轮上下滚动,左右旋转控制滚轮横向滚动。

在lcd屏幕右下角绘制有两个矩形,控制屏幕方块位移至矩形当中判断按钮B按下来参数控制,左降速右提速

2.LCD屏幕鼠标控制

首先利用line方法绘制鼠标,然后将鼠标封装为函数方便之后调用,再绘制一次鼠标函数用以将绘制的鼠标擦 除,读取摇杆xy轴参数变化并处理数据用于控制绘制的鼠标,用x轴控制鼠标的上下位移,y轴控制鼠标的左 右位移。

3.系统信息

提取开发板信息并显示与lcd屏幕

 

实物展示

  • 功能目录

FlnS0HWwGxqOBbYVOFHKUdFWjqdO

  • 运行功能

FiVyEJnJiXfvEbRCJtPJr_uKq_d0

  • 判断继续或者退出功能

Frmh5VhYOuI_CE2XZ3j2DbQdJgTW

 

主要代码和说明

  • 屏幕初始化

def homepage():#开机
    display.fill(att.black)
    display.text(att.font16,'Hello!',70,40,att.white,att.background)
    display.text(att.font16,'Welcome To',40,90,att.white,att.background)
    display.text(att.font16,'Pi Pico',62,140,att.white,att.background)
    display.text(att.font8,'Please A or B',62,220,att.white)
    time.sleep(1)
  • 功能目录,创建功能类字典,将功能数赋值lines,摇杆y轴移动lines±1,功能行变更且相应行背景颜色变更,判断start按钮,为0时运行当前行的程序
def menu():#菜单
    global lines
    menus = {0:'',1:'mousePc',2:'mousePico',3:'att-sensor',4:'setting',5:'info'}
    display.fill(0)
    display.text(att.font16,' MENUS ',4,4,att.white,att.background)
    for lists in range(1,len(menus)):
        display.text(att.font16,'* {0:^12}*'.format(menus[lists]),0,40*lists,att.white)
    clamp = lambda change: min(5, max(1, change))
    while True:
        w,h =int(board.xaxis.read_u16()/3000)-10,int(board.yaxis.read_u16()/3000)-11#控制杆数值
        if  w > 5 :
            lines += 1
            next_line = clamp(lines-5)
            up = next_line-1
            display.text(att.font16,'* {0:^12}*'.format(menus[next_line]),0,40*next_line,att.white,att.background)
            if up == 0:
                pass
            else:
                display.text(att.font16,'* {0:^12}*'.format(menus[up]),0,40*up,att.white)
        if  w < -5:
            lines -= 1
            next_line = clamp(lines-5)
            up = clamp(lines-4)
            display.text(att.font16,'* {0:^12}*'.format(menus[next_line]),0,40*next_line,att.white,att.background)
            display.text(att.font16,'* {0:^12}*'.format(menus[up]),0,40*up,att.white)
        if not buttonStart.value():
            if clamp(lines-5) == 1:
                pc_mouse()#电脑鼠标控制
            elif clamp(lines-5) == 2:
                display.fill(0)
                mouse_arrow()#
                pico_mouse()#pico箭头控制
            elif clamp(lines-5) == 3:
                att_sonsor()#三轴姿态传感器
            elif clamp(lines-5) == 4:
                setting_b()
            elif clamp(lines-5) == 5:
                info()
        time.sleep(0.01)
  • 电脑鼠标控制函数,引入hid库,读取摇杆xy轴数据,处理获取到的摇杆数值,判断摇杆位移,利用数值控制电脑鼠标移动,判断ab按钮value数值,b按钮控制鼠标左键,a按钮控制鼠标右键,判断lcd中白色方块位置,在右侧矩形并按下b按钮,鼠标移动速度+1,在左侧矩形并按下b按钮,鼠标移动速度-1,最后按钮select暂停,摇杆左右控制yes和no并用按钮b确认
def pc_mouse(x=0,y=0,v=0,h=0):#电脑鼠标控制
    global width,height,mouse_speed
    display.fill(0)
    clamp = lambda change: min(230, max(0, change))#约束函数最大为230最小为0
    clamp1 = lambda change: min(3, max(1, change))#约束函数最大为3最小为1
    display.fill_rect(120,120,10,10,att.white)
    display.text (att.font8,'{}   X:{:d}   Y:{:<10d}'.format('PC-MOUSE',0,0),0,0,att.white,att.background)
    while True:
        display.rect(120,190,40,30,att.white)
        display.rect(180,190,40,30,att.white)
        if not buttonStart.value():
            AS()
        x,y =int(xAxis.read_u16()/3000)-10,int(yAxis.read_u16()/3000)-11#处理控制杆数值   
        if not 2> x > -2 or not 2> y > -2:#判断误差,数越大速度越慢,误差越小速度越慢
            display.fill_rect(120,120,10,10,att.black)
            width += y
            height += x
            display.fill_rect(clamp(120+width),clamp(120+height),10,10,att.white)
            print(clamp(120+width),clamp(120+height))
            time.sleep(0.01)
            display.fill_rect(clamp(120+width-y),clamp(120+height-x),10,10,att.black)
            mouse.move(y*clamp1(mouse_speed),x*clamp1(mouse_speed))#移动鼠标
            display.text (att.font8,'{}   X:{:d}   Y:{:d}   S:{:<5d}'.format('PC-MOUSE',clamp(width),clamp(height),clamp1(mouse_speed)),0,0,att.white,att.background)
        if buttonA.value() == 0:#判断按钮信号
            mouse.press(mouse.BUTTON_RIGHT)#右键按下
        else: 
            mouse.release(mouse.BUTTON_RIGHT)#右键松开
        if buttonB.value() == 0:
            mouse.press(mouse.BUTTON_LEFT)#左键按下
        else: 
            mouse.release(mouse.BUTTON_LEFT)#左键松开
#         if clamp(120+width)clamp(120+height)
        if 160>clamp(120+width)>120 and 220>clamp(120+height)>190:
            while True:
                if not buttonB.value():
                    mouse_speed -= 1
                    time.sleep(0.1)
                if int(xAxis.read_u16()/3000)-10 or int(yAxis.read_u16()/3000)-11:
                    break
                time.sleep(0.01)
        if 220>clamp(120+width)>180 and 220>clamp(120+height)>190:
            while True:
                if not buttonB.value():
                    mouse_speed += 1
                    time.sleep(0.1)
                if int(xAxis.read_u16()/3000)-10 or int(yAxis.read_u16()/3000)-11:
                    break
                time.sleep(0.01)
        if not buttonSelect.value():
            display.fill(att.background)
            display.text(att.font16,'Do you want to ',10,20,att.white,att.background)#start键按下
            display.text(att.font16,'continue?',10,52,att.white,att.background)
            display.text(att.font16,'yes and no?',28,140,att.white,att.background)
            display.line(30,180,70,180,att.white)
            while True:
                while int(yAxis.read_u16()) < 40000:#左边
                    display.line(30,180,70,180,att.white)
                    time.sleep(0.01)
                    display.line(30,180,70,180,att.background)
                    time.sleep(0.01)
                    if buttonB.value() == 0:
                        pc_mouse()
                while int(yAxis.read_u16()) > 1000:#右边
                    display.line(160,180,185,180,att.white)
                    time.sleep(0.01)
                    display.line(160,180,185,180,att.background)
                    time.sleep(0.01)
                    if buttonB.value() == 0:
                        menu()
        time.sleep(0.01)
  • Pi Pico LCD箭头控制,读取摇杆xy轴处理后控制lcd箭头位移,利用约束函数控制鼠标不会超出屏幕,select按钮暂停,摇杆左右控制yes和no并用按钮b确认
def pico_mouse(x=0,y=0):#pico箭头控制
    global width,height
    clamp = lambda change: min(98, max(-120, change))
    display.fill(0)
    while True:
        x,y =int(xAxis.read_u16()/3000)-10,int(yAxis.read_u16()/3000)-11#处理控制杆数值
        if x or y:
            arrow_clear()
            width +=  y
            height +=  x
            mouse_arrow(clamp(width),clamp(height))#移动鼠标
            arrow_clear(clamp(width-y),clamp(height-x))#清理鼠标
        time.sleep(0.01)
        print (pico_mouse,clamp(width),clamp(height))
        display.text (att.font8,'{}   X:{:d}   Y:{:<10d}'.format('PICO-MOUSE',clamp(width),clamp(height)),0,0,att.white,att.background)
        if not buttonSelect.value():
            display.fill(att.background)
            display.text(att.font16,'Do you want to ',10,20,att.white,att.background)#start键按下
            display.text(att.font16,'continue?',10,52,att.white,att.background)
            display.text(att.font16,'yes and no?',28,140,att.white,att.background)
            display.line(30,180,70,180,att.white)
            while True:
                while int(yAxis.read_u16()) < 40000:#左边
                    display.line(30,180,70,180,att.white)
                    time.sleep(0.01)
                    display.line(30,180,70,180,att.background)
                    time.sleep(0.01)
                    if buttonB.value() == 0:
                        pico_mouse()
                while int(yAxis.read_u16()) > 1000:#右边
                    display.line(160,180,185,180,att.white)
                    time.sleep(0.01)
                    display.line(160,180,185,180,att.background)
                    time.sleep(0.01)
                    if buttonB.value() == 0:
                        menu()

遇到的问题和办法

1.如何刷固件

电脑连结板卡USB Type,闭合按钮B,通电后将UF2固件复制进入板卡,板卡将自动重启证明成功

2.开始没有找到可用库浪费了些时间

    GitHub - picospuch/eetree-mpy-lecture-code

https://gitee.com/eetree-git/RP2040_Game_Kit

3.固件中的库不知道去哪里查看?

不知道有多少库,st7789、st7789c、gxf、breakout_colourlcd240x240感觉重复并且各自功能不清晰,然 后也不知道库里怎么编写的

4.代码臃肿,目前代码还比较臃肿,很多代码重复出现,如返回功能等

5.在lcd打字就会造成延迟提升,如,打字前移动平稳,打字后移动缓慢还有卡顿

6.有些库中的方法不知道怎么调用,只能退而求次的使用替代方法

7.画出来的箭头在移动时会出现像素丢失现象,如移动后箭头没有了一条边

计划和建议

  • 计划精炼代码,将重复代码进行封装后调用
  • 计划实现水平仪功能和开发蜂鸣器的交互性能
  • 计划实现setting功能,可以在setting中调整背景颜色、字体大小、声音大小等参数
  • 计划开发更多硬件功能
  • 建议将固件当中的库代码也发出来,不然真的有些看不懂,help()到的方法完全不知道怎么用,需要什么 参数
  • 有些方法无法使用或者不明确用法,建议将用法备注
附件下载
pipico_RP2040_R1.7z
团队介绍
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号