一.项目介绍
本项目基于带显示屏的RP2040与十二指神探套件,开发了一款探测距离并发出警报的小型设计,可应用于人体检测、门窗关闭,距离提示等智能家用场景中。项目的具体要求如下
- 可检测门窗开关状态
- 人体经过或靠近检测
- 可使用蜂鸣器发出警报、成功识别等状态音
- 可在LCD上显示基本信息如开关状态、人体或物体是否经过、距离远近
二.资源介绍
本次项目主要应用了十二指神探扩展版实现。作为RP2040的扩展板,十二指神探接口完全适配即插即用。扩展板搭载了的包含传感器和功能模块(官方提供链接有失效)
- 麦克风
- 蜂鸣器
- 红外收发 VSMB10940/IRM-H6XXT/TR2
- 霍尔效应开关CC6201
- 加热电阻
- 温湿度传感器NSHT30
- 六轴传感器LSM6DS3TR-C
- 接近/环境光/IR传感器RPR-0521RS
- 颜色传感器LTR-381RGB-WA
功能多面且资料完备,最重要的是价格便宜,适合新手作为入门套件购买学习。
三.设计思路
项目实现重点在于如何获得实际距离,本设计采用十二指神探上搭载的rpr0521传感器,通过拟合的方式获取实际距离。此外,也通过RP2040套件的LCD与拨码,实现人机交互,可调节目标距离并显示。实现思路如下
- 测距思路
rpr0521传感器将发光器件与接收器件集成同一芯片上,自身发出的光线遇到探测物时将反射回来从而让接收器收到,原理可参照下图(rpr0720是0521的升级版本,原理一致)。因此,记录发出光线与接收光线的时间差,再乘以光速就可以得到物体距离了。
然而在实际中,该项繁琐的工作传感器可自行完成,使用者可通过通信协议(一般为I2C)配置传感器的工作方式,再将读取的传感器数据处理一下便可得到物体距离。
通常情况下,传感器芯片的示例代码(如初始配置,通信方式,数据处理等)可以在官网上找到,或联系供应商获得,然而笔者通过上述两种方式并未找到示例,只能尝试自行解决。传感器的功能配置可参照芯片手册进行,而数据处理通过测量若干点的方式拟合得到了测距公式。该部分请参照下一节。
四.代码与功能演示
本项目的主要代码如下,具体功能可参照注释与视频演示。
import uos
import test.st7789 as st7789
from test.fonts import vga2_8x8 as font1
from test.fonts import vga1_16x32 as font2
from machine import Pin, PWM, I2C
import math
import framebuf
#屏幕初始化
st7789_res = 0
st7789_dc = 1
disp_width = 240
disp_height = 240
CENTER_Y = int(disp_width/2)
CENTER_X = int(disp_height/2)
spi_sck=Pin(2)
spi_tx=Pin(3)
spi0=SPI(0,baudrate=4000000, 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)
display.fill(st7789.BLACK)
display.text(font2, "distance", 10, 10)
display.text(font2, "detecting...", 10, 40)
display.text(font2, "current", 10, 70)
#display.text(font2, "100", 10, 100, st7789.RED)
display.text(font2, "goal", 10, 140)
#display.text(font2, "200", 10, 170, st7789.GREEN)
#外设初始化
buttonL = Pin(7,Pin.IN, Pin.PULL_UP) #A
buttonR = Pin(9,Pin.IN, Pin.PULL_UP) #A
buzzer=PWM(Pin(23))
buzzer.freq(500)
rpr=I2C(0,scl=Pin(21),sda=Pin(20))
rpr.writeto_mem(56,0x41,b'\xe5')
rpr.writeto_mem(56,0x42,b'\x01')
rpr.writeto_mem(56,0x43,b'\x00')
rpr.writeto_mem(56,0x44,b'\xa7')
#获取距离,手动测量若干点后导入excel拟合
def GetDis(Isnum=True):
data1=int.from_bytes(rpr.readfrom_mem(56,0x45,1),'>')
data2=int.from_bytes(rpr.readfrom_mem(56,0x44,1),'>')
raw=str('{:04b}'.format(data1))+str('{:08b}'.format(data2))
raw=int(raw,2)
if Isnum:
if raw==0:
return "out of range"
if raw>115:
return str(366.24*pow(raw,-0.82))+"cm "
else:
return str(61.851*pow(raw,-0.496))+"cm "
return result
else:
if raw==0:
return 0
if raw>130:
return 360*pow(raw,-0.8)
else:
return 60*pow(raw,-0.5)
return result
#变量初始化
goal=30
#主循环
while True:
goal=(goal-buttonR.value()+buttonL.value())%60
display.text(font2, str(goal), 10, 170, st7789.BLUE)
display.text(font2, GetDis(), 10, 100, st7789.YELLOW)
buzzer.duty_u16(int(10*abs(GetDis(False)-goal)))
if abs(GetDis(False)-goal)<3:
display.text(font2, "OFF", 100, 170, st7789.GREEN)
else:
display.text(font2, "ON ", 100, 170, st7789.RED)
实际效果见下
- 通过拨码调节目标距离
- 刷新探测距离
五.遇到的问题
本设计中涉及到使用I2C通信与距离传感器通信获取数据,由于是第一次接触rpr0521传感器不了解其通信方式,遂通过查阅芯片手册的方式了解到如何设置采集方式与如何采集数据。
寄存器地址与备注
寄存器含义
六.总结与感想
本项目锻炼了我的信息搜集能力和编程能力,对嵌入式开发,尤其是I2C协议以及遇到不了解的芯片后如何应用有了新的体会,受益匪浅。未来期望再次参加此类活动,了解并学习更多的知识,开拓电子设计视野。