智能车项目设计实验报告

  |  

文章导航

大四上智能车项目设计实验报告

一、项目要求及准备

(一)项目要求

1.完成小车装配,了解硬件与操作系统,初步设计功能。 2.学习Linux常用命令,尝试编译、执行程序。 3.安装软件、学习控制各模块,学习GPIO相关知识。 4.学习电机相关知识,H桥、PWM等。 5.学习超声传感器相关知识,完成相关功能。 6.学习红外避障传感器,完成避障功能。 7.学习红外循迹传感器,完成循迹功能。 8.学习摄像头的使用,完成双线循迹。 9.根据已有传感器设计综合项目

(二)前期准备

  1. 根据老师提供的资料完成了小车的装配。

在装配小车的过程中我们发现小车有两块板子,主要控制部分为上面的树莓派板子,下面的板子和树莓派几乎没有关系(可能是因为学长学姐还车时没把线插好),在排查完后我们了解到下面的板子主要起到电机控制的功能,和其他部分关系不大,可以直接把传感器接在树莓派板子的GPIO口上。 2. 小车远程连接

这部分主要是小车Linux系统SSH和VNC远程连接配置的问题,在查阅相关资料以后得以解决。遇到的难题是把小车网络配置静态IP以后,每次不使用显示屏进行调试时,小车会自动连接默认WiFi。我们发现小车在路由器、手机、电脑构成的局域网下默认IP地址是不同的,以我们测试的设备为例:路由器192.168.1.x、电脑192.168.137.x、手机192.168.43.x,这与不同设备所能承载的最大连接数有关,所以在更换设备后会出现无法连接的情况。

  1. GPIO和Linux操作指令的学习

    这一部分主要是各自查阅资料进行学习,Linux系统不同于我们常用的Windows系统,它的绝大部分工作是靠命令行来完成的,这样简化了许多不必要的操作,保证了系统运行的稳定性。 小车引脚一共有40个,但不是所有引脚都可以作为IO口,经过查阅技术手册,我们得到了对应的引脚图。

  1. 小车的初步试运行

我们将小车安装完成以后进行了进一步的测试,主要是连接了小车与显示器,配置了远程连接,通过浏览器访问的方式测试了摄像头的状态,经过一系列的学习和初步调试,我们已经初步掌握了小车调试的方法,接下来就是进一步的工作。

二、调试过程

(一)摄像头模块

  1. 读入摄像头照片
1
2
3
import cv2
cap = cv2.VideoCapture(0)
ret, frame = cap.read()

我们使用python中的opencv库读入摄像头数据,cv2.VideoCapture(0)中的参数0表示是系统默认的摄像头,ret为布尔值,true表示读取正常,frame为三维rgb矩阵。cv2.cvtColor(), cv2.threshold()将图像二值化为黑白图,一共进一步处理。默认像素640×480。

  1. 循迹核心代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for i in range(num_point):
    detect_height = height - 15 * (i+1)
    left_area = dst[detect_height, 0: half_width-1]
right_area = dst[detect_height, half_width: width-1]
    left_line = np.where(left_area == 0)
    right_line = np.where(right_area == 0)

    if len(left_line[0])!=0:
        left_point[i] = int(np.max(left_line))  
    else:
        left_point[i] = 0 
    if len(right_line[0])!=0:
        right_point[i] = int(np.min(right_line))
    else:
        right_point[i] = half_width - 1            
    left_max = np.max(left_point)
    right_min = np.min(right_point)

核心逻辑: i值为选取的行数,我们读取摄像头照片的后几行,每个间隔为15像素,然后取最值(避免噪声的干扰)。 将照片分为左右两部分,左边取像素为0的列坐标最大值,右边取像素为0的列坐标最小值,达到检测赛道的目的(蓝线)。 当小车行驶到将要转弯的地方时,(假设将要左转)那么此时左侧的赛道将会消失,取而代之的是右侧赛道检测值向左偏。 当检测到一侧赛道消失时,控制小车向这个方向转弯。而弯道的大小由另一侧偏离的量决定,将这个值传递给小车转弯控制函数作为参数,即可实现小车的实时控制。 3. 左右转函数 左右转函数在后面原理相同,只是参数不同,在此先叙述原理。 小车电机控制由四个端口输出的值来决定,将端口使能后,分别将其命名为pwm1-pwm4。经过测试我们发现,pwm1值不为0时,小车左边前后轮正转;pwm2不为0时,小车左边前后轮反转;pwm3值不为0时,小车右边前后轮正转;pwm4不为0时,小车右边前后轮反转。通过修改pwm1和pwm3的参数即可控制左右转的程度。

1
2
3
4
5
6
7
8
9
10
def right(left_distance):  # 右转
    pwm1.ChangeDutyCycle(max(50,min(left_distance,320)/5))
    pwm2.ChangeDutyCycle(0)
    pwm3.ChangeDutyCycle(0)
    pwm4.ChangeDutyCycle(0)
def left(right_distance):  # 左转
    pwm1.ChangeDutyCycle(0)
    pwm2.ChangeDutyCycle(0)
    pwm3.ChangeDutyCycle(max(50,min(right_distance,320)/5))
    pwm4.ChangeDutyCycle(0)

内部min函数保证左右两边传入参数不大于320,除以5是为了和pwm的区间相对应;外部max函数保证即使传入参数很小,小车也可以以50%的占空比进行转弯,因为我们测试发现,当占空比很小时,小车由于阻尼比较大,无法正常前进,所以使用此方法保证可以行进。

(二)红外循迹模块

  1. 循迹原理 红外循迹传感器原理不用多说,无非就是没检测到黑线为低电平,检测到为高电平。
  2. 核心代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SR = gpio.input(RIGHT)
SL = gpio.input(LEFT)
# print("SR={},SL={}".format(SR,SL))
if (SL == 0 and SR == 0)or(SL == 1 and SR == 1):  # 未检测到,直行
    print("go1")
    run()
elif SL == 1 and SR == 0:  # 左传感器检测到,左转
    print("left")
    left()
elif SL == 0 and SR == 1:  # 右传感器检测到,右转
    print("right")
    right()
elif SL == 1 and SR == 1:  # 两边同时检测到
    print("go2")
    run()

此代码逻辑很简单,即:左边检测到就往左转,右边检测到就往右转,两边都没有检测到就直行,两边都检测到也直行。 3. 使用的端口 GPIO.36 左红外传感 GPIO.32 右红外传感 (使用BOARD模式) 4. 遇到的问题 刚开始忘记强制上拉下拉引脚,导致刚开始出了问题,当右传感器一检测到就会停车,后来发现这是因为很多IO由于CMOS工艺问题会出现float的现象,所以不能悬空,需要PU或PD。对于红外引脚,未检测到障碍时为低电平,我们选择下拉,避免浮动。 使用语句:

1
2
gpio.setup(RIGHT_infrare_sensor,gpio.IN,pull_up_down=gpio.PUD_DOWN)
gpio.setup(LEFT_infrare_sensor, gpio.IN,pull_up_down=gpio.PUD_DOWN)

(三)红外避障模块

  1. 避障传感器原理 原理也很简单无需赘述,有障碍为低电平,否则为高电平。 当时调试传感器比较费事,主要调节方法为:将传感器对着被测物体,物体和传感器的距离为想要的灵敏距离。将502可调电阻反时针调节到最大,将103电阻慢慢的旋转一圈直至led刚变亮
  2. 核心代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def hongwai(): #红外避障
    while (1):
        SR = gpio.input(RIGHT_infrare_sensor)
        SL = gpio.input(LEFT_infrare_sensor)
        if SL == 0 and SR == 0:
            back()
            time.sleep(1)
            left()
            time.sleep(1)
        elif SL == 1 and SR == 0:
            left()
        elif SL == 0 and SR == 1
            right()
        elif SL == 1 and SR == 1:
            run()

原理也相当简单:左边检测到向右转,右边检测到向左转,避开将要遇到的障碍物。当两边都没有检测到就直行。两边都检测到就先后退,执行一段时间的延时,然后再左转。 3. 使用的端口 GPIO.33,GPIO.35为左右传感端口。(BOARD模式)

(四)超声波模块

  1. 超声测距原理 模块自动发送8个40khz的方波,自动检测是否有信号返回 有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。 测试距离=(高电平*声速(340m/s)/2)
  2. 核心代码
1
2
3
4
5
6
7
8
9
10
11
12
def disMeasure():
    gpio.output(Trig,gpio.LOW)
    time.sleep(0.001)
    gpio.output(Trig,gpio.HIGH)
    time.sleep(0.001)
    while (gpio.input(Echo)!=1){
        start=time.time()
    }
    while(gpio.input(Echo)!=0){
        stop=time.time()
    }
    return (stop-start)*340/2

主要思想就是检测ECHO的时间从而得到模块与障碍物的距离,后面的逻辑可以根据这个距离进行判断是否应该规避。 实际测试中我们发现超声模块的效果很不好,经过查阅资料我们发现应该和温度传感器一起使用,以确定当时的具体声速,才能获得精确的距离,而且该超声模块比较廉价,精度本身就不高。 3. 使用的端口 超声模块占据引脚的38以及40端口,用于发送触发信号TRIG以及接收回声信号ECHO(BOARD模式)

(五)语音识别模块

  1. 模块原理

LD3320A是一颗基于非特定人语音识别技术的语音识别/声控芯片。LD3320 芯片上集成了高精度的 A/D 和 D/A 接口,不再需要外接辅助的 Flash 和 RAM,即可以实现语音识别/声控/人机对话功能。并且,识别的关键词语列表是可以动态编辑的。

上面是抄说明书的,没什么用。

我们只需要知道:

模块基于C语言编写,可以识别自定义语句(无音调),可以控制IO口返回相应的高低电平,我们根据返回的三位二进制数解码出对应的指令,进行小车行为的控制。

  1. 核心代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def voice():
    while(1):
        p1 = gpio.input(port1)
        p2 = gpio.input(port2)
        p3 = gpio.input(port3)
        function=4*p1+2*p2+p3
        if function==6:
            run()
            print("run")
            time.sleep(5)
            stop()
            time.sleep(3)
        elif function==5:
            back()
            print("back")
            time.sleep(5)
            stop()
            time.sleep(3)
elif function==4:
            left()
            print("left")
            time.sleep(5)
            stop()
            time.sleep(3)
        elif function==3:
            right()
            print("right")
            time.sleep(5)
            stop()
            time.sleep(3)
        elif function==7:
            stop()
            print("stop")
        elif function==2:
            print("xunxian")
            xunxian()
        elif function==1:
            print("bizhang")
            hongwai()
        else:
            print(“wait")

核心逻辑很好理解:定义function,将二进制翻译为十进制数,使用判断语句,找到对应的指令,进入相应的功能模块。 对应指令: 0:等待(空转默认状态) 1:红外避障 2:红外循迹 3:右拐 4:左拐 5:后退 6:前进

  1. 引脚设置 GPIO.7 ,GPIO.11 ,GPIO.13为传感器返回识别结果端口。 (BOARD模式)

三、成果展示

(一)主要成果

经过不断的调试,我们的小车不仅在自己的赛道上表现良好,在同学搭建的其他赛道(宽度、形状完全不同)也运行顺畅,仅需要根据具体赛道对参数做细微修正。 传感器的单独调试效果也很好,我们让每个传感器都物尽其用。 我们的综合功能设计也做得很好,在语音控制下可以做出前进、后退、左拐、右拐、循迹、避障等等行动。实现了完全的语音控制。

(二)视频展示

主要视频展示在答辩时已经进行过了,现附在附录文件夹中,完整版合集视频投稿在哔哩哔哩视频网,链接如下: https://www.bilibili.com/video/BV1Kp4y1x7Hu

(三)课件汇报

主要为两部分,之前课堂汇报的课件和最终答辩的课件,具体内容也附在附件里面了。

四、主要承担的工作

作为大学本科阶段的最后一个实验,也是战线长达一学期的项目设计实验,我们小组展现了很好的团队精神。大家一起攻坚克难,一起想控制逻辑,一起调传感器,一起学习知识,一起调参。最终结果可能并不是最亮眼的,但是我们应该是没有遗憾了。 在这次项目设计实验中,我和其他四位同学一起商讨策略,一起完成任务,一起拓展创新,在过程中学到了很多。在后面主要负责小车调参、传感器功能实现和视频剪辑工作。熬过夜,扛着赛道到处找教室调车,也因为验收临时改赛道而心态爆炸。但是我们都坚持了下来,最后汇报呈现出来的结果可能不那么理想,但拼搏精神是最大的收获!

本站总访问量 您是第位访客