1.任务要求
按照硬核学堂要求,需要在LCD屏上设计一款水平仪,通过一个滚动的小球或气泡,来显示当前板子的倾斜度,当板子处于水平位置的时候,小球停在屏幕的正中间,倾斜板子,小球偏移,并能够显示偏移的角度(二维信息)
以上要求基本都已满足。
2.环境配置
试用的固件为
lecture · EETree-git/RP2040_Game_Kit - 码云 - 开源中国 (gitee.com)里面的固件
这个固件自带了一个ST7789的显示库,本项目就基于这个显示库完成图形开发,只要按住B键将固件拖进去就好了
用于开发的IDE是本次课程推荐的IDE,thonny
3.硬件系统
本例只是用了MMA7660和ST7789显示屏部分,所以只截图了相关的电路,可以看到MMA7660通过IIC总线挂载在RP2040上面,SDA SCL分别是IO10和IO11,ST7789的IO:RST、DC、SCK、SDA则分别挂载在IO2、3、4、5几个IO上,由于固件自带ST7789专用驱动,所以只需要了解ST7789的IO即可。
4.程序实现
二话不说,先上流程图和代码,稍后讲解
import time
import random
from breakout_colourlcd240x240 import BreakoutColourLCD240x240
from machine import Pin, I2C
import vga2_8x8
import vga1_16x32
width = BreakoutColourLCD240x240.WIDTH
height = BreakoutColourLCD240x240.HEIGHT
display_buffer = bytearray(width * height * 2) # 2-bytes per pixel (RGB565)
display = BreakoutColourLCD240x240(display_buffer)
display.set_backlight(1.0)
i2c = I2C(1, scl=Pin(11), sda=Pin(10), freq=400_000)
i2c.writeto_mem(76, 0x07, '\x01')
time.sleep(0.21)
class Ball:
def __init__(self, x, y, r, dx, dy, pen):
self.x = x
self.y = y
self.r = r
self.dx = dx
self.dy = dy
self.pen = pen
def write8x8(char,x,y):
char=char*8
display.set_pen(255,255,255)
for i in range(8):
a=vga2_8x8.FONT[char+i]
for c in range(8):
d=[128,64,32,16,8,4,2,1]
if a&d[c]==d[c]:
display.pixel(x+c,y+i)
def write16x32(char,x,y):
char=(char-0x20)*64
display.set_pen(255,255,255)
for i in range(32):
a=vga1_16x32.FONT[char+i*2]
for c in range(8):
d=[128,64,32,16,8,4,2,1]
if a&d[c]==d[c]:
display.pixel(x+c,y+i)
a=vga1_16x32.FONT[char+i*2+1]
for c in range(8):
d=[128,64,32,16,8,4,2,1]
if a&d[c]==d[c]:
display.pixel(x+8+c,y+i)
balls = []
for i in range(0, 25):
r = random.randint(0, 10) + 3
balls.append(
Ball(
random.randint(r, r + (width - 2 * r)),
random.randint(r, r + (height - 2 * r)),
r,
(14 - r) / 2,
(14 - r) / 2,
display.create_pen(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)),
)
)
currentx=[]
currenty=[]
sumx=0
sumy=0
a=0
while True:
mma=i2c.readfrom(76, 4)
if mma[0]>31:
x=abs(mma[0]-63)*-1
else:
x=mma[0]
if mma[1]>31:
y=abs(mma[1]-63)*-1
else:
y=mma[1]
if mma[2]>31:
z=abs(mma[2]-63)*-1
else:
z=mma[2]
'''print('x=')
print(x)
print('y=')
print(y)'''
if a<14:
a+=1
currentx.append(x)
currenty.append(y)
else:
currentx.append(x)
currenty.append(y)
currentx.pop(0)
currenty.pop(0)
for i in currentx:
sumx+=i
for z in currenty:
sumy+=z
nowx=sumx/14
nowy=sumy/14
sumx=0
sumy=0
display.set_pen(0,255,0)
display.clear()
display.set_pen(250,0,250)
display.circle(120, 120, 120)
display.set_pen(0,255,0)
display.circle(120, 120, 118)
display.set_pen(250,0,250)
display.circle(120, 120, 60)
display.set_pen(0,255,0)
display.circle(120, 120, 58)
display.set_pen(0,255,250)
#display.circle(int(120-nowy*3.75),int(120+nowx*3.75),10)
display.circle(int(120-nowy*5.45),int(120+nowx*5.45),10)
display.set_pen(250,0,250)
display.pixel_span(0,120,240)
display.pixel_span(0,121,240)
for i in range(240):
display.pixel(120,i)
display.pixel(121,i)
write16x32(88,2,2)
write16x32(58,18,2)
write16x32(58,18,34)
write16x32(89,2,34)
if 0<=int(nowx*4):
if nowx*4<10:
write16x32(int(abs(nowx*4))-48,34,2)
else:
write16x32(int(abs(nowx*4)/10)-48,34,2)
write16x32(int(abs(nowx*4)%10)-48,34+16,2)
else:
write16x32(45,34,2)
if abs(nowx*4)<10:
write16x32(int(abs(nowx*4))-48,34+16,2)
else:
write16x32(int(abs(nowx*4)/10)-48,34+16,2)
write16x32(int(abs(nowx*4)%10)-48,34+32,2)
if 0<=int(nowy*4):
if nowy*4<10:
write16x32(int(abs(nowy*4))-48,34,34)
else:
write16x32(int(abs(nowy*4)/10)-48,34,34)
write16x32(int(abs(nowy*4)%10)-48,34+16,34)
else:
write16x32(45,34,34)
if abs(nowy*4)<10:
write16x32(int(abs(nowy*4))-48,34+16,34)
else:
write16x32(int(abs(nowy*4)/10)-48,34+16,34)
write16x32(int(abs(nowy*4)%10)-48,34+32,34)
display.update()
下面开始分段讲代码实现
先说说屏幕是怎么显示的把:
因为图形库已经由固件自带,所以只需要完成基本图形绘制即可完成示例水平仪形状的绘制,简要学习了自带的方法,本项目用到的主要有
,但是自带的方法里面没有画空心圆,只有画实心圆的方法,所以,画两个同心圆的线框还是通过不同大小的实心同心圆叠加产生的效果,按照图层叠加,使用clear方法填充完背景色后,首先画半径为120的紫色大圆,再画半径118的背景色小圆,再画半径60的紫色小圆,最后画半径58的背景色小圆(代码118-125行),画完同心圆就应该画正交线了,为了美观,正交线也是两个像素的宽度,但不知为啥,这个显示库只提供了水平线的方法,没提供竖直线的方法,我只好写了个For循环使用pixel方法手工画了一次130-134行(也可能是人家有这些方法我没发现,看见群里其他小伙伴做的那么炫,我可羡慕了)
以上内容实现了基础的屏幕显示,可更重要的还有个数据来源啊,本来想偷懒的,可翻遍了gayhub也没找到一个薅来就能用的MMA7660 micro python库,只要亲自下场看datasheet了,不过幸亏这玩意简单,就十个寄存器,前三个就是x、y、z的坐标,剩下的寄存器一块来看下程序里都用到了啥
好了,关于此项目的开发,基本就是这些了,谢谢各位看官老爷的阅读,小弟才疏学浅,日后还需要向各位大佬多加学习!