2022寒假在家练+树莓派RP2040板+俞卓晨
项目介绍:
本项目是以树莓派RP2040嵌入式平台为基础,通过寒假的学习和实践,最终采用micropython对其进行程序编写,实现能控制LCD和电脑界面的“鼠标”。
本项目耗时一周,无额外器械,最终以178行代码和一个BIN文件实现所需功能。
本项目实现需要的设备:树莓派RP2040板、usb线、电脑
本项目实现的鼠标共有3种模式。
通过usb线将树莓派RP2040板和电脑相连后,即开始使用。
首先是开机菜单及指南,然后进入标准模式,在标准模式下,共有鼠标以标准速度移动,左键,右键的功能,并能够实现多键并用来实现真正鼠标的功能。
用户可通过select键进行模式切换,在快速模式下,用户可以将鼠标快速移动,并依然有左键,右键的功能,并能够多键并用来实现真正鼠标的功能。
在滚轮模式下,用户可通过机器实现对电脑滚轮的上下控制。
3种模式均可以通过select键无限切换。
3种模式下在lcd屏幕上均有模式指南和箭头形状鼠标的显示。
设计思路:
主要通过遥杆,A,B键和select实现交互。
LCD屏幕显示内容提升鼠标功能
通过各按键的电位变化来实现功能控制。
设计思路流程图如下:
硬件介绍:
RP2040 芯片
RP2040 芯片由树莓派自己设计开发,采用 40 nm 制程工艺,7×7 mm QFN-56 封装。RP2040 的设计思想基于多年来树莓派产品和项目中使用的其他供应商设备的优缺点。它主要具备以下 3 个方面的关键优势:
两个快速 CPU 内核。RP2040 具有 一对 ARM Cortex-M0+ 内核,时钟频率为 133 MHz,提供充足的整数性能。用户可以使用一个内核运行应用程序代码,另一个内核监督硬件;也可以使用 FreeRTOS 或 MicroPython 在两个内核上运行应用程序代码。
大量的 RAM。RP2040 拥有 264KB 的 RAM,这使得用户可以专注于实现功能,无需花费时间和精力优化应用程序的大小。其中,一个完全连接的交换机将 ARM 内核和 DMA 引擎连接到六个独立的 RAM 组,使得用户可以充分利用系统的性能。
灵活的 I/O。RP2040 提供所有常用接口:硬件 UART、SPI 和 I2C 控制器、USB 1.1 和四通道 ADC。而可编程 I/O (PIO) 子系统使 RP2040 脱颖而出,支持包括 SDIO、DPI、I2S,甚至 DVI-D 在内的软件实现协议。
所有这些都被封装在一块 2 平方毫米的 40 nm 制程芯片中。
作为一个嵌入式系统的学习平台,首先要基于核心芯片的核心板的特点以及嵌入式系统的关键知识点来定义这款学习平台:
采用树莓派Pico核心芯片RP2040:
双核Arm Cortex M0+内核,可以运行到133MHz
264KB内存
性能强大、高度灵活的可编程IO可用于高速数字接口
片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度
支持MicroPython、C、C++编程
板上功能:
240*240分辨率的彩色IPS LCD,SPI接口,控制器为ST7789
四向摇杆 + 2个轻触按键 + 一个三轴姿态传感器MMA7660用做输入控制
板上外扩2MB Flash,预刷MicroPython的UF2固件
一个红外接收管 + 一个红外发射管
一个三轴姿态传感器MMA7660
一个蜂鸣器
双排16Pin连接器,有SPI、I2C以及2路模拟信号输入
可以使用MicroPython、C、C++编程
USB Type C连接器用于供电、程序下载
实现的功能:
开机菜单及指南
在标准模式下,共有鼠标以标准速度移动,左键,右键的功能,并能够实现多键并用来实现真正鼠标的功能。
在快速模式下,用户可以将鼠标快速移动,并依然有左键,右键的功能,并能够多键并用来实现真正鼠标的功能。
在滚轮模式下,用户可通过机器实现对电脑滚轮的上下控制。
3种模式均可以通过select键无限切换。
3种模式下在lcd屏幕上均有模式指南和箭头形状鼠标的显示。
图片展示:
主要代码:
import usb_hid, uos, utime, time
import st7789 as st7789
from hid import Mouse
from machine import Pin, ADC, PWM
from fonts import vga1_16x32 as font1
from fonts import vga2_8x8 as font2
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)
print(spi0)
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)
#一些初始化
display.fill(st7789.BLACK)
display.text(font1, "standard", 2,38, st7789.WHITE, st7789.BLACK)
display.text(font1, "roller", 2, 88, st7789.WHITE, st7789.BLACK)
display.text(font1, "fast", 2, 138, st7789.WHITE, st7789.BLACK)
display.text(font1, "press select", 2,188, st7789.RED, st7789.BLACK)
#菜单界面
utime.sleep(4)
display.fill(st7789.BLACK)
display.text(font1, "stardard", 2,38, st7789.GREEN, st7789.BLACK)
image = "3.bin"
#导入鼠标文件
xAxis = ADC(Pin(28))
yAxis = ADC(Pin(29))
buttonB = Pin(5, Pin.IN, Pin.PULL_UP)
buttonA = Pin(6, Pin.IN, Pin.PULL_UP)
buttonStart = Pin(7, Pin.IN, Pin.PULL_UP)
buttonSelect = Pin(8, Pin.IN, Pin.PULL_UP)
m = Mouse()
#调用鼠标
while True:
#第一层循环
xValue = xAxis.read_u16()
yValue = yAxis.read_u16()
x=y=0
if xValue<15000:
y = -20
elif xValue>45000:
y = +20
elif yValue < 15000:
x = -20
elif yValue > 45000:
x = +20
#遥杆操控鼠标数据判别
m.move(x,y)
mouse_image = open(image, 'rb')
for column in range(y+0,y+21):
buf = mouse_image.read(30)
display.blit_buffer(buf, 110+x,120+column, 15, 1)
utime.sleep(0.1)
display.fill_rect(110+x,120+y,30,30,st7789.BLACK)
#图形化鼠标移动和清除
buttonValueA = buttonA.value()
buttonValueB = buttonB.value()
if buttonValueB==0:
m.press(m.BUTTON_LEFT)
elif buttonValueB==1:
m.release(m.BUTTON_LEFT)
if buttonValueA==0:
m.press(m.BUTTON_RIGHT)
elif buttonValueA==1:
m.release(m.BUTTON_RIGHT)
#按键判别
buttonValueSelect = buttonSelect.value()
if buttonValueSelect==0:
display.fill(st7789.BLACK)
display.text(font1, "roller", 2, 38, st7789.GREEN, st7789.BLACK)
#模式切换判别,进入滚轮模式
image = "3.bin"
duty = 0
direction = 1
while True:
#第二层循环,滚轮模式
buttonValueStart = buttonStart.value()
xValue = xAxis.read_u16()
yValue = yAxis.read_u16()
v=h=0
if xValue<1000:
v = +10
elif xValue>60000:
v = -10
elif yValue<1000:
h = -10
elif yValue>65000:
h = +10
#遥杆操控滚轮数据判别
m.move(0,0,v,h)
mouse_image = open(image, 'rb')
for column in range(v+0,v+21):
buf = mouse_image.read(30)
display.blit_buffer(buf, 110+h,120+column, 15, 1)
utime.sleep(0.1)
display.fill_rect(110+h,120+v,30,30,st7789.BLACK)
#图形化鼠标移动和清除
buttonValueSelect = buttonSelect.value()
if buttonValueSelect==0:
break
#跳出循环进入快速模式
if buttonValueSelect==0:
display.fill(st7789.BLACK)
display.text(font1, "fast", 13, 35, st7789.GREEN, st7789.BLACK)
#模式切换判别
while True:
#第三层循环,快速模式
xValue = xAxis.read_u16()
yValue = yAxis.read_u16()
x=y=0
if xValue<15000:
y = -40
elif xValue>45000:
y = +40
elif yValue<15000:
x = -40
elif yValue>45000:
x = +40
#遥杆操控滚轮数据判别
m.move(x,y)
mouse_image = open(image, 'rb')
for column in range(y+0,y+21):
buf = mouse_image.read(30)
display.blit_buffer(buf, 110+x,120+column, 15, 1)
utime.sleep(0.1)
display.fill_rect(110+x,120+y,30,30,st7789.BLACK)
#图形化鼠标移动和清除
buttonValueA = buttonA.value()
buttonValueB = buttonB.value()
if buttonValueB==0:
m.press(m.BUTTON_LEFT)
elif buttonValueB==1:
m.release(m.BUTTON_LEFT)
if buttonValueA==0:
m.press(m.BUTTON_RIGHT)
elif buttonValueA==1:
m.release(m.BUTTON_RIGHT)
#按键判别
buttonValueSelect = buttonSelect.value()
if buttonValueSelect==0:
display.fill(st7789.BLACK)
display.text(font1, "stardard", 13, 35, st7789.GREEN, st7789.BLACK)
utime.sleep(0.1)
break
#跳出循环回到标准模式
遇到的主要难题及解决方法:
在箭头鼠标图形化显示时,一开始一直是乱码且移动会覆盖背景。
最后采用for循环显示图片和背景清除的方式实现鼠标图形的正常移动。
未来的计划或建议:
未来的计划是能够在这个机器上实现更多的功能,将其他项目也做了,挑战自己。
建议是希望在教程上能够更详细,因为自己在做的过程中有时候走了弯路,陷入了不必要的折磨,也希望这样的活动能够更多一些。