1 项目需求
- 利用240*240的显示屏制作一个双通道电压表,通过指针的摆动显示当前的电压。
- 被测对象为四向摇杆的x、y轴电位计,这两个电位计分压从0-3.3V摆动,推动摇杆,表盘上的指针摆动,并在下面用数字的方式显示当前的电压值。
- 完成表盘的设计以及校准,能够准确测量电压,可以切换到12Pin扩展排针上的两个模拟通道输入端,对这两个输入信号进行测量 - 手指触碰表针摆动
- 通过提供的杜邦线连接其它数据端口,编程数据端口输出低频率的数字波形(会在0-3.3之间摆动),看指针的摆动
- 指针摆动做出连续移动的效果,真实仿真模拟表盘的工作机制
2 完成的功能及达到的性能
2.1 电压图表显示
利用240*240的显示屏制作一个双通道电压表,通过指针的摆动显示当前的电压。
2.2四向摇杆的x、y轴电位计控制电压显示
3 实现思路
- 模数转换器 (ADC)将模拟信号(直流输入电压)转换成数字信号;
- LCD模拟指针式显示显示方式实现双路电压表测量和显示;
- 通过四向遥感改变两路电压;
- AD转换器采集四向摇杆的两路电压
- 根据电压的值来控制指针的指示方向
流程图如图:
4 硬件介绍
采用树莓派Pico核心芯片RP2040:
1、双核Arm Cortex M0+内核,可以运行到133MHz
264KB内存
2、性能强大、高度灵活的可编程IO可用于高速数字接口
3、片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度
4、支持MicroPython、C、C++编程
板上功能:
1、240*240分辨率的彩色IPS LCD,SPI接口,控制器为ST7789
2、四向摇杆 + 2个轻触按键 + 一个三轴姿态传感器MMA7660用做输入控制
3、板上外扩2MB Flash,预刷MicroPython的UF2固件
4、一个红外接收管 + 一个红外发射管
5、一个三轴姿态传感器MMA7660
6、一个蜂鸣器
7、双排16Pin连接器,有SPI、I2C以及2路模拟信号输入
8、可以使用MicroPython、C、C++编程
9、USB Type C连接器用于供电、程序下载
5 主要代码及说明
1、定义常量、变量,包括图片文件地址、屏幕引脚、屏幕像素等:
image_file0 = "back.bin"
st7789_res = 0
st7789_dc = 1
disp_width = 240
disp_height = 240
CENTER_Y = int(disp_width/2)
CENTER_X = int(disp_height/2)
x=60
y=40
f_x=60
f_y=60
x1=60
y1=40
f_x1=60
f_y1=40
f_pointer=0
f_pointer1=0
PWM_OUT_Time=0
2、初始化外设,包括初始化SPI、LCD、ADC、GPIO、PWM:
Joy_x = machine.ADC(29)
Joy_y = machine.ADC(28)
Joy_z = machine.ADC(26)
Joy_h = machine.ADC(27)
spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi0=machine.SPI(0,baudrate=80000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
#
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)
3、开机画面,先显示文字信息,然后显示硬禾LOGO:
display.fill(st7789.BLACK)
display.text(font2, "Hello! RPi Pico", 10, 10)
display.text(font2, "HGF", 10, 40)
display.text(font2, "MicroPython", 35, 100)
display.text(font2, "EETREE", 35, 150)
display.text(font2, "www.eetree.cn", 30, 200)
utime.sleep(1)
f_image = open(image_file1, 'rb')
for column in range(1,240):
buf=f_image.read(480)
display.blit_buffer(buf, 1, column, 240, 1)
utime.sleep(1)
4、电压表初始化显示,显示静态背景、读数显示
f_image = open(image_file0, 'rb')
for column in range(1,240):
buf=f_image.read(480)
display.blit_buffer(buf, 1, column, 240, 1)
freq=machine.freq()
print(freq)
5、电压表主要功能(while True内),测量并显示电压,读取摇杆两路电压:
while True:
PWM_OUT_Time = PWM_OUT_Time+1
if PWM_OUT_Time<30:
PWM_OUT.value(1)
else:
PWM_OUT.value(0)
if PWM_OUT_Time == 60:
PWM_OUT_Time=0
if INPUT.value() == 1:
xValue = Joy_x.read_u16()
yValue = Joy_y.read_u16()
else:
xValue = Joy_z.read_u16()
yValue = Joy_h.read_u16()
pointer = int(xValue * (330-0)/0xffff)/100
display.text(font2, str(pointer), 170, 33)
pointer1 = int(yValue * (330-0)/0xffff)/100
display.text(font2, str(pointer1), 170, 153)
if f_pointer<pointer-0.3:
f_pointer = f_pointer + 0.2
else:
if f_pointer>pointer+0.3:
f_pointer = f_pointer - 0.1
else:
f_pointer = pointer
if f_pointer1<pointer1-0.3:
f_pointer1 = f_pointer1 + 0.2
else:
if f_pointer1>pointer1+0.3:
f_pointer1 = f_pointer1 - 0.1
else:
f_pointer1 = pointer1
angle1=round(30+(f_pointer*120/4))
if angle1<90:
A1=angle1*3.1415926/180.0
divy=math.sin(A1)*40
divx=math.cos(A1)*40
x=int(95-divx)
y=int(100-divy)
if f_x!=x:
display.line(f_x-1,f_y,95,100,st7789.WHITE)
else:
if f_y!=y:
display.line(f_x-1,f_y,95,100,st7789.WHITE)
f_x=x
f_y=y
display.line(x-1,y,95,100,st7789.BLACK)
else:
angle1=180-angle1
A1=angle1*3.1415926/180.0
divy=math.sin(A1)*40
divx=math.cos(A1)*40
x=int(95+divx)
y=int(100-divy)
if f_x!=x:
display.line(f_x-1,f_y,95,100,st7789.WHITE)
else:
if f_y!=y:
display.line(f_x-1,f_y,95,100,st7789.WHITE)
f_x=x
f_y=y
display.line(x-1,y,95,100,st7789.BLACK)
angle2=round(30+(f_pointer1*120/4))
if angle2<90:
A2=angle2*3.1415926/180.0
divy=math.sin(A2)*40
divx=math.cos(A2)*40
x1=int(95-divx)
y1=int(220-divy)
if f_x1!=x1:
display.line(f_x1-1,f_y1,95,220,st7789.WHITE)
else:
if f_y1!=y1:
display.line(f_x1-1,f_y1,95,220,st7789.WHITE)
f_x1=x1
f_y1=y1
display.line(x1-1,y1,95,220,st7789.BLACK)
else:
angle2=180-angle2
A2=angle2*3.1415926/180.0
divy=math.sin(A2)*40
divx=math.cos(A2)*40
x1=int(95+divx)
y1=int(220-divy)
if f_x1!=x1:
display.line(f_x1-1,f_y1,95,220,st7789.WHITE)
else:
if f_y1!=y1:
display.line(f_x1-1,f_y1,95,220,st7789.WHITE)
f_x1=x1
f_y1=y1
display.line(x1-1,y1,95,220,st7789.BLACK)
6、遇到的主要难题和解决办法
对bin格式图片不了解,前期花费大量时间调试image2lcd软件,通过修改输出灰度以及扫描模式使得图片能在单片机上正常显示。通过不断调参使电压表指针刻度相对精确。
7.项目总结
通过这次寒假一起练活动,我对于RP2040开发板有了更加深入的了解,在项目开发的过程中,也充分锻炼了我的代码能力。同时一个完整的项目经历,让我对于项目开发的基本流程有了新的认识。