2024艾迈斯欧司朗竞赛 - dToF传感器模块搭配RP2040实现平面角度测算
该项目使用了TMF8821,实现了角度测算的设计,它的主要功能为:基于CircuitPython 使用TMF8821的dToF传感器,在带屏幕的RP2040开发板上实现,将板卡组合后固定,并保证与面前的平面存在一定夹角,通过程序测算出板卡距离屏幕的夹角和垂直最小距离的任务。
标签
开发板
CircuitPython
RP2040
TMF8821
disk
更新2025-03-04
74

- 项目介绍

2024艾迈斯欧司朗dToF传感器光电设计竞赛是由艾迈斯欧司朗赞助硬禾科技举办。本次项目,首先编译适配了RP2040游戏机套件的CircuitPython 镜像,依托开源的TMF8821 dToF传感器驱动,实现在RP2040游戏机套件上进行使用TMF8821 dToF传感器 进行被测平面的 与 设备间夹角的动态变化。


-使用到的硬件介绍

树莓派RP2040游戏机套件 和 TMF8821 dToF传感器模块.

树莓派RP2040游戏机套件,不仅拥有丰富的传感器,还带有屏幕和案件,背面还有扩展接口。方便扩展

dToF模块是基于 TMF8821 设计的直接飞行时间 (dToF) 传感器模块,TMF8821采用单个模块化封装,带有相关的 VCSEL(垂直腔面发射激光器



- 方案框图和项目设计思路介绍


几何抽象

{2F1A6D0F-9AC9-41AE-998E-609042F01740}.png

  • 传感器会获得 三个到平面的距离 OA OB OC,
  • 根据数据手册,可以知道∠AOC为32°,且 ∠AOB = ∠BOC,∴ ∠AOB = ∠BOC=16°
  • 传感器垂直固定于底板,所以OB⊥OM,三角形OMB是直角三角形
  • ∠OMB的角度就是 开发板与墙面的夹角(OA 和 OC 中较短的 会和墙面形成夹角)
  • ∠BOM 在 三角形 AOB 中
  • 三角形 AOB 中 已知了OA 和 OB的长,∠AOB =16
  • 第一次三角函数,三角形 AOB 中,计算 AB 长度
  • 第二次三角函数,三角形 AOB 已知三边长,计算∠BOM 度数
  • 在直角三角形OMB中,∠OMB = 90 - ∠BOM




主要实现的方案逻辑如下

{D18E3CE5-301C-414C-8A46-18242834E466}.png

  1. 传感器获取三个角度的到被测平面的距离
  2. 利用几何余弦定理,计算角度



具体设计和实现步骤

{0459652C-478A-4F63-BEC8-F59C46C81381}.png

  • 适配了树莓派RP2040游戏机 的CircuitPython(以下称 CPY) 固件
  • 找到了合适的CPY 驱动
  • 两次 余弦定理计算夹角
  • 屏幕输出实时计算结果



- 软件流程图和关键代码介绍

{A5B9FAE3-CA96-4395-91D4-9CB5956AEC5D}.png

  • lib是主要驱动库和依赖库
  • main文件是入口文件
  • consie_law 是 余弦定理函数
  • i2c_0 不是项目必须文件( 因为开发有2路I2C,项目中使用的是GP16/17)


主要代码:

  • consie_law.py
import math

def calculate_angle_A(a, b, C_deg= 16):
"""
计算三角形的角 A,给定边 a, b 和夹角 C(度数)。

参数:
a (float): 边 a 的长度
b (float): 边 b 的长度
C_deg (float): 夹角 C 的角度(度数)

返回:
float:A 的角度(度数)
"""
# 将角度 C 转换为弧度
C_rad = math.radians(C_deg)

# 使用余弦定理计算边 c 的长度
c = math.sqrt(a**2 + b**2 - 2 * a * b * math.cos(C_rad))

# 使用余弦定理计算角 A
cos_A = (b**2 + c**2 - a**2) / (2 * b * c)

# 确保余弦值在[-1, 1]的范围内,防止由于浮动误差导致的 math domain error
cos_A = max(-1, min(1, cos_A))

A_rad = math.acos(cos_A) # 反余弦,得到角 A 的弧度

# 将角 A 转换为度数
A_deg = math.degrees(A_rad)

return A_deg
if __name__ == '__main__':
# 示例使用:
a = 366
b = 390
C_deg = 16

angle_A = calculate_angle_A(a, b,C_deg)

print(f"角 A 的角度为: {angle_A:.2f}°")


print(90-angle_A )



函数前半部分是第一次余弦定理 计算 第三条边的长度,然后后半部门计算 角度

对应的两个公式如下

{13ACE8C3-08FA-4452-80E2-D0351C6C51B3}.png


  • 程序入口文件main.py
import time
import board
from adafruit_ticks import ticks_ms, ticks_diff
from busio import I2C

from lib.tmf8821 import TMF8821
from cosine_law import calculate_angle_A

i2c = I2C(scl=board.GP17, sda=board.GP16, frequency=125000)

tof = TMF8821(i2c, verbose=True)

tof.config.iterations = 5.5e5 # PDF page 21:550k
tof.config.period_ms = 32 # PDF page 21:32.2 ms

'''
'3x3_normal_mode': 1,
'3x3_macro_mode_upper': 2,
'3x3_macro_mode_lower': 3,
'3x3_wide_mode': 6,
'3x3_checkerboard_mode': 11,
'3x3_inverted_checkerboard_mode': 12,
'4x4_normal_mode': 7,
'4x4_macro_mode_upper': 4,
'4x4_macro_mode_lower': 5,
'4x4_narrow_mode': 13,
'3x6_mode': 10,
'''
tof.config.spad_map = '3x3_normal_mode'
tof.config.spread_spectrum_factor = 5

tof.write_configuration()

tof.active_range = 'short'

第一部分主要是根据数据手册进行初始化


if True:
print('Starting measurements...')
tof.start_measurements()
while True:
t_start = ticks_ms()
measurement = tof.wait_for_measurement(timeout_ms=500)

# PDF page 26
out_dis_2 = measurement.distances[1]
out_dis_5 = measurement.distances[4]
out_dis_8 = measurement.distances[7]

if (measurement.confidences[1] == 255 and
measurement.confidences[4] == 255 and
measurement.confidences[7] == 255):
# print(out_dis_2,out_dis_5,out_dis_8)
out_wall_angle = 90 - calculate_angle_A(min(out_dis_2,out_dis_8),out_dis_5)
print('Angle to the wall :',round(out_wall_angle,2),' and distance is ',out_dis_5,' mm')


else:
print('Out of measurements.')
time.sleep(1)

主循环中,选择了 2/5/8 三个SPAD 点的距离(高置信度为255),对应是三个点到墙面距离。

为什么,没有选择数据手册中的水平的 4/5/6?

image.png

因为数据手册中是水平摆放,但是传感器模块在开发板使用时,是垂直放置。


在测量结果中,5号位就是 垂直到墙面的距离。 2和8 中较短的是计算边

在Line# 中使用 calculate_angle_A 计算后,得出夹角。




- 功能展示图及说明

通电后就开始测量和输出计算结果在屏幕上

{1FF0B07D-1CEA-4366-9254-95F7FAA9F06B}.png

改变角度

{49608020-A3CD-4621-8A35-02A990179EB4}.png


右侧角度

{9253BDBD-2EC5-4043-974F-C198DC635EAF}.png

角度过大,会超出量程

{48B81145-8BF5-42E8-B01B-A5B80CE65EE2}.png

动态效果,请看视频比较清楚



- 项目中遇到的难题和解决方法

  • 首先遇到的是没有MPY的驱动,只找到CPY的驱动,所以自己手动适配了MPY
  • 开发板进入UF2 的按钮和其他略有不同,对应按键为B


- 对本次竞赛的心得体会(包括意见或建议)

1. 学习了适配CircuitPython

2. 了解了dToF传感器

3. Game kit 麻雀虽小,五脏俱全

4. TMF8821 文档详细

5. MicroPython的支持


1. 基于RP2040,不支持Wi-Fi

2. dToF传感器,缺乏MicroPython 库支持

   


   - 可编译下载的代码文件(在电子森林我的项目-设计资源-附件处)

附件下载
adafruit-circuitpython-eetree_rp2040_game_kit-en_US-20241128-eetree_RP2040_Game_Kit-5783167.uf2
circuitpython 镜像
cods.zip
代码文件
团队介绍
CircuitPython 爱好者
团队成员
disk
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号