基于深度学习的自动避障小车_5_运动控制

Introduction

本文说明了如何控制小车运动。只要给电机两个触点一个高电平一个低电平,电机即可运转,只是方向需要调试。如果是完全新手,请先阅读我博客之前的入门级教程:LED,温湿度等文章来了解树莓派相关的知识

raspberrypi基于深度学习的自动避障智能小车_目录

1. 控制代码表

小车的连接参考基于深度学习的自动避障小车_3_小车组装, 则相应的前轮的控制电平输出为:

IN1 IN2 IN3 IN4
前进 0 1 1 0
后退 1 0 0 1
左转 1 0 1 0
右转 0 1 0 1

(在写这篇博客的时候,因为小车已经拆掉了,怎么也对不起来了。后面如果再组装起来,就更新下映射表。这个表格可以自己测出来,由于连接方式可能不同,生成的映射表也同,根据实际连接情况自己测得即可)

2. 小车类

2.1 读取配置文件

为了使代码更整洁高效,我将配置单独写入了config.ini,利用最简单的ini配置文件模式。

小车上的配置文件内容如下:

# 如果是二驱的,则只需要将缺少的前驱/后驱全部置0
[front_engine]
out1=20
out2=21
out3=12
out4=16
[rear_engine]
out1=6
out2=13
out3=19
out4=26
[cam_server_ip]
# 这里的端口则是motion默认的控制端口
control_port=8080

其中control_port如前一章所述,是用来控制抓拍的端口。front_engine是前面两个轮子的四个接口,右边是pi GPIO的BCM编码,根据你的实际连接情况进行修改即可。rear_engine是后轮。

读取配置

cf = configparser.ConfigParser()
cf.read('config.ini')

my_car = Car(cf)
# 详细读取在后面的Car类里

2.2 小车类

import RPi.GPIO as GPIO
from collections import OrderedDict


class Car:

    def __init__(self, cf):
        # 这样生成的字典中元素按照插入的顺序排列
        self.out_mapping_port = OrderedDict()
        self.read_config(cf)
        self.stand_order = ['f_out1', 'f_out2', 'f_out3', 'f_out4']

    def read_config(self, cf):
        """读取配置文件映射端口"""

        if int(cf['front_engine']['out1']) != 0:
            # 读入的配置中,每个section中应该是有序的吧????不然ordereddict也就没用了。
            for key in cf['front_engine']:
                self.out_mapping_port['f_' + key] = int(cf['front_engine'][key])
        if int(cf['rear_engine']['out1']) != 0:
            for key in cf['rear_engine']:
                self.out_mapping_port['r_' + key] = int(cf['rear_engine'][key])
        GPIO.cleanup()
        GPIO.setmode(GPIO.BCM)
        for key in self.out_mapping_port:
            GPIO.setup(self.out_mapping_port[key], GPIO.OUT)

    def exec_operation(self, operation):
        """operation按照二进制位对应r_4,3,2,1 f_4,3,2,1前驱后驱的out端口"""
        for key in self.out_mapping_port:
            # print(key)
            GPIO.output(self.out_mapping_port[key], operation & 1)
            operation >>= 1

    def disconnect(self):
        # 清除针脚的状态,有点类似读写文件时的close
        GPIO.cleanup()

init函数主要是读入配置文件,out_mapping_port是轮子和GPIO口的映射,声明为有序字典可以保证在输出的时候,和添加元素的顺序是一致的。

exec_operation则直接将控制码映射到GPIO口上。采用了二进制的模式,相应位为1,表示该GPIO对应高电平,最后整体为一个数字(控制码),只需要传递这个控制码即可。

2.3 转弯一定角度

在本文最开始的控制码表中,只是列出了状态和代码,但是实际上,如果写入相应的状态后,小车会一直处于相应的“前进,后退,原地左转右转”,但由于地面粗糙程度的不同,要写统一固定的转弯时间是不可能的。但是在本项目中,先这样固定下来了。在实验环境下测试,旋转0.11s大概在60度角左右。在小车类里并没有控制转弯的时间,更详细的控制,在web_server项目里,entry.py文件,

def formulate_operation(oper):
    """发现bug:socket传输数据的时候,会将发送的数字指令重叠在一起发送,此函数将加入特殊标记,在server端根据这个特殊分隔符处理。"""
    return "_%s_" % str(oper)


class ControlSocket:
    def __init__(self, socket_ip):
# 省略部分代码
# 。。。

    def move(self, direction):
        """发送对应的方向指令给小车"""
        time_direction = {'forward': 0.8, 'left': 0.11, 'right': 0.11}
        print(direction)
        print(str(direction_code[direction]))
        self.socket.sendall(bytes(formulate_operation(direction_code[direction]), 'utf8'))
        sleep(time_direction[direction])
        self.socket.sendall(bytes(formulate_operation(direction_code['stop']), 'utf8'))

通过socket发送指令,第一个sendall发送了相应的指令给小车,然后sleep相应时间(直行0.8s,转弯0.11s),再发送一个停止指令。

Reference

13.10 读取配置文件

文章版权归 FindHao 所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明作者 FindHao 和本文原始地址:
https://www.findhao.net/easycoding/1826

你可能喜欢:(相似内容推荐和广告都使用了谷歌的推荐系统,需要对本站取消广告屏蔽才能显示。感谢点击↓广告支持博主~)

Find

新浪微博(FindSpace博客)QQ群:不安分的Coder(375670127) 不安分的Coder

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*