基于声音和视频的人跟随自动驾驶汽车- smart_car(PC控制)

smart_car

https://github.com/jamesshao8/smart_car

smart_car

How to install:

  1. download the raspberry image for with pre-installed respeaker drivers: https://pan.baidu.com/s/1bprWJr5 password:t1m7
  2. copy gcc_phat.py included in this repository to the folder in voice engine where there is a file with the same name
  3. find the setup.py and type "sudo python setup.py install"
  4. you will also need to install opencv and arduino, they can all be installed through apt-get

Then all the libraries from 3rd party has been installed. Below is the steps for my own program:

  1. download the smart_arduino.ino to the arduino uno
  2. then run smart_raspberry.py on raspberry pi

Here's the video when running http://v.youku.com/v_show/id_XMzQwNzYzMjYyMA==.html

For hardware assembly, please refer to my blog: http://blog.csdn.net/shukebeta008/article/month/2018/02

如何安装:

  1. 下载预先安装的respeaker驱动程序的镜像: https ://pan.baidu.com/s/1bprWJr5密码:t1m7
  2. 将此存储库中包含的gcc_phat.py复制到语音引擎中具有相同名称的文件的文件夹中
  3. 找到setup.py并输入“sudo python setup.py install”
  4. 你还需要安装opencv和arduino,它们都可以通过apt-get安装

然后安装了第三方的所有库。以下是我自己的程序的步骤:

  1. 将smart_arduino.ino下载到arduino uno
  2. 然后在raspberry pi上运行smart_raspberry.py

这是运行http://v.youku.com/v_show/id_XMzQwNzYzMjYyMA==.html时的视频

代码:

元器件材料清单:

树莓派 *1

arduino UNO or Nano *1

L298N电机驱动模块 *1

前后轮马达 各1

转向马达 *1

7.2V锂电池 (电机驱动供电)

充电宝 5V 2A (树莓派)

手机USB线

USB-typeB

快换接头 *1

杜邦线

超声波

USB摄像头

越野车底盘

接线:

树莓派 :

microUSB - 5V 2A充电宝

USB - USB摄像头

USB - arduino UNO(树莓派给UNO板供电)

树莓派GPIO - respeaker模块

arduino UNO   L298N电机驱动模块

5       IN1

6        IN2

9        IN3

10       IN4

GND   GND

VIN    +5V

arduino UNO 超声波模块

5V     VCC

8       (EchoPin, INPUT)

7        (TrigPin, OUTPUT)

GND    GND

L298N电机驱动模块

UNO接USB供电,输出电流比较弱,可能无法驱动电机,需要 5V输入 端口,独立供电,

5V输入   UNO

GND    GND

+5V      VIN

A              前后轮马达(两个合一供电)

OUT1      马达 正极+ 红线

OUT 2      马达 负极-  黑线

B               转向马达

OUT3      马达 正极+ 红线

OUT 4     马达 负极-  黑线

主电源      7.2V锂电池

+12V     正极+

GND      负极-

2:驱动直流电机
由于本模块是2路的H桥驱动,所以可以同时驱动两个电机,接法如图所示
使能ENA ENB之后,
可以分别从IN1 IN2输入PWM信号驱动电机1的转速和方向
可以分别从IN3 IN4输入PWM信号驱动电机2的转速和方向
信号如图所示

直流电机

旋转方式

IN1

IN2

IN3

IN4

调速PWM信号

调速端A

调速端B

M1、M2前后

正转

/

/

/

反转

/

/

/

停止

/

/

/

M3左右转向

正转

/

/

/

125

反转

/

/

/

125

停止

/

/

/

如果要做电机调速,还可以让Arduino输出PWM波,而不是恒定的5V电平,达到控制速度的效果(本项目暂时没有用)。

原理图:

使用Protues进行Arduino仿真——Blink

https://blog.csdn.net/youshenmebutuo/article/details/76692332

Arduino UNO仿真开发环境设置和仿真运行

https://www.cnblogs.com/hyper99/p/Arduino-UNO-fang-zhen-kai-fa-huan-jing-she-zhi-he-.html

CAD Circuits  thinker 在线仿真

https://www.tinkercad.com/things/442uq6V3DTr-blink-an-led-with-digital-output/editel?collectionid=OMOZACHJ9IR8LRE&lessonid=EIC0NAWJD0K8S1O&magic=e9f406e30e1526317c5202afc57a743bd6f83ef7&projectid=OMOZACHJ9IR8LRE&t=1535065144290658858&tenant=circuits#/lesson-viewer

代码:

(主要本例为越野底盘,前后轮由5、6控制正反转,转向由9、10控制左右)

    正转  反转  左转  右转  左后  右后

5    高    低      高      高      低      低

6   低     高      低      低      高      高

9   低     低      高      低      高      低

10  低    低      低      高      低      高

arduino:

int led = 13;
//float duration;                
//float distance;              
//int srfPin = 8;

const int TrigPin = 7; //发出超声波
const int EchoPin = 8; //收到反射回来的超声波
float cm; //因为测得的距离是浮点型的
 
void setup() 
{
    Serial.begin(9600);
    pinMode(led, OUTPUT); 
    pinMode(9,OUTPUT);
    pinMode(10,OUTPUT);
    pinMode(5,OUTPUT); 
    pinMode(6,OUTPUT);

    pinMode(TrigPin, OUTPUT); 
    pinMode(EchoPin, INPUT); 
    
    
}
void loop()
{
    delay(100);               // wait for a second
    
    if (Serial.available()>0)
    {
      char cmd = Serial.read();
      Serial.print(cmd);
      Serial.println(); 
      switch (cmd)
      {
        case '1':
            Forward();
            break;
        case '2':
            Back();
            break;
        case '3':
            Turn_left();
            break;
        case '4':
            Turn_right();
            break;
        case '6':
            Measure();
            break;
        case '7':
            Turn_left_Back();
            break; 
        case '8':
            Turn_right_Back();
            break;
        case '9':
            Stop();
          
        default:
            Stop();
      }
    }
}
void Forward()
{
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
}
void Back()
{
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}
void Turn_right()
{
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
}
void Turn_left()
{
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
}
 

void Turn_left_Back()
{
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}

void Turn_right_Back()
{
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}

void Stop()
{
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
}
 
void Measure()
{
      /*
      pinMode(srfPin, OUTPUT); 
      digitalWrite(srfPin, LOW);            
      delayMicroseconds(2); 
      digitalWrite(srfPin, HIGH);           
      delayMicroseconds(10); 
      digitalWrite(srfPin, LOW);            
      pinMode(srfPin, INPUT); 
      duration = pulseIn(srfPin, HIGH);         
      distance = duration/58;       
      Serial.println(distance);     
      delay(50); */  

    digitalWrite(TrigPin, LOW); //低高低电平发一个短时间脉冲去TrigPin 
    delayMicroseconds(2);       // delayMicroseconds在更小的时间内延时准确
    digitalWrite(TrigPin, HIGH); 
    delayMicroseconds(10); 
    digitalWrite(TrigPin, LOW); //通过这里控制超声波的发射
	
    cm = pulseIn(EchoPin, HIGH) / 58.0; //将回波时间换算成cm 
    cm = (int(cm * 100.0)) / 100.0; 保留两位小数 
    Serial.print("Distance:"); 
    Serial.print(cm); 
    Serial.print("cm"); 
    Serial.println(); 
    delay(50); 
}

树莓派:

#!/usr/bin/env python
import socket
import sys
import threading
import random
import os
import time
import struct
import serial
 
 
 
 
#import cv
#import Image,StringIO
 
 
port_serial="/dev/ttyACM0"
sl = serial.Serial(port_serial,9600)
 
 
HOST = "0.0.0.0"
PORT = 9004
SOCK_ADDR = (HOST, PORT)
exit_now = 0
 
 
 
 
def exit_signal_handle(sig,stack_frame):
    global exit_now
    print "EXIT sig"
    exit_now = 1
 
 
class serial_thread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        self.running = True
        while self.running:
            try:
                data=sl.readline()
                print data
            except:
                print sys.exc_info()
 
 
    def stop(self):
        self.running = False
 
 
def forward():
    print "forward"
    string="1"
    sl.write(string)
 
 
def reverse():
    print "reverse"
    string="2"
    sl.write(string)
 
 
def pivot_left():
    print "left"
    string="3"
    sl.write(string)
 
 
def pivot_right():
    print "right"
    string="4"
    sl.write(string)
 
 
def stop():
    print "stop"
    string="0"
    sl.write(string)
 
 
 
 
    
def net_input(command):
    global laser_index_vertical
    global laser_index_horizontal
   
    if command == 1:
        forward()
    elif command == 2:
        reverse()
    elif command == 3:
        pivot_left()
    elif command == 4:
        pivot_right()
    elif command == 0:
        stop()
 
 
###
 
 
class SocketClientObject(object):
 
 
    def __init__(self, socket, address ):
        self.socket = socket
        self.address = address
 
 
###
 
 
class ClientThread(threading.Thread):
    def __init__(self, client_object):
        threading.Thread.__init__(self)
        self.client_object = client_object
 
 
    def run(self):
        self.running = True
        while self.running:
            data = self.client_object.socket.recv(1024)
            print ">> Received data: ", data, " from: ", self.client_object.address
            
            if(data=='0'):
                net_input(0)            
            elif(data=='1'):
                net_input(1)
            elif(data=='2'):
                net_input(2)
            elif(data=='3'):
                net_input(3)
            elif(data=='4'):
                net_input(4)
            elif(data=='5'):
                break
        print "client_quit"
 
 
        self.client_object.socket.close()
 
 
    def stop(self):
        self.running = False
        
###
 
 
 
 
   
 
 
def main():
    ser_th = serial_thread()
    ser_th.start()
 
 
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(SOCK_ADDR)
        sock.listen(5)
 
 
        
 
 
 
 
        while exit_now == 0:
            # accept connections from outside
            (clientsocket, address) = sock.accept()
            print " Accept client: ", address
            # now do something with the clientsocket
            # in this case, we'll pretend this is a threaded server
            ct = ClientThread(SocketClientObject(clientsocket, address))
            ct.start()
        
 
 
 
 
    except:
        print "#! EXC: ", sys.exc_info()
        #sock.close()
        #ser_th.stop()
        #ser_th.join()
        print "THE END! Goodbye!"
 
 
###
 
 
if __name__ == "__main__":
 
    main()

PC端 控制程序::

#!/usr/bin/env python
import socket
import time
import pygame
import cv2.cv as cv  
import PIL.Image, StringIO  
import threading
 
 
import cv2
import numpy as np
 
 
 
 
def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('192.168.1.10',9004))
    pygame.init()
    W, H = 320, 240
    screen = pygame.display.set_mode((W, H))
    clock = pygame.time.Clock()
    running = True
    command_to_send=0
    command_last=0
    laser_control = False
    while running:
        command_last=command_to_send   
 
 
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                command_to_send=5
                running = False
            elif event.type == pygame.KEYUP:
                command_to_send=0
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    command_to_send=1
                elif event.key == pygame.K_DOWN:
                    command_to_send=2
                elif event.key == pygame.K_LEFT:
                    command_to_send=3
                elif event.key == pygame.K_RIGHT:
                    command_to_send=4
         
        if(command_to_send!=command_last):
            sock.send(str(command_to_send))
 
 
        clock.tick(50)
 
 
 
    sock.close()
 
 
 
 
if __name__ == '__main__':
    main()

小车arduino中运行的代码(只包含控制部分,不含超声波):

int led = 13;
 
 
void setup() 
{
    Serial.begin(9600);
    pinMode(led, OUTPUT); 
    pinMode(9,OUTPUT);
    pinMode(10,OUTPUT);
    pinMode(5,OUTPUT); 
    pinMode(6,OUTPUT);
    
    
}
void loop()
{
    //digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(100);               // wait for a second
    //digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    //delay(1000);               // wait for a second
    
    if (Serial.available()>0)
    {
      char cmd = Serial.read();
      Serial.print(cmd);
      switch (cmd)
      {
        case '1':
            Serial.println("Forward");
            Forward();
            break;
        case '2':
            Serial.println("Back");
            Back();
            break;
        case '3':
            Serial.println("Left");
            Turn_left();
            break;
        case '4':
            Serial.println("Right");
            Turn_right();
            break;

        case '7':
            Serial.println("left_Back");
            Turn_left_Back();
            break; 
        case '8':
            Serial.println("right_Back");
            Turn_right_Back();
            break;

        default:
            Stop();
      }
    }
}
void Forward()
{
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
}
void Back()
{
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}
void Turn_right()
{
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
}
void Turn_left()
{
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}

void Turn_left_Back()
{
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}

void Turn_right_Back()
{
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}

 
void Stop()
{
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
}

实物接线图:

具体操作:

1、UNO 通过USB连接电脑,打开.ino后缀的arduino文件,编译检查,上传烧录;

2、断开USB连接,进行断电接线;

3、先进行USB端口+UNO控制,超声波有数据返回,马达只是发出吱吱声并未转动,单个马达测试,低速转动,轻轻捏轴就能止动,用电压表测得L298N电机驱动模块 OUT1、OUT2输出电压为2V;刚开始还以为是程序出错或模块漏电,经排查后推断可能是供电不足,面包板5V电源输入后,测试马达加速运转,用L298N电机驱动模块 5V输入 端口供电后,马达正常转动。

左右转向测试过程中,已经break,车子停止,但马达扔低速运转,发出吱吱声,随优化下程序,虽然默认stop状态,但启动之后,增加case '9',可以通过COM串口 强制停止  Stop();实验证明,测试过程中随时终止马达运转,非常有效;


         

接下来arduino板子通过USB与树莓派连接通信:、

参考链接:

Arduino与树莓派间的通信实践

https://blog.csdn.net/ydogg/article/details/53307365

树莓派与arduino通信

https://blog.csdn.net/u011577439/article/details/51762076

树莓派与arduino通过USB进行通信 具体操作:

1、安装需要的库搭建环境:(GPIO库、arduino库、serial、minicom)本例已经安装好GPIO库,还没安装的按上述参考链接自行安装;

安装serial,用于串口或者USB通信

sudo apt-get install python-serial

安装串口调试工具

sudo apt-get install minicom 

安装arduino库

sudo apt-get install arduino

2、将Arduino用USB线连接到树莓派的USB,在树莓派中输入

ls /dev/tty*

3、看有没有ttyUSB0或者ttyUSB1生成,如果两者没有连接是不会自动生成这个文件的,看到说明两者可以通讯了。(本例UNO 通过USB连接树莓派,并没有看到ttyACM0。)

查看有没有ttyACM0 这个文件(注只有在两个硬件USB互连的情况下才会有这个。如果两者没有连接是不会有的) 最新的系统一般都会自动生成。看到ttyACM0就说明二者可以通讯了 接下来上测试代码。(两个硬件USB互连的情况,具体选择,根据自己的链接方式来判断吧)

4、根据实际的端口情况修改树莓派代码;本例通过 ls /dev/tty* ,查看到ttyUSB0;

代码修改:把默认的 ttyACM0 改为 ttyUSB0 即可;

5、在树莓派上运行测试:

sudo python2 /home/pi/Desktop/smart_car-master/pi_part.py

运行后进入“假死”状态,其实是在等待PC端接入;

PC端环境搭建链接:

6、在PC端上运行控制端程序PC.py:

 python /home/python/Desktop/PC.py 

树莓派上看到接入信息:

PC端点击 pygame window,按 方向键 上下左右 控制:

树莓派端响应:

树莓派+arduino+小车测试流程:

1、确认arduino与小车各硬件连接正常后,L298N接入7.2V电池;USB自带供电太鸡肋,小车不能正常启动;

2、UNO通过USB链接树莓派;5V 2A充电器USB连接树莓派供电;

3、ssh进入树莓派,启动测试程序:

sudo python2 /home/pi/Desktop/smart_car-master/pi_part.py

4、打开虚拟机PC端,启动PC.py进入键盘控制:

python /home/python/Desktop/PC.py 

5、鼠标点击 pygame控制窗口,按 上下左右 键进行控制;

7、关闭 pygame窗口,PC端程序自动退出,树退出莓派端程序提示用户端退出;

Ctrl+c接收树莓派端程序,完成测试:

整车测试:

千万不要用越野车底盘做智能小车,丑到它爸都不承认是亲生的,重心过高,7.2V锂电池+5V 2A充电宝,太重太高,跑起来往一边侧,根本无法体验越野性能,还是用正常4个减速电机的底盘比较稳妥。

猜你喜欢

转载自blog.csdn.net/jacka654321/article/details/81951470
今日推荐