esp32 本地控制_esp32 本地控制

简 介: 通过揣进测试了新版的基于ESP32的裁判系统对于激光信号的检测能力。

关键词智能车竞赛125Hz激光信号

 

§01 智能车竞赛裁判系统


对于 基于ESP32的智能车竞赛裁判系统 中对于室内AI视觉组判别的要求在博文 AI视觉组基于ESP32的裁判系统第一版本设计要求 已经给出。这些裁判系统的功能最终可以由调制激光信号检测以及车模通过检测两个功能组合而成。下面继续调试在 基于ESP32智能车竞赛比赛系统硬件初步调试-5-6 基础上的激光调制信号检测功能。

1、检测激光信号要求

  检测经过125Hz调试的激光光斑信号。

指标要求:

灵敏度:5mW红色激光,光斑直径在5厘米左右

响应时间:小于500ms


检测点:5个,分为两组;一组为一个监测点,位于靶心检;另外一组包括四个检测点,位于目标四周检;


相应形式:红色LED(直径大于10mm)、绿色LED(直径大于10mm)、蜂鸣器;


esp32 本地控制_d3_02


▲ 光电检测传感器的位置分布

  功能描述

对于水果目标靶,如果靶心检测点检测到信号,而四周检测点没有检测到信号,则表示激光发送成功;如果任何一个四周检测点检测到激光信号,都表示激光发送失败;

对于动物目标靶,任何一个检测点检测到激光信号,都表示激光投射失败;

检测到激光发送成功时,绿色LED点亮,同时蜂鸣器鸣叫,五秒钟后停止; 检测到激光发送失败时,红色LED闪烁,频率10Hz,占空比50%,持续时间五秒钟,同期蜂鸣器也做相同的断续鸣叫。

esp32 本地控制_2d_03


▲ 目标靶位上的响应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。

esp32 本地控制_d3_04


▲ 图1.1 测量LED的输出波形来表征计算时间

(3)检测激光信号

  在静态情况下,输出的数据大都在500上下,1000之下。

esp32 本地控制_esp32 本地控制_05


▲ 图1.2 在没有信号的输出的噪声

  在检测到光的时候输出数值超过10000。所以使用10000作为检测阈值比较合适。

esp32 本地控制_2d_06


▲ 图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 检测到激光信号对应的输出数据变化