自动跟随机器人教程(四)软件部分 树莓派+电脑 控制小车移动

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shukebeta008/article/details/79335279

接下来可以说是本教程的核心内容了,不可能在一篇文章中讲完,首先讲一个比较初级的程序。树莓派可以接收同一个局域网上电脑的连接,并且电脑键盘上发出的前后左右的控制信号通过网络发向树莓派后,树莓派再经过串口发向Arduino,对电机进行控制。


树莓派需要实现的程序分为两部分,一个是Socket服务器,另一个是串口写入的代码。涉及到多线程知识。

客户端程序作为Socket客户端连入树莓派,然后通过pygame库获取键盘命令后把运动指令发往树莓派。


树莓派的程序稍微复杂些,首先主循环是监听客户端连入,连入后用另一个线程对从客户端发来的数据进行处理,把指令用串口下发给Arduino。当指令涉及到超声波读取时,树莓派用另一个线程去监听串口收到的数据,这个数据就是距离数据(为了尽量简化,下面的代码范例中不含超声波读取部分,完整部分参见后面教程中的最终程序)。


下面贴上部分代码:

首先是运行于小车树莓派中的程序:

#!/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()

接下来是电脑控制端运行的程序:

#!/usr/bin/env python
import socket
import time
import pygame
import cv2.cv as cv  
import 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;
        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 Stop()
{
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
}

猜你喜欢

转载自blog.csdn.net/shukebeta008/article/details/79335279