树莓派PICO和其扩展板(硬禾学堂研制)体验与研究
进行了如下探究,但尚未完善: 使用micropython编程,进行了几个外设的控制。使用板载PWM输出来连接ADC引脚输入检测信号,在显示屏上读出;使用姿态传感器控制显示内容的位置。
标签
树莓派
嵌入式系统
sslzykk
更新2021-03-17
1302

我们来进行两个探究。1. 模拟示波器显示方波脉冲。

                            2. 通过改变开发板姿态来移动屏幕中文字。

 

 

#####探究1:

我们知道,PWM意义为脉冲宽度调制,其原理为通过控制方波脉冲的占空比,来实现模拟连续的时域内的三角函数曲线波,以此实现对模拟物理量的表达,比如声音的振幅,LED的亮度。而ADC转换的意义为 模拟—数字 转换,如果在有ADC功能的引脚输入一个PWM调制后的信号,这个信号会被解调成原本的方波脉冲。我们通过PICO及其扩展板做一个实验来验证这一点。

 

首先,扩展板将PICO连接到了一个最高支持240X240像素的LCD屏上,使用3.3V电源使能屏幕光源(LED). 屏幕像素的控制是通过四根导线与Pico板的通信实现的,分别是:SCL(控制线), SDA(数据线), DC(直流电线),和RSTn(三项四线电源),其通信方式为I2C。

我们首先来看LCD屏显示的代码:

from machine import Pin, PWM
from time import sleep
import utime
import st7789
from fonts import vga1_16x32 as font2

st7789_res = 0
st7789_dc  = 1

spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi0=machine.SPI(0,baudrate=4000000, phase=0, polarity=1, sck=spi_sck, mosi=spi_tx)
disp_width = 240
disp_height = 240
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=120, rotation=0)

此代码定义了一个函数display, 其本体是等号右边的st7789库里面的ST7789类,调用display时可以使用此函数的其他形式。要实现屏幕的控制,首先需要加载运行这个库.以下为库的部分代码:

def pixel(self, x, y, color):
        """
        Draw a pixel at the given location and color.

        Args:
            x (int): x coordinate
            Y (int): y coordinate
            color (int): 565 encoded color
        """
        self.set_window(x, y, x, y)
        self.write(None, _encode_pixel(color))

 

如注释所示,此函数为ST7789类内的一个行为,调用时可以在屏幕上的一个像素画点。

 

 

如果在模块一接上如下代码:

display.fill(st7789.BLACK)

display.text(font2, "text_content", x, y)
display.text(......)


#for i in range(5000):
#   display.pixel(random.randint(0, disp_width),
#          random.randint(0, disp_height),
          #st7789.color565(random.getrandbits(8),random.getrandbits(8),random.getrandbits(8)))

就可以在屏幕上显示想要的内容,内容可在display.text中自定义。最后四行代码可以额外产生雪花般的效果,可以不加。

FhdlBR4ZwBtG7ZuIxZ1WzgwE7ojE

接下来,我们通过PWM来输出信号,代码如下:

from machine import Pin, PWM
from time import sleep

pwm=PWM(Pin(28))
pwm.freq(200000)
while True:
    for duty in range(0,51200,+256):
        pwm.duty_u16(duty)

 

从原理图可以看出,具有PWM功能的28号引脚可以通过跳线连接到蜂鸣器电路,或者连接到外部输出接口。如上图所示,用黄线两端连接三根柱的下面两根就可以控制蜂鸣器(与其他跳线无关)。蜂鸣器的声音大小和频率可以通过占空比(duty)和频率(freq)控制,但由于此函数过于简单实际效果不明显。

 

如果如图这样跳线,就将信号输出到了27号引脚上,其通过A-D转化后,就读到了原本的脉冲方波信号。将代码整合后,就制作出了简易的方波示波器:

from machine import Pin, PWM
from time import sleep
import utime
import st7789
from fonts import vga1_16x32 as font2

st7789_res = 0
st7789_dc  = 1

spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi0=machine.SPI(0,baudrate=4000000, phase=0, polarity=1, sck=spi_sck, mosi=spi_tx)
disp_width = 240
disp_height = 240
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=120, rotation=0)
                        
spi = machine.SPI(0)
reset = machine.Pin(0)
dc = machine.Pin(1)
oled = st7789.ST7789(spi,240,240,reset,dc)
oled.fill(st7789.BLACK)

key = machine.Pin(6,machine.Pin.IN)
keyleft=machine.Pin(4,machine.Pin.IN)
keyright=machine.Pin(5,machine.Pin.IN)


pwm=PWM(Pin(28))
pwm.freq(200)

  
    
potentiometer = machine.ADC(27)
data1=0

mo=500
a=0


###中断函数###
def int_handler(pin):
    keyleft.irq(handler=None)
    global mo
    global dif
    
    if key.value()==1:
        a=0
        print("key=0")
    elif key.value()==0:
        a=1
        print("key=1")
        
    if keyleft.value() == 0:
        if keyright.value() == 1:
           print("顺时针")
           if mo<1000:
               mo=mo+100
        if keyright.value() == 0:
           print("逆时针")
           if mo>100:
               mo=mo-100
    if keyleft.value() == 1:
        if keyright.value() == 0:
           print("顺时针")
           if mo<1000:
               mo=mo+100           
        if keyright.value() == 1:
           print("逆时针")
           if mo>100:
               mo=mo-100
    #oled.text(font2,mo,100,2)
    oled.fill(st7789.BLACK)
    
    if mo==100:
         dif=80
         oled.text(font2, "1000", 100, 2)
    if mo==200:
         dif=87
         oled.text(font2, "900", 100, 2)
    if mo==300:
         dif=300
         oled.text(font2, "800", 100, 2)
    if mo==400:
         dif=65
         oled.text(font2, "700", 100, 2)
    if mo==500:
         dif=41
         oled.text(font2, "600", 100, 2)
    if mo==600:
         dif=80
         oled.text(font2, "500", 100, 2)
    if mo==700:
         dif=87
         oled.text(font2, "400", 100, 2)
    if mo==800:
         dif=300
         oled.text(font2, "300", 100, 2)
    if mo==900:
         dif=65
         oled.text(font2, "200", 100, 2)
    if mo==1000:
         dif=41
         oled.text(font2, "100", 100, 2)
    keyleft.irq(handler=int_handler) 

keyleft.irq(trigger=machine.Pin.IRQ_FALLING|machine.Pin.IRQ_RISING, handler=int_handler)
###中断实现###



while True:
        pwm.duty_u16(60000)
        data1 = potentiometer.read_u16()
        for x in range (0,240):
            data2=data1
            data1=potentiometer.read_u16()
            if data2>data1:
                display.vline(x, data1//mo, (data2-data1)//mo, st7789.BLUE)
            elif data1>data2:
                display.vline(x, data2//mo, (data1-data2)//mo, st7789.BLUE) 
            else:
                display.hline(x, data1//mo, (data1-data2)//mo, st7789.RED)
            display.pixel(x, data1//mo, st7789.WHITE)
         
        display.fill(st7789.BLACK)

 

其中,有中断注释的部分是为了实现旋钮控制振幅单位(V/div),在最后的while循环外能够产生中断,先跳到中断函数内执行对mo的操作改变这个全局变量的值,再在最后的while循环内代入计算。竖线是通过库函数display.vline实现,但横线hline画不好,暂时未解决。烧录后就可以实现视频的效果。通过改变pwm.freq和pwm.duty_u16的占空比可以展示不同的波形。

 

#####探究2:

MMA7660是一个三轴加速度传感器,在x,y,z三个方向移动开发板就会由于惯性而在芯片内部产生相应电容的变化,通过算法就可以解算出加速度。通过放大这个加速度,把它作为显示内容的横纵坐标的增量进行迭代,就可以在屏幕上“移动”显示的文字。

请看代码:

from machine import Pin,PWM, I2C, SPI
import st7789
from fonts import vga2_8x8 as font1
from fonts import vga1_16x32 as font2
import time
import struct
from time import sleep
from math import ceil
import utime

import uos
import random

# spi
SCK = Pin(2)
MOSI = Pin(3)
RST = Pin(0, Pin.OUT)
DC = Pin(1, Pin.OUT)

SCL = Pin(11)
SDA = Pin(10)
BUS = 1 

width = 240
height = 240 

# inititializing SPI and I2C
spi0 = SPI(0, baudrate=40000000, polarity=1, phase=0, sck=SCK,mosi=MOSI)

mma7660 = I2C(BUS,scl=SCL, sda=SDA, freq=40000000)
display = st7789.ST7789(spi0, width, height, reset=RST, dc=DC,xstart=0, ystart=0,rotation=0)

display.fill(st7789.color565(255,255,0))
time.sleep(2)
display.fill(st7789.BLACK)
display.text(font2,"Hello MMA7660", 10, 10)

address = mma7660.scan()
print("I2C address:%x", hex(address[1]))
display.text(font2,"I2C addr: %x" %address[1] , 10, 40)

print("激活 MMA7660")
# 向寄存器 0x07写入 1
mma7660.writeto_mem(76, 7, b'1')

key1=machine.Pin(21,machine.Pin.IN)
key2=machine.Pin(22,machine.Pin.IN)
key3=machine.Pin(20,machine.Pin.IN)



st7789_res = 0
st7789_dc  = 1
xa=20
ya=20
def disp(xout,yout):
    spi_sck=machine.Pin(2)
    spi_tx=machine.Pin(3)
    spi0=machine.SPI(0,baudrate=4000000, phase=0, polarity=1, sck=spi_sck, mosi=spi_tx)
    disp_width = 240
    disp_height = 240
    print(spi0)
    global xa
    global ya

    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)

    xa=xa+10*ceil(xout)
    ya=ya+10*ceil(yout)

    display.text(font2,"HELLO,PICO!",xa,ya,st7789.WHITE)
    
    





# The 6-bit measurement data is stored in the XOUT (0x00), YOUT (0x01), and ZOUT (0x02) registers 
try:
    while True:
        x= mma7660.readfrom_mem(76, 0, 6)
        y= mma7660.readfrom_mem(76, 1, 6)
        z= mma7660.readfrom_mem(76, 2, 6)
        
        
            
        xout = struct.unpack('>f', x)[0]
        yout = struct.unpack('>f', y)[0]
        zout = struct.unpack('>f', z)[0]
        
        disp(xout,yout)

    
        print('x:{:+.10f},y:{:+.10f},z:{:+.10f}'.format(xout,yout,zout))

except KeyboardInterrupt:
    print("QUIT")
    display.fill(st7789.color565(255,0,0))
    display.text(font2, "GOOD BYE", 80, 120)

于是就实现了视频第二段的效果。存留的问题是:无法获得每个轴负向的加速度,导致图案只能往右下方移动。请后续开发者参照MMA7660官方的文档来完善。

 

 

 

团队介绍
刘卓远
团队成员
sslzykk
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号