总结报告
1 项目介绍
本次活动我做的项目是实现能控制LCD和电脑界面的“鼠标”。具体目标是利用板上的四向摇杆和按键设计一款“鼠标”,要求在240*240的LCD屏幕内可以通过该鼠标进行菜单选择和参数控制(在屏幕上要有图形化的箭头形状),并且通过USB端口可以控制PC屏幕上的光标移动和点击操作,行使电脑鼠标的功能。
2 设计思路
3 硬件介绍
3.1 总体介绍
硬件部分的元器件包括RP2040、MMA7660重力感应传感器、XT3406AFMR CMOS降压DC/DC调整器、FJ08K-N游戏摇杆电位计、Buzzer-蜂鸣器、VSMB10940高速红外发射二极管、IRM-H638T红外线接收头、双排16Pin连接器和240*240分辨率的彩色IPS LCD等。本项目用到的元器件包括RP2040、FJ08K-N游戏摇杆电位计和240*240分辨率的彩色IPS LCD等。
3.2 树莓派Pico核心芯片RP2040简介
树莓派基金会推出的双核Arm Cortex M0+微控制器,时钟速率133MHz,264KB SRAM,性能强大、高度灵活的可编程IO可用于高速数字接口,片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度,支持MicroPython、C、C++编程。
4 实现的功能及图片展示
4.1 控制电脑鼠标
本项目通过MicroPython编程实现了通过USB端口控制PC屏幕上的光标移动和点击操作。具体介绍如下:
将板子与电脑连接,打开板子开关。电脑用Thonny打开文件mouse.py,点击运行,此时板子的LCD屏幕上显示文本“MOUSE MODE”,表示已经进入鼠标模式,即通过USB端口控制了PC屏幕上的光标。
拖动板子上的四向摇杆,可以实现PC屏幕上光标的相应移动。
按照对应方向,板子上的B按键对应设置为鼠标的左键,板子上的A按键对应设置为鼠标的右键,按下对应按键可以实现点击鼠标对应按键的功能。
4.2 LCD界面模拟鼠标
本项目通过MicroPython编程实现了在240*240的LCD屏幕内通过所设计的鼠标进行相应的菜单选择和参数控制操作。具体介绍如下:
将板子与电脑连接,打开板子开关。电脑用Thonny打开文件,点击运行,此时板子的LCD屏幕上显示文本“MOUSE MODE”,表示已经进入鼠标模式。此时同时按下板子上的A按键和B按键保持3秒后,板子的LCD屏幕上显示文本“LCD MODE”、光标、“Mouse speed”设置界面和“EXIT”按钮,表示已经进入LCD模式,即实现了LCD界面上的模拟鼠标。
拖动板子上的四向摇杆,可以实现LCD屏幕上光标的相应移动。
按照对应方向,板子上的B按键对应设置为鼠标的左键,按下B按键可以实现点击鼠标左键的功能。
“Mouse speed”设置界面由文本、控制按钮“+”、控制按钮“-”和当前速度指示条组成,通过此界面可以实现对鼠标模式下电脑光标的移动速度进行三个档位的控制。单击“-”按钮,设置鼠标模式下的光标速度变慢,LCD屏显示的速度条变短,每次改变总长度的三分之一,最低到整个条的三分之一处,对应为最低速度,此时再次单击“-”按钮无效;单击“+”按钮,设置鼠标模式下的光标速度变快,LCD屏显示的速度条变长,每次改变总长度的三分之一,最多显示整个速度条,对应为最高速度,此时再次单击“+”按钮无效。
单击“EXIT”按钮,板子的LCD屏幕上显示文本“MOUSE MODE”,表示退出LCD模式,重新进入鼠标模式。以上两种模式可以通过上述方法相互切换。
5 主要代码片段及说明
xValue = xAxis.read_u16()
yValue = yAxis.read_u16()
ax[i % 4] = xValue
ay[i % 4] = yValue
i += 1
sum = 0
for k in ax:
sum += k
xave = sum / 4
sum = 0
for k in ay:
sum += k
yave = sum / 4
利用滑动平均滤波算法,对所采集摇杆数据进行滤波,从而达到使所采集摇杆数据更加稳定的效果。具体原理是采用队列方式,将所采集的数据按照顺序放入有限元素的队列ax、ay,当采集到一个新数据时,将队列里面的最老的数据替换掉,每次计算队列里面数据的平均值xave、yave作为所采集的数据的校正值。
x = y = 0
y = (xave - 33280) / 3240
x = (yave - 34180) / 3250
将采集的坐标数据xave和yave转化为位移数据x和y,在某一方向上取数据的最大值与原点平均值差值的十分之一为区间,即将上下左右每个方向划分为十个区间,将每次采集到的数据等比例缩小为0到10之间的数值,作为每一次光标坐标的位移值。
while buttonB.value() == 0:
if LCDx > 15 and LCDx < 41 and LCDy > 147 and LCDy < 173:
display.fill_rect(15, 147, 26, 26, WHITE)
while True:
if buttonB.value() != 0:
display.fill_rect(16, 148, 24, 24, BLACK)
display.text(font1, "-", 24, 156)
if t >= 0.1:
break
else:
t = t*100
p = p-1
break
elif LCDx > 199 and LCDx < 225 and LCDy > 147 and LCDy < 173:
display.fill_rect(199, 147, 26, 26, WHITE)
while True:
if buttonB.value() != 0:
display.fill_rect(200, 148, 24, 24, BLACK)
display.text(font1, "+", 208, 156)
if t < 0.0001:
break
else:
t = t/100
p = p+1
break
else:
break
此段代码规定在LCD模式下鼠标的单击操作,当B键按下时,首先判断光标坐标所位于的区域,再执行相应的操作。当单击界面上显示的按钮时,对应按钮会全白覆盖指示按键已按下,当按键松开时恢复原状并执行相应操作。通过while循环实现LCD界面的实时变化和参数的实时修改。
6 遇到的主要难题及解决方法
6.1 Mouse和LCD模式下光标移动问题
由于move函数的参数为下一坐标值与当前坐标值的差值,故所采集的数据校正值不能直接使用。而经过滤波后,所采集坐标数据的变化虽然更加平稳,但仍不能保证绝对平稳。因此,如果直接使用两次坐标值的差值作为每一次的位移值,依然会不稳定且产生位移过大的情况。所以,在某一方向上取数据的最大值与原点平均值差值的十分之一为区间,即将上下左右每个方向划分为十个区间,将每次采集到的数据等比例缩小为0到10之间的数值,取整后即可解决这些问题,并且在方向上也能实现较为流畅的变化。
6.2 LCD模式下光标移动时的显示问题
由于在本代码中LCD模式下光标显示是通过line函数绘制的,因此在控制光标进行移动时,会在界面上留下上一次的光标印记。开始时通过使用fill_rect函数以背景色黑色覆盖光标,但是发现当背景有其他显示时,也会一同将其覆盖掉。因此最后采用了在每次循环开始时在相同位置以背景色黑色重新绘制一个光标,以最小程度覆盖掉上一次循环时的光标。而界面上的其他显示也因为while循环而重复绘制,所以光标不会对其产生影响。
6.3 LCD模式下速度条的显示问题
在程序编写过程中,出现了速度条不能随速度值的改变而动态显示的情况。开始的思路是在进入LCD模式时,根据if条件语句判断当前速度值,从而在速度条上显示对应速度值的长度。但是经过测试,若采用这种写法,当速度值改变后便无法经过if条件判断,所以并不能实现速度条即时的变化。因此,最终采用的思路是设置速度指示变量p,在每一次对速度调节按钮执行单击操作时,改变p的值,而统一在循环开始时显示以含p表达式作为长度参数的速度条,即得到解决。
7 未来的计划或建议等
假期活动较多,所以利用在这里时间较为有限和紧凑,加之初次接触对嵌入式系统的编程,因此对于一些细节性、系统性和概念性的东西没有理解完全,因此我希望在以后能够有机会对嵌入式系统编程方面进行更加系统和精细的学习,用这块板子实现更多的功能。