大家好久不见,2022年开始了,大家有没有设定今年要完成的小目标呢?
2022年寒假在家一起练于2022年2月27日截止了,看到同学们提交的项目后,老师们倍感欣慰。同学们的项目都非常优秀,你们抓住了寒假的时光,为2021年的自己画了一个句号,给2022年的自己一个特别的开始。
同学们提交的项目还在陆续审核中,预计本周结束,下周开始邮件告知审核结果。大家耐心等待哦。
今天我们来欣赏一位来自华北电力大学的【xiaoyu555】同学所做的“鼠标”。
1
项目介绍
2
实现的功能
3
设计思路
4
实现的过程
orange=0xfd20
xAxis = ADC(Pin(29)) #x轴
yAxis = ADC(Pin(28)) #Y轴
Bbutton = Pin(5,Pin.IN, Pin.PULL_UP) #B按键
Abutton = Pin(6,Pin.IN, Pin.PULL_UP) #A按键
buttonStart = Pin(7,Pin.IN, Pin.PULL_UP)#START按键
#调用ST7789C来驱动LCD屏幕
spi0=machine.SPI(0,baudrate=4000000, phase=1, polarity=1,sck=machine.Pin(game_kit.lcd_sck, machine.Pin.OUT),
mosi=machine.Pin(game_kit.lcd_sda, machine.Pin.OUT))
print(spi0)
display = st7789c.ST7789(spi0, 240, 240,
reset=machine.Pin(game_kit.lcd_rst, machine.Pin.OUT),
dc=machine.Pin(game_kit.lcd_dc, machine.Pin.OUT),
rotation=0)#实例化了一个ST7789
display.init() #st7789初始化
display.fill(st7789c.WHITE)
#设置边界
width =240
height=240
#rp2040鼠标定义
class rpMouse():
'''
Poly class to keep track of a polygon based sprite
'''
#初始化
def __init__(
self,
# list (x,y) tuples of convex polygon, must be closed
polygon,
x=None, # 鼠标X坐标
y=None, # 鼠标Y坐标
v_x=None, # X轴的移动速度
v_y=None, # Y轴的移动速度
angle=None, # 鼠标图案的移动速度
max_velocity=25, # 鼠标图案移动的最大速度
min_velocity=10 # 鼠标图案移动的最小速度
): #这边是传入的参数,对其进行一个初始化赋值
self.polygon = polygon #赋值元组
# 如果没有初始化起始位置便随便给个位置
self.x = random.randint(0, width) if x is None else x
self.y = random.randint(0, width) if y is None else y
# 如果角度有给就设置
self.angle = float(0) if angle is None else angle
# 除非有给速度参数否则随便给一个
self.velocity_x = random.uniform(
0.50, 0.99)*6-3 + 0.75 if v_x is None else v_x
self.velocity_y = random.uniform(
0.50, 0.99)*6-3 + 0.75 if v_y is None else v_y
self.max_velocity = max_velocity #设置最大值
self.min_velocity = min_velocity #设置最小值
#移动
def moveX(self,moveflag):
self.draw(st7789c.WHITE) #使旧的鼠标图案融于背景色,达到消失的效果
if(moveflag==1) :#向左
self.x -= int(self.velocity_x*0.2) #每次以速度移动
if(self.x<0): #如果到最底端,就更新位置到最上端
self.x=240
elif(moveflag==2) : #向右
self.x += int(self.velocity_x*0.2) #每次以速度移动
self.x %= width #不会超过边界
self.draw(orange) #使之移动
def moveY(self,moveflag):
self.draw(st7789c.WHITE)
if moveflag==1:#向上
self.y -= int(self.velocity_y*0.2) #每次以速度移动,乘上倍数,看起来流畅
if(self.y<=0):
self.y=240
if moveflag==2:
self.y += int(self.velocity_y*0.2) #每次以速度移动,乘上倍数,看起来流畅
self.y %= height
self.draw(orange) #使之移动
#画鼠标
def draw(self, color):
display.polygon(self.polygon, self.x, self.y, color, self.angle, 0, 0)
#更新鼠标的移动速度
def update(self,vflag): #1为加速,2为减速
if vflag==2 :
self.velocity_x -= 1
self.velocity_y -= 1
elif vflag==1:
self.velocity_x += 1
self.velocity_y += 1
if self.velocity_x > self.max_velocity: #使速度不超过最大值
self.velocity_x = self.max_velocity
elif self.velocity_x < self.min_velocity:
self.velocity_x = self.min_velocity
#定义一个rp2040鼠标
mouse_poly=[(-7,-7),(7,0),(-7,7),(-3,0),(-7,-7)] #鼠标图像元组
mouse =rpMouse(mouse_poly,x=120,y=120,v_x=15,v_y=15,angle=180.0) #类对象
mouse.draw(orange)
#初始化
def __init__(
self,
# list (x,y) tuples of convex polygon, must be closed
polygon,
x=None, # 鼠标X坐标
y=None, # 鼠标Y坐标
v_x=None, # X轴的移动速度
v_y=None, # Y轴的移动速度
angle=None, # 鼠标图案的移动速度
max_velocity=25, # 鼠标图案移动的最大速度
min_velocity=10 # 鼠标图案移动的最小速度
): #这边是传入的参数,对其进行一个初始化赋值
self.polygon = polygon #赋值元组
# 如果没有初始化起始位置便随便给个位置
self.x = random.randint(0, width) if x is None else x
self.y = random.randint(0, width) if y is None else y
# 如果角度有给就设置
self.angle = float(0) if angle is None else angle
# 除非有给速度参数否则随便给一个
self.velocity_x = random.uniform(
0.50, 0.99)*6-3 + 0.75 if v_x is None else v_x
self.velocity_y = random.uniform(
0.50, 0.99)*6-3 + 0.75 if v_y is None else v_y
self.max_velocity = max_velocity #设置最大值
self.min_velocity = min_velocity #设置最小值
解释:
#画鼠标
def draw(self, color):
display.polygon(self.polygon, self.x, self.y, color, self.angle, 0, 0)
每次绘制时只需要传入想要的鼠标的颜色,然后进行绘制就行。
#移动
def moveX(self,moveflag):
self.draw(st7789c.WHITE) #使旧的鼠标图案融于背景色,达到消失的效果
if(moveflag==1) :#向左
self.x -= int(self.velocity_x*0.2) #每次以速度移动
if(self.x<0): #如果到最底端,就更新位置到最上端
self.x=240
elif(moveflag==2) : #向右
self.x += int(self.velocity_x*0.2) #每次以速度移动
self.x %= width #不会超过边界
self.draw(orange) #使之移动
def moveY(self,moveflag):
self.draw(st7789c.WHITE)
if moveflag==1:#向上
self.y -= int(self.velocity_y*0.2) #每次以速度移动,乘上倍数,看起来流畅
if(self.y<=0):
self.y=240
if moveflag==2:
self.y += int(self.velocity_y*0.2) #每次以速度移动,乘上倍数,看起来流畅
self.y %= height
self.draw(orange) #使之移动
#定时器检索按键,并且给显示对应画面
def timercb(n):
global rporcomflag #判断是操控rp2040的鼠标还是PC屏幕的光标,0为RP2040的,1是PC屏幕光标
global faceflag #判断是进入初始页面还是其他页面的变量
if(Bbutton.value()==0 and rporcomflag==1): #相当于电脑鼠标左键按下
hid_mouse.press(hid_mouse.BUTTON_LEFT)
if(Bbutton.value()==1 and rporcomflag==1): #相当于电脑鼠标左键松开
hid_mouse.release(hid_mouse.BUTTON_LEFT)
if(Abutton.value()==0 and rporcomflag==1): #相当于电脑右键按下一次
hid_mouse.click(hid_mouse.BUTTON_RIGHT)
if(Bbutton.value()==0 and rporcomflag==0): #如果是rp2040按下B键,为确定键
if(mouse.y>70 and mouse.y<98 and mouse.x>=84 and mouse.x<=163): #移动到冰墩墩的位置
faceflag=1 #冰墩墩
elif(mouse.y>98 and mouse.y<128 and mouse.x>=84 and mouse.x<=163):
faceflag=2 #TEXT
elif(mouse.y>220 and mouse.y<240 and mouse.x>=110 and mouse.x<=240):
mouse.update(1) #更新鼠标的速度
utime.sleep(0.05)
elif(mouse.y>220 and mouse.y<240 and mouse.x>=0 and mouse.x<=100):
mouse.update(2) #更新鼠标的速度
utime.sleep(0.05)
tim=Timer(period=100, mode=Timer.PERIODIC, callback=lambda t:timercb(1))
利用定时器不断地扫描按键,减少主循环中对摇杆判断的影响。
利用rporcomflag来判断是操控哪个,从而判断B,A键按下时的效果。
当操控RP2040鼠标图案时,判断鼠标位置,从而当B键按下时,进入不同的页面。
#定义hid鼠标
hid_mouse=Mouse()
rporcomflag=0
enterflag=0 #每次进入图像后置1,不让再次刷新图像,返回后再置0,使得下一次得以进入图像。
#这样子可以避免影响返回键A的判断
while True:
if (rporcomflag==1): #1为电脑鼠标控制
xValue = xAxis.read_u16() #读取摇杆位移
yValue = yAxis.read_u16()
if buttonStart.value()==0: #当按下START时,使rporcomflag置0
rporcomflag-=1
utime.sleep(0.2)
if xValue <=600: #当摇杆向左
hid_mouse.move(-1,0) #进行对应的位移
elif xValue >= 60000: #当摇杆向右
hid_mouse.move(1,0)
if yValue <= 600: #当摇杆向上
hid_mouse.move(0,-1)
elif yValue >= 60000: #当摇杆向下
hid_mouse.move(0,1)
elif rporcomflag==0 and faceflag==0: #0为rp2040鼠标控制
xValue = xAxis.read_u16()
yValue = yAxis.read_u16()
if buttonStart.value()==0:
rporcomflag+=1
utime.sleep(0.2)
if xValue <= 600:#左
mouse.moveX(1)
utime.sleep(0.00835)
elif xValue >= 60000:
mouse.moveX(2)
utime.sleep(0.0083)
if yValue <= 600:
mouse.moveY(1)
utime.sleep(0.0083)
elif yValue >= 60000:
mouse.moveY(2)
utime.sleep(0.0083)
interface1() #每次移动后要再进行一次页面的刷新,防止鼠标图像清空时使背景色消失
mouse.draw(orange)
if(Abutton.value()==0 and rporcomflag==0):#返回操作
display.fill(st7789c.WHITE)
interface1()
faceflag=0
enterflag=0
elif(faceflag==1 and enterflag==0): # 冰墩墩界面
display.jpg("bingdundun.jpg", 0, 0, st7789c.SLOW)
enterflag=1 #每次进入图像后置1,不让再次刷新图像,返回后再置0,使得下一次得以进入图像。
#这样子可以避免影响返回键A的判断
elif(faceflag==2 and enterflag==0): #text界面
display.jpg("text.jpg", 0, 0, st7789c.SLOW)
enterflag=1
5
遇到的难题和解决方法
if(Abutton.value()==0 and rporcomflag==0):
display.fill(st7789c.WHITE)
interface1()
faceflag=0
elif(faceflag==1): # 冰墩墩界面
display.jpg("bingdundun.jpg", 0, 0, st7789c.SLOW)
解决方法:定义一个变量,当进入一次界面后,便将其置1,并且只有当其为0时才能再次进入这个界面,这时就能控制其进入一次,并且,当按下返回键时,就会将该变量重新置为0,变成可进入的状态,从而解决问题。
if(Abutton.value()==0 and rporcomflag==0):
display.fill(st7789c.WHITE)
interface1()
faceflag=0
enterflag=0
elif(faceflag==1 and enterflag==0): # 冰墩墩界面
display.jpg("bingdundun.jpg", 0, 0, st7789c.SLOW)
enterflag=1 #每次进入图像后置1,不让再次刷新图像,返回后再置0,使得下一次得以进入图像。
#这样子可以避免影响返回键A的判断
6
成品展示
7
资料获取
电子森林链接:https://www.eetree.cn/project/detail/912
百度网盘链接:https://pan.baidu.com/s/1w96ahikxAOgv7YJZrb5abQ?pwd=0000 提取码:0000
END
硬禾学堂
硬禾团队一直致力于给电子工程师和相关专业的同学,带来规范的核心技能课程,帮助大家在学习和工作的各个阶段,都能有效地提升自己的职业能力。
硬禾学堂
我们一起在电子领域探索前进
关注硬禾公众号,随时直达课堂
点击阅读原文查看更多