多车组软件使用说明

多车组 智能车竞赛

简 介: 本文给出了多车软件使用说明。多车软件及其配套的计时器硬件和线圈,用于第十七届全国大学生智能车竞赛的多车组。

关键词 多车组智能车竞赛

多车组软件
目 录
Contents
背景介绍
时间差计时系统
总 结
ESP32软件

§01 车组软件


  第十七届全国大学智能汽车竞赛竞速比赛中,包括有多车组,它要求测量多车前后两次通过比赛起跑线上的时间差来比较车模编队前后的距离。

一、背景介绍

  在多车组比赛计时软件中,需要部署两套计时系统,一个是记录总比赛时间,另外一个是记录多车通过起跑线时的时间差。记录比赛总时间的比赛系统,它的部署与其他组别是相同的,在车库门口设置一个计时线圈或者计时光带,记录车模从车库驶出和驶入之间的时间差。记录比赛时间差则使用另外单独的计时系统和比赛系统,它会自动记录多车通过时前后车模之间的时间差,并乘以比率 5 进行显示。

▲ 图1.1 线圈部署示意图

▲ 图1.1 线圈部署示意图

二、时间差计时系统

  时间差计时系统使用龙邱的单独一个计时线圈和相应的计时软件。

1、计时器和计时线圈

  用于测量时间差的计时器也是基于 ESP32 的单片机系统,但它内部的 Python 程序是经过修改后的程序。其中四个拨码开关的设置如下图所示。

计时器拨码开关设置:
开关1:OFF,这一位开关决定电磁线圈触发灵敏度
开关2:ON
开关3:OFF
开关4:OFF

▲ 图1.2.1 计时器内部拨码开关设置

▲ 图1.2.1 计时器内部拨码开关设置

2、计时软件

  计时器模块通过 TypeC USB 连线与计算机相连, 计算机需要安装 CH340 USB 驱动软件 。 安装后,可以在 可以在计算机惯例-设备管理-端口 中看到 USB-SERIAL CH340 (COM n) 。 其中 COMn 是计算机分配给 USB 窗口号。 建议将 COM 号修改到 1 ~ 8 之间。

  PC 软件使用智能车竞赛比赛裁判系统-22-7-12。 由于只需要测量两次前后车模通过起跑线时的时间差,所以该软件是独立使用。 程序启动后直接在“时间差” 页面完成计时器清零和计时工作。

▲ 图1.2.2 计时软件界面

▲ 图1.2.2 计时软件界面

(1)软件设置

  软件设置有三个参数。
  1. 串口设置并打开 :根据前面 USB 对应的串口端口, 在打开串口 后面选择对应的串口端口,然后按动打开串口按钮,此时界面右上角接收数字会递增;
  2. 设置最大延时:这个数字缺省情况下是 10秒钟;
  3. 设置时间比率:根据本届比赛规则,延迟时间是按照 5 倍的比例进行显示;

▲ 图1.2.3 软件连接计时模块后,打开串口对应的接受数字就会递增

▲ 图1.2.3 软件连接计时模块后,打开串口对应的接受数字就会递增

3、软件使用

  比赛开始,首车和尾车从车库出发之后,按动“清零”按钮,界面数字显示时间为 0.

  当车队运行一周之后,第一次通过计时线圈,软件根据计时器返回的数字计算出头车与尾车之间的时间差,使用 5 倍的比率进行显示。
  当车队创二次通过计时线圈,软件继续测量头车与尾车之间的时间差,并累加前面时间差,使用 5 倍比率进行显示。

  最后将改时间与比赛系统记录的运行时间叠加之后作为最终的比赛成绩。

  结 ※


  文给出了多车软件使用说明。多车软件及其配套的计时器硬件和线圈,用于第十七届全国大学生智能车竞赛的多车组。

一、ESP32软件

from machine                import UART,Pin,Timer,ADC,PWM
import time
import machine, math

machine.freq(240000000)

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)

button = Pin(32, Pin.IN, Pin.PULL_UP)
sw4 = Pin(15,   Pin.IN, Pin.PULL_UP)
sw3 = Pin(2,    Pin.IN, Pin.PULL_UP)
sw2 = Pin(19,   Pin.IN, Pin.PULL_UP)
sw1 = Pin(4,    Pin.IN, Pin.PULL_UP)
led1 = Pin(5, Pin.OUT)
led2 = Pin(18, Pin.OUT)

led1.off()
led2.off()
bz1 = Pin(21, Pin.OUT)
bz1.off()

gled = Pin(25, Pin.OUT)
rled = Pin(33, Pin.OUT)
speaker = Pin(26, Pin.OUT)

gled.off()
rled.off()
speaker.off()

def sw1234Read():
    workmode = 0
    if sw2.value() == 0: workmode |= 0x1
    if sw3.value() == 0: workmode |= 0x2
    if sw4.value() == 0: workmode |= 0x4

    return sw1.value(), workmode

WORKMODE_TIMER      =   0           # Check two line
WORKMODE_NULL1      =   1           #
WORKMODE_NULL2      =   2           #
WORKMODE_NULL3      =   3           #
WORKMODE_FRUIT      =   4           # Target is fruit,  check laser
WORKMODE_ANIMAL     =   5           # Target is Animal, check laser
WORKMODE_DIGIT1     =   6           # Target is digit,  check first pass
WORKMODE_DIGIT2     =   7           # Target is digit,  check first pass

SAMPLE_NUM = const(500)
ad1dim = [0] * SAMPLE_NUM
ad2dim = [0] * SAMPLE_NUM

LASER_THRESHOLD = 50000             # Laser light check threshold

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_LOW    = 250
AD34_CHECK_THRESHOLD_HIGH   = 500
AD34_CHECK_THRESHOLD        = AD34_CHECK_THRESHOLD_HIGH
ad3checktime = 0
ad4checktime = 0

sample_mode = 0                     # 0 : sample adc3, adc4

sample_point = 0
stop_flag = 0
total_count = 0

uart1 = UART(2, baudrate=115200, rx=16, tx=17, timeout=10)

DSCMD_NONE          = 0xff
DSCMD_HELLO         = 0x00
DSCMD_INIT          = 0x01
DSCMD_STARTSEND     = 0x10
DSCMD_STOPSEND      = 0x11
DSCMD_BEEP          = 0x12
DSCMD_SENDSNAPSHOT  = 0x13
DSCMD_TURNOFFLIGHT  = 0x14
DSCMD_SETCONTINUECHECK = 0x15
DSCMD_SETBEACONSEQUENCY = 0x16
DSCMD_BEACONSTART   = 0x17
DSCMD_BEACONSTOP    = 0x18
DSCMD_GETBEACONSTATE = 0x19
DSCMD_BEACONINIT    = 0x1a

DSRET_NCHECK        = 0x80
DSRET_CHECK         = 0x81
DSRET_LAST          = 0x82
DSRET_HELLO         = 0x90
DSRET_INIT          = 0x91

SENDFLAG_LAST       = 0x82
SENDFLAG_CHECK      = 0x81
SENDFLAG_NOCHECK    = 0x80
SENDFLAG_STOP       = 0xff
SENDFLAG_SNAPSHOT   = 0x83

def receCmd():
    if uart1.any() == 0: return DSCMD_NONE,0

    framebyte = uart1.read(4)
    if len(framebyte) != 4: return DSCMD_NONE, 0

    framelist = list(framebyte)
    time = int.from_bytes(framebyte[1:3], 'big')
    sumnum = sum(framelist[0:3]) & 0xff ^ 0xff

    if sumnum != framelist[3]: return DSCMD_NONE, 0
    return framelist[0], time

def sendCmd(cmd, time):
    senddim = [0x55,cmd]
    senddim.extend(list(time.to_bytes(4, 'big')))
    sumnum = sum(senddim)&0xff^0xff
    senddim.extend([sumnum])

    sendbytes = bytes(senddim)
    uart1.write(sendbytes)

def procCmd(cmd, time):
    global count32,sendflag,delay3s,count32,sendenableflag
    global initflag,lastcount32,snapshot32,speakercount,senddelay,sendcount

    if cmd == DSCMD_NONE: return

    if cmd == DSCMD_HELLO:
        sendCmd(DSRET_HELLO, 0x0)
        return

    if cmd == DSCMD_INIT:
        sendCmd(DSRET_INIT, 0x0)
        count32 = 0x0
        delay3s = time
        count3s = time

        initflag = 1
        lastcount32 = 0
        snapshot32 = 0

        sendcount = 0
        sendenableflag = 1
        sendflag = SENDFLAG_STOP

        return

    if cmd == DSCMD_STARTSEND:
        sendCmd(SENDFLAG_LAST, lastcount32)
        count3s = delay3s
        sendflag = 0x0
        sendenableflag = 0x1
        senddelay = time
        sendcount = 0

        return

    if cmd == DSCMD_STOPSEND:
        sendCmd(SENDFLAG_CHECK, count32)
        sendenableflag = 0
        sendflag = 0
        sendcount = 0
        return

    if cmd == DSCMD_BEEP:
        speakercount = 500
        return

    if cmd in (DSCMD_SETBEACONSEQUENCY,
               DSCMD_BEACONSTART,
               DSCMD_BEACONSTOP,
               DSCMD_GETBEACONSTATE,
               DSCMD_TURNOFFLIGHT,
               DSCMD_BEACONINIT):
        return

    print(cmd, time)

speakercount = 0
flash50mscount = 0
flash50inc = 0
resultflag = 0                      # 1 :OK; 2:ERROR; 0:NULL
buzzcount = 00

def resultOK():
    global resultflag, speakercount, flash50mscount, flash50inc

    resultflag = 1
    speakercount = 4500
    flash50mscount = 0
    flash50inc = 0

def resultERROR():
    global resultflag, speakercount, flash50mscount, flash50inc

    resultflag = 2
    speakercount = 4500
    flash50mscount = 0
    flash50inc = 0

def speaker1ms():
    global resultflag, speakercount, flash50mscount, flash50inc
    global detectflag1, detectflag2, detectcount, buzzcount

    if detectflag1 != detectflag2:
        detectcount += 1

    if buzzcount > 0:
        buzzcount -= 1

    if speakercount > 0:
        speakercount -= 1

        if speakercount == 0:
            if resultflag > 0:
                resultflag = 0
                rled.off()
                gled.off()

        flash50mscount += 1
        if flash50mscount >= 50:
            flash50mscount = 0
            flash50inc += 1

        if resultflag == 0:
            speaker.on()
        elif resultflag == 1:
            gled.on()
            speaker.on()
        elif resultflag == 2:
            if flash50inc & 0x1 == 0:
                rled.on()
                speaker.on()
            else:
                rled.off()
                speaker.off()

def sendTime():
    global count32,snapshot32,lastcount32,sendflag

    if sendflag == SENDFLAG_STOP:
        return

    if initflag == 0:               return

    if keepWorkMode > 0:
        sendCmd(sendflag, snapshot32)
        sendflag = SENDFLAG_STOP
        return

    timesend = count32
    if sendflag == SENDFLAG_LAST:
        timesend = lastcount32
    elif sendflag == SENDFLAG_CHECK or sendflag == SENDFLAG_NOCHECK:
        timesend = count32
    elif sendflag == SENDFLAG_SNAPSHOT:
        timesend = snapshot32
        sendCmd(SENDFLAG_SNAPSHOT, snapshot32)
        sendflag = SENDFLAG_NOCHECK
    elif keepWorkMode > 0:
        timesend = count32
        sendCmd(SENDFLAG_SNAPSHOT, snapshot32)
        sendflag = SENDFLAG_NOCHECK

    sendCmd(sendflag, timesend)
    sendflag = SENDFLAG_STOP

count32 = 0                         # Global 1ms counter
sendflag = SENDFLAG_STOP            # send flag
sendenableflag = 0                  # Enable send
senddelay = 100                     # Everay send period
sendcount = 0                       # count for send delay
delay3s = 3000                      # No check delay
count3s = 3000                      # count for no check delay
initflag = 0
lastcount32 = 0
snapshot32 = 0

detectflag1 = 0                     # Stand for line1 check
detectflag2 = 0                     # Stand for line2 check
detectcount = 0                     # Count the detectflag1 detectflag2 no equal

def ADC4Sample(_):
    global count32,sendenableflag,sendflag,senddelay,sendcount
    global delay3s,count3s,initflag,lastcount32,snapshot32
    global speakercount, keepWorkMode
    global detectflag1, detectflag2, buzzcount

    count32 += 1
    speaker1ms()

    if keepWorkMode == 0:
        if count32 & 0x100:
            led1.on()
        else: led1.off()
    else:
        if count32 & 0x80:
            led1.on()
        else: led1.off()

    if sendenableflag != 0:
        sendcount += 1
        if sendcount >= senddelay:
            sendcount = 0
            if sendflag == SENDFLAG_STOP:
                if count32 < delay3s:
                    sendflag = SENDFLAG_NOCHECK
                else: sendflag = SENDFLAG_CHECK
    else:
        sendcount += 1
        if sendcount >= senddelay:
            sendcount = 0
            if sendflag == SENDFLAG_STOP:
                sendflag = SENDFLAG_CHECK

    global ad1dim,ad2dim
    global sample_point
    global adc1,adc2,adc3, adc4
    global ad3average, ad4average, ad34point, ad3sigma, ad4sigma

    global ad3checktime, ad4checktime,total_count
    global ad3baseline, ad4baseline

    total_count += 1

    detectflag = 0

    if sample_mode == 1:
        ad1dim[sample_point] = adc1.read()
        ad2dim[sample_point] = adc2.read()

    if sample_mode == 0 or sample_mode == 1:
        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

        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
            detectflag = 1
            detectflag1 = 1
            if keepWorkMode == 6 or keepWorkMode == 7:
                gled.on()

        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
            detectflag = 1
            detectflag2 = 1

            if keepWorkMode == 6 or keepWorkMode == 7:
                rled.on()

    sample_point += 1
    if sample_point >= SAMPLE_NUM:
        sample_point = 0

    if detectflag > 0:
        buzzcount = 100
        bz1.on()

    if count3s >= delay3s:
        if sendenableflag > 0:
            if detectflag > 0:
                count3s = 1
                lastcount32 = count32
                snapshot32 = coutn32
                if keepWorkMode == 0:
                    count32 = 0
                sendflag = SENDFLAG_LAST
        else:
            if detectflag > 0:
                snapshot32 = count32
            count3s = 1

    else:
        if detectflag > 0:
            snapshot32 = count32
        count3s += 1

time0 = Timer(0)
time0.init(period=1, mode=Timer.PERIODIC, callback=ADC4Sample)

showcount = 0

keepThreshold,keepWorkMode = sw1234Read()
def initDevice():
    global sample_mode, detectflag1, detectflag2, detectcount
    global speakercount, flash50mscount, flash50inc, resultflag, buzzcount

    speakercount = 0
    buzzcount = 50
    flash50mscount = 0
    flash50inc = 0
    resultflag = 0                      # 1 :OK; 2:ERROR; 0:NULL

    detectflag1 = 0
    detectflag2 = 0
    detectcount = 0

    print("Initialize device:%d,%d"%(keepThreshold, keepWorkMode))

    if keepThreshold == 1:
        AD34_CHECK_THRESHOLD        = AD34_CHECK_THRESHOLD_LOW
    else:
        AD34_CHECK_THRESHOLD        = AD34_CHECK_THRESHOLD_HIGH

    led1.off()
    led2.off()
    bz1.off()

    gled.off()
    rled.off()
    speaker.off()

    if keepWorkMode in (4, 5):
        sample_mode = 1             # Sample adc1,2,3,4
    else: sample_mode = 0           # Sample adc3,4

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)

initDevice()

while True:
    threshold, workmode = sw1234Read()
    if threshold != keepThreshold or workmode != keepWorkMode:
        keepThreshold = threshold
        keepWorkMode = workmode
        initDevice()

    if button.value() == 0:
        time.sleep(0.01)
        if button.value() == 0:
            initDevice()
            while button.value() == 0:
                speakercount = 10

            time.sleep(.01)

    if keepWorkMode == 4:           # Fruit mode
        check1 = sample_amp(ad1dim)
        check2 = sample_amp(ad2dim)

        print((check1, check2))

        if check1 > LASER_THRESHOLD:
            if resultflag == 0:
                resultOK()

            detectflag1 = 0
            detectflag2 = 0

        if check2 > LASER_THRESHOLD:
            if resultflag == 0:
                resultERROR()
            detectflag1 = 0
            detectflag2 = 0

        if detectcount > 10000:
            detectflag1 = 0
            detectflag2 = 0
            detectcount = 0
            bz1.on()
            buzzcount = 200

        if detectflag1 > 0 and detectflag2 > 0:
            if resultflag == 0:
                resultERROR()

            detectflag1 = 0
            detectflag2 = 0
            detectcount = 0

    if keepWorkMode == 5:           # Animal mode
        check1 = sample_amp(ad1dim)
        check2 = sample_amp(ad2dim)

        if check1 > LASER_THRESHOLD:
            resultERROR()

        if check2 > LASER_THRESHOLD:
            resultERROR()

        if detectcount > 6000:
            detectflag1 = 0
            detectflag2 = 0
            detectcount = 0
            bz1.on()
            buzzcount = 200
        elif detectcount > 3000:
            bz1.on()
            buzzcount = 50

        if detectflag1 > 0 and detectflag2 > 0:
            if detectcount < 2500:
                resultERROR()
            else: resultOK()

            detectflag1 = 0
            detectflag2 = 0
            detectcount = 0

        if resultflag != 0:
            detectflag1 = 0
            detectflag2 = 0
            detectcount = 0

    if speakercount == 0:
        speaker.off()

    if buzzcount == 0:
        bz1.off()

    showcount += 1
    if showcount > 50:
        showcount = 0

    cmd,tm = receCmd()
    if cmd != DSCMD_NONE:
        led2.on()
        procCmd(cmd, tm)
        led2.off()

    sendTime()

    time.sleep_ms(1)


■ 相关文献链接:

● 相关图表链接:

猜你喜欢

转载自blog.csdn.net/zhuoqingjoking97298/article/details/125751476