简 介: 通过揣进测试了新版的基于ESP32的裁判系统对于激光信号的检测能力。
关键词
: 智能车竞赛,125Hz,激光信号
§01 智能车竞赛裁判系统
对于 基于ESP32的智能车竞赛裁判系统 中对于室内AI视觉组判别的要求在博文 AI视觉组基于ESP32的裁判系统第一版本设计要求 已经给出。这些裁判系统的功能最终可以由调制激光信号检测以及车模通过检测两个功能组合而成。下面继续调试在 基于ESP32智能车竞赛比赛系统硬件初步调试-5-6 基础上的激光调制信号检测功能。
检测经过125Hz调试的激光光斑信号。
指标要求:
灵敏度:5mW红色激光,光斑直径在5厘米左右
响应时间:小于500ms
检测点:5个,分为两组;一组为一个监测点,位于靶心检;另外一组包括四个检测点,位于目标四周检;
相应形式:红色LED(直径大于10mm)、绿色LED(直径大于10mm)、蜂鸣器;
▲ 光电检测传感器的位置分布
功能描述:
对于水果目标靶,如果靶心检测点检测到信号,而四周检测点没有检测到信号,则表示激光发送成功;如果任何一个四周检测点检测到激光信号,都表示激光发送失败;
对于动物目标靶,任何一个检测点检测到激光信号,都表示激光投射失败;
检测到激光发送成功时,绿色LED点亮,同时蜂鸣器鸣叫,五秒钟后停止; 检测到激光发送失败时,红色LED闪烁,频率10Hz,占空比50%,持续时间五秒钟,同期蜂鸣器也做相同的断续鸣叫。
▲ 目标靶位上的响应LED
§02 测试激光检测
1、激光信号检测
在 ESP32检测调制激光信号程序优化 中,对于采集激光信号中检测算法进行了优化。检测一个通道激光信号的时间,从原来的的40ms左右,提高到11ms。 下面的程序就是基于优化后的算法实现。
(1)测试代码
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST3.PY -- by Dr. ZhuoQing 2021-06-10
#
# Note:
#============================================================
from machine import ADC,Timer,Pin,freq
import time
import math
#------------------------------------------------------------
led = Pin(5, Pin.OUT)
freq(240000000)
#------------------------------------------------------------
speaker = Pin(21, Pin.OUT)
#------------------------------------------------------------
adc1 = ADC(Pin(36))
adc2 = ADC(Pin(39))
adc3 = ADC(Pin(34))
adc4 = ADC(Pin(35))
adc1.atten(ADC.ATTN_6DB)
adc2.atten(ADC.ATTN_6DB)
adc3.atten(ADC.ATTN_6DB)
adc4.atten(ADC.ATTN_6DB)
SAMPLE_NUM = const(500)
AVERAGE_NUM = 16
ad1dim = [0] * SAMPLE_NUM
ad2dim = [0] * SAMPLE_NUM
#ad3dim = [0] * SAMPLE_NUM
#ad4dim = [0] * SAMPLE_NUM
SAMPLE_AVERAGE_LENGTH = 40
ad3average = [0] * SAMPLE_AVERAGE_LENGTH
ad4average = [0] * SAMPLE_AVERAGE_LENGTH
ad34point = 0
ad3sigma = 0
ad4sigma = 0
#------------------------------------------------------------
AD34_BASE_ALPHA = 0.0005
ad3baseline = 0
ad4baseline = 0
AD34_CHECK_THRESHOLD = 250
ad3checktime = 0
ad4checktime = 0
#------------------------------------------------------------
sample_point = 0
stop_flag = 0
sample_mode = 1 # 0 : sample adc3, adc4
# 1 : sample adc1, adc2
total_count = 0
#------------------------------------------------------------
def ADC4Sample(_):
global ad1dim,ad2dim,ad3dim,ad4dim
global sample_point
global adc1,adc2,adc3, adc4
global ad3average, ad4average, ad34point, ad3sigma, ad4sigma
global ad3checktime, ad4checktime,total_count
global ad3baseline, ad4baseline
# led.on()
#--------------------------------------------------------
total_count += 1
#--------------------------------------------------------
if sample_mode == 1:
ad1dim[sample_point] = adc1.read()
ad2dim[sample_point] = adc2.read()
if sample_mode == 0:
adc = adc3.read()
ad3sigma += adc
ad3sigma -= ad3average[ad34point]
ad3average[ad34point] = adc
adc = adc4.read()
ad4sigma += adc
ad4sigma -= ad4average[ad34point]
ad4average[ad34point] = adc
ad34point += 1
if ad34point >= SAMPLE_AVERAGE_LENGTH:
ad34point = 0
# ad3dim[sample_point] = ad3sigma / SAMPLE_AVERAGE_LENGTH
# ad4dim[sample_point] = ad4sigma / SAMPLE_AVERAGE_LENGTH
#----------------------------------------------------
value = ad3sigma / SAMPLE_AVERAGE_LENGTH
if ad3baseline == 0:
if ad34point == SAMPLE_AVERAGE_LENGTH - 1:
ad3baseline = value
else: ad3baseline = ad3baseline * (1 - AD34_BASE_ALPHA) +AD34_BASE_ALPHA * value
if abs(value - ad3baseline) > AD34_CHECK_THRESHOLD:
if ad3checktime == 0:
ad3checktime = total_count
value = ad4sigma / SAMPLE_AVERAGE_LENGTH
if ad4baseline == 0:
if ad34point == SAMPLE_AVERAGE_LENGTH - 1:
ad4baseline = value
else: ad4baseline = ad4baseline * (1 - AD34_BASE_ALPHA) + AD34_BASE_ALPHA * value
if abs(value - ad4baseline) > AD34_CHECK_THRESHOLD:
if ad4checktime == 0:
ad4checktime = total_count
#--------------------------------------------------------
sample_point += 1
if sample_point >= SAMPLE_NUM:
sample_point = 0
#--------------------------------------------------------
# led.off()
#------------------------------------------------------------
SAMPLE_PERIOD = 1
FREQUENCY_MOD = 125
def angle1(n):
return n*2*3.1415926*SAMPLE_PERIOD / 1000.0 * FREQUENCY_MOD
def wval(w):
if w < SAMPLE_NUM / 2:
return w * 2 / SAMPLE_NUM
else: return (SAMPLE_NUM - w) * 2 / SAMPLE_NUM
cosdim = [int(math.sin(angle1(a)) * wval(a) * 0x7ff) for a in range(SAMPLE_NUM)]
sindim = [int(math.cos(angle1(a)) * wval(a) * 0x7ff) for a in range(SAMPLE_NUM)]
#------------------------------------------------------------
def sample_amp(s):
global cosdim,sindim,sample_point
cos_sam = 0
sin_sam = 0
scopy = s.copy()
if sample_point > 0:
scopy = scopy[sample_point:] + scopy[:sample_point]
cos_sum = sum([s*w for s,w in zip(scopy,cosdim)]) / SAMPLE_NUM
sin_sum = sum([s*w for s,w in zip(scopy,sindim)]) / SAMPLE_NUM
return math.sqrt(cos_sum**2 + sin_sum**2)
#------------------------------------------------------------
time0 = Timer(0)
time0.init(period=SAMPLE_PERIOD, mode=Timer.PERIODIC, callback=ADC4Sample)
#------------------------------------------------------------
count = 0
while True:
led.on()
check1 = sample_amp(ad1dim)
check2 = sample_amp(ad2dim)
led.off()
print(check1, check2)
time.sleep_ms(50)
#------------------------------------------------------------
# END OF FILE : test2.PY
#============================================================
(2)计算时间
根据前面的程序,在计算过程中,LED输出高电平。通过测量LED的输出波形,便可以知道计算两个通道的激光信号所消耗的时间。
下图显示了LED的输出信号波形,可以看到两个通道的计算时间大约为30ms。
▲ 图1.1 测量LED的输出波形来表征计算时间
(3)检测激光信号
在静态情况下,输出的数据大都在500上下,1000之下。
▲ 图1.2 在没有信号的输出的噪声
在检测到光的时候输出数值超过10000。所以使用10000作为检测阈值比较合适。
▲ 图1.3 检测到激光信号对应的输出数据变化
(4)判断程序
下面是测试的判断激光信号的程序。
LASER_THRESHOLD = 10000
while True:
check1 = sample_amp(ad1dim)
check2 = sample_amp(ad2dim)
print(check1, check2)
if check1 > LASER_THRESHOLD:
led.on()
else: led.off()
if check2 > LASER_THRESHOLD:
led1.on()
else: led1.off()
time.sleep_ms(50)
※ 测试结论 ※
通过实验测试了对于激光信号检测能力。检测两个通道使用时间需要30ms。
■ 相关文献链接:
- 基于ESP32模块利用检测线圈检测车模停止时间,室内视觉AI裁判系统
- AI视觉组基于ESP32的裁判系统第一版本设计要求
- 基于ESP32智能车竞赛比赛系统硬件初步调试-5-6
- ESP32检测调制激光信号程序优化
● 相关图表链接:
- 光电检测传感器的位置分布
- 目标靶位上的响应LED
- 图1.1 测量LED的输出波形来表征计算时间
- 图1.2 在没有信号的输出的噪声
- 图1.3 检测到激光信号对应的输出数据变化