基于TensorFlow2.x卷积神经网络的智能小车寻迹

概述

        在写OpenCV+TensorFlow简单的机器小车传统视觉寻迹之时,可以预见的是,由于环境因素,传统小车寻迹的效果可能会受到环境因素的影响,例如地上的污渍在进行二值化时就有可能出现噪音。本次将采用卷积神经网络,训练出一个简单较好的模型,在寻迹上会有更加突出的效果。以下图片操作由OpenCV完成。

        接下来将分为数据集,卷积神经网络,神经网络的训练,网络模型的保存以及测试。

话不多说,直接上测试

 

数据集

初始数据集的构建

        从智能小车寻迹任务来说,可以大致分为前进,左转,右转这三个命令。因此在制作数据集的时候就只需要3个label标签。

        在制作时,我沿用的还是以前的想法,通过opencv将得到的图片进行二值化,然后将图片交给神经网络来处理。主要包含以下的考虑。

  • 由于在寻迹的时候由于场地灯光等因素,在制作都满足这些情况的数据集的时候,会过于庞大,并且夹杂环境因素的影响,可能导致神经网络的过拟合(记住一些没用的特征)。
  • 在我现在的使用场景来看,其实并不需要这么复杂的数据集。当然本文仅做启发,如有需要自己拓展起来也是非常的容易

         如上图所示,我是用电脑自带的画图软件,进行构建的。这些图作为基础的数据集,之后还会在此之上进行旋转平移等操作,进一步扩大数据集。做的图是符合寻迹过程中完美的二值化的样子。

        在学习机器学习的过程中,大多数的文章运用的mnist手写数字、CIFAR10数据集,但是在自己构建数据集的时候,基础数据集的构建需要自己完成。

数据集的扩展

        数据集过少,在实际应用过程中可能出现过拟合,模型对训练集死记硬背,没有理解数据背后的规律,泛化能力差。由于初始数据集是基于完美的二值化之后的图像创建的,训练数据的噪音干扰足够小;在后续中可以看到该自定的模型也并不复杂;因此解决过拟合最好的办法就是增加样本数量。

        增加样本的数量有很多:旋转,平移,遮挡,缩放等等。对于智能小车寻迹来说,旋转和平移是最符合,也是有最直接需求的方法。

 旋转

        由于不影响小车正确的前进路线,这里的旋转只能进行稍微的旋转,否则容易引起方向的误判。我这里旋转角度为±4°之内。

# 开发作者   :Tian.Z.L
# 开发时间   :2022/3/14  14:48 
# 文件名称   :PictureGetter.PY
# 开发工具   :PyCharm
import cv2
import os

index_1 = 1  # 直行的图片索引
index_2 = 1  # 左转图片的索引
index_3 = 1  # 右转图片的索引
path = "C:/Users/TianZhonglin/Desktop/labPatentProject/TensorFlowLearnning/AutoDriver/DataSet"  # 文件夹目录
files = os.listdir(path)  # 得到文件夹下的所有文件名称
for file in files:
    img = cv2.imread("./DataSet/" + str(file))  # 读取彩色图像(BGR)
    # 切割文件名称,例如1_1.png为直行,最前面的1为该图片的类别
    own = str(file).split('_')[0]   
    center = (640 // 2, 480 // 2)
    if own == '1':
        index = index_1
        index_1 += 10
    elif own == '2':
        index = index_2
        index_2 += 10
    else:
        index = index_3
        index_3 += 10
    for i in range(5):
        M = cv2.getRotationMatrix2D(center, -i, 1.2)
        rotated = cv2.warpAffine(img, M, (640, 480), borderValue=(255, 255, 255))
        ret, binary = cv2.threshold(rotated, 200, 255, cv2.THRESH_BINARY)
        cv2.imwrite('./after/' + own + '_' + str(index).zfill(5) + '.jpg', binary)
        index += 1
    for i in range(5):
        M = cv2.getRotationMatrix2D(center, i, 1.2)
        rotated = cv2.warpAffine(img, M, (640, 480), borderValue=(255, 255, 255))
        ret, binary = cv2.threshold(rotated, 200, 255, cv2.THRESH_BINARY)
        cv2.imwrite('./after/' + own + '_' + str(index).zfill(5) + '.jpg', binary)
        index += 1
print('success')

        将所有的图片进行旋转,得到的图片被我放在另一个空文件夹中。因为之后在制作数据集的时候为了方便样本图片的分类,所以需要对索引进行严格的管理,保证每个类别的样本名称是顺序的。

图片平移

        同样,为了尽可能满足小车实际的行使,平移的间距不宜过大也不宜太小。样本图片大小为640*480,我这里选择左右平移50像素以内。

        

# 开发作者   :Tian.Z.L
# 开发时间   :2022/3/14  20:23 
# 文件名称   :move.PY
# 开发工具   :PyCharm
# 图像平移 (Translation transform)
import cv2
import numpy as np
import matplotlib.pyplot as plt
import os

index_1 = 111  # 接着旋转之后直行的索引
index_2 = 61  # 接着旋转之后左转的索引
index_3 = 101  # 接着旋转之后右转的索引
path = "C:/Users/TianZhonglin/Desktop/labPatentProject/TensorFlowLearnning/AutoDriver/after"  # 文件夹目录
files = os.listdir(path)  # 得到文件夹下的所有文件名称
for file in files:
    img = cv2.imread("./after/" + str(file))  # 读取彩色图像(BGR)
    own = str(file).split('_')[0]
    center = (640 // 2, 480 // 2)
    # index = 4
    if own == '1':
        index = index_1
        index_1 += 10
    elif own == '2':
        index = index_2
        index_2 += 10
    else:
        index = index_3
        index_3 += 10
    rows, cols, ch = img.shape
    for i in range(5):
        dx, dy = (i + 1) * 10, 0  # 向右偏移量,
        MAT = np.float32([[1, 0, dx], [0, 1, dy]])  # 构造平移变换矩阵
        # dst = cv2.warpAffine(img, MAT, (cols, rows))  # 默认为黑色填充
        dst = cv2.warpAffine(img, MAT, (cols, rows), borderValue=(255, 255, 255))  # 设置白色填充
        ret, binary = cv2.threshold(dst, 200, 255, cv2.THRESH_BINARY)
        cv2.imwrite('./after/' + own + '_' + str(index).zfill(5) + '.jpg', binary)
        index += 1
    for i in range(5):
        dx, dy = (i + 1) * -10, 0  # 向左偏移量
        MAT = np.float32([[1, 0, dx], [0, 1, dy]])  # 构造平移变换矩阵
        # dst = cv2.warpAffine(img, MAT, (cols, rows))  # 默认为黑色填充
        dst = cv2.warpAffine(img, MAT, (cols, rows), borderValue=(255, 255, 255))  # 设置白色填充
        ret, binary = cv2.threshold(dst, 200, 255, cv2.THRESH_BINARY)
        cv2.imwrite('./after/' + own + '_' + str(index).zfill(5) + '.jpg', binary)
        index += 1

        这段代码是接着旋转之后运行的,将所有已经旋转的样本进行平移,至此就已经得到了足够的样本数量。但是在实际进行应用中,480P的图片过大,计算开销过大是不合适的,因此需要将这2970张图片进行缩小。

图片缩小

# 开发作者   :Tian.Z.L
# 开发时间   :2022/3/14  20:54 
# 文件名称   :adjust.PY
# 开发工具   :PyCharm
import cv2
import os

path = "C:/Users/TianZhonglin/Desktop/labPatentProject/TensorFlowLearnning/AutoDriver/after"  # 文件夹目录
files = os.listdir(path)  # 得到文件夹下的所有文件名称
for file in files:
    img = cv2.imread('after/' + str(file))
    img = cv2.resize(img, (32, 24))
    cv2.imwrite('after/' + str(file), img)

        根据mnist、CIFAR10的灵感,这里我将图片按比例缩小为32*24。其实根本原因是摄像头的分辨率就是为640*480。

数据集制作

        这里采用的是TensorFlow2.0制作自己的数据集。提供的思路

首先我们将不同类别的样本图片放在各自文件夹下,如下图所示。

  

         文件夹00000为直行样本,00001为左转样本,00002为右转样本。

其次运行以下代码

# 开发作者   :Tian.Z.L
# 开发时间   :2022/3/14  20:26 
# 文件名称   :test.PY
# 开发工具   :PyCharm
import csv

import tensorflow as tf
import os
import numpy as np

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# 训练图片的路径
train_dir = 'C:\\Users\\TianZhonglin\\Desktop\\labPatentProject\\TensorFlowLearnning\\AutoDriver\\after'
AUTOTUNE = tf.data.experimental.AUTOTUNE


# 获取图片,存放到对应的列表中,同时贴上标签,存放到label列表中
def get_files(file_dir):
    # 存放图片类别和标签的列表:第0类
    list_0 = []
    label_0 = []
    # 存放图片类别和标签的列表:第1类
    list_1 = []
    label_1 = []
    # 存放图片类别和标签的列表:第2类
    list_2 = []
    label_2 = []

    for file in os.listdir(file_dir):
        # print(file)
        # 拼接出图片文件路径
        image_file_path = os.path.join(file_dir, file)
        for image_name in os.listdir(image_file_path):
            # print('image_name',image_name)
            # 图片的完整路径
            image_name_path = os.path.join(image_file_path, image_name)
            # print('image_name_path',image_name_path)
            # 将图片存放入对应的列表
            if image_file_path[-1:] == '0':
                list_0.append(image_name_path)
                label_0.append(0)
            elif image_file_path[-1:] == '1':
                list_1.append(image_name_path)
                label_1.append(1)
            else:
                list_2.append(image_name_path)
                label_2.append(2)

    # 合并数据
    image_list = np.hstack((list_0, list_1, list_2))
    label_list = np.hstack((label_0, label_1, label_2))
    # 利用shuffle打乱数据
    temp = np.array([image_list, label_list])
    temp = temp.transpose()  # 转置
    np.random.shuffle(temp)

    # 将所有的image和label转换成list
    image_list = list(temp[:, 0])
    image_list = [i for i in image_list]
    label_list = list(temp[:, 1])
    label_list = [int(float(i)) for i in label_list]
    return image_list, label_list


def get_tensor(image_list, label_list):
    ims = []
    for image in image_list:
        # 读取路径下的图片
        x = tf.io.read_file(image)
        # 将路径映射为照片,3通道
        x = tf.image.decode_jpeg(x, channels=1)
        # 修改图像大小
        x = tf.image.resize(x, [32, 24])
        # 将图像压入列表中
        ims.append(x)
    # 将列表转换成tensor类型
    img = tf.convert_to_tensor(ims)
    y = tf.convert_to_tensor(label_list)
    return img, y


def preprocess(x, y):
    # 归一化
    x = tf.cast(x, dtype=tf.float32) / 255.0
    y = tf.cast(y, dtype=tf.int32)
    return x, y


if __name__ == "__main__":
    # 训练图片与标签
    image_list, label_list = get_files(train_dir)
    x_train, y_train = get_tensor(image_list, label_list)
    print('--------------------------------------------------------')
    # 生成图片,对应标签的CSV文件(只用保存一次就可以了)
    with open('./image_label.csv', mode='w', newline='') as f:
        Write = csv.writer(f)
        for i in range(len(image_list)):
            Write.writerow([image_list[i], str(label_list[i])])
    f.close()

就可以在同级目录下生成一个.csv文件,里面记录着样本的信息。包括样本以及类别标签label。

 至此,数据集就已经制作完毕了。接下来就要讲讲神经网络以及数据集的导入问题。

神经网络

训练模型大致流程为

  1. 加载数据集
  2. 自定义神经网络/现成的神经网络
  3. 训练
  4. 保存模型

加载数据集

       在借鉴制作数据集的文章中,就已经提供了一个载入数据集的方案。

from tensorflow.keras import layers, optimizers, datasets, Sequential
import tensorflow as tf
import os
import numpy as np

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# 训练图片的路径
train_dir = 'C:\\Users\\TianZhonglin\\Desktop\\labPatentProject\\TensorFlowLearnning\\AutoDriver\\after'
AUTOTUNE = tf.data.experimental.AUTOTUNE


# 获取图片,存放到对应的列表中,同时贴上标签,存放到label列表中
def get_files(file_dir):
    # 存放图片类别和标签的列表:第0类
    list_0 = []
    label_0 = []
    # 存放图片类别和标签的列表:第1类
    list_1 = []
    label_1 = []
    # 存放图片类别和标签的列表:第2类
    list_2 = []
    label_2 = []

    for file in os.listdir(file_dir):
        # print(file)
        # 拼接出图片文件路径
        image_file_path = os.path.join(file_dir, file)
        for image_name in os.listdir(image_file_path):
            # print('image_name',image_name)
            # 图片的完整路径
            image_name_path = os.path.join(image_file_path, image_name)
            # print('image_name_path',image_name_path)
            # 将图片存放入对应的列表
            if image_file_path[-1:] == '0':
                list_0.append(image_name_path)
                label_0.append(0)
            elif image_file_path[-1:] == '1':
                list_1.append(image_name_path)
                label_1.append(1)
            else:
                list_2.append(image_name_path)
                label_2.append(2)

    # 合并数据
    image_list = np.hstack((list_0, list_1, list_2))
    label_list = np.hstack((label_0, label_1, label_2))
    # 利用shuffle打乱数据
    temp = np.array([image_list, label_list])
    temp = temp.transpose()  # 转置
    np.random.shuffle(temp)

    # 将所有的image和label转换成list
    image_list = list(temp[:, 0])
    image_list = [i for i in image_list]
    label_list = list(temp[:, 1])
    label_list = [int(float(i)) for i in label_list]
    # print(image_list)
    # print(label_list)
    return image_list, label_list


def get_tensor(image_list, label_list):
    ims = []
    for image in image_list:
        # 读取路径下的图片
        x = tf.io.read_file(image)
        # 将路径映射为照片,3通道
        x = tf.image.decode_jpeg(x, channels=1)
        # 修改图像大小
        x = tf.image.resize(x, [32, 24])
        # 将图像压入列表中
        ims.append(x)
    # 将列表转换成tensor类型
    img = tf.convert_to_tensor(ims)
    y = tf.convert_to_tensor(label_list)
    return img, y


def preprocess(x, y):
    # 归一化
    x = tf.cast(x, dtype=tf.float32) / 255.0
    y = tf.cast(y, dtype=tf.int32)
    return x, y

    # 训练图片与标签


image_list, label_list = get_files(train_dir)
x_train, y_train = get_tensor(image_list, label_list)
# 载入训练数据集
db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
db_train = db_train.map(preprocess).batch(2970)
db_train = next(iter(db_train))

        通过上述代码,将2970个样本全部加载到db_train中,此时的db_train为列表类型,其中包含了样本以及样本对应的标签。样本张量为db_train[0]。

自定义神经网络

        这是最重要也是最能体现个人思考与特点的地方了。在tensorflow中,封装完备的API已经帮我们处理好了所有的矩阵操作,设计人员只需要专注于神经网络的设计即可。这对于新手来说是一件非常容易上手的好事,不过最好还是探究背后的底层实现,再次不过多叙述了。

        这里采用的是Sequential容器,将自定义的网络放在这个容器内。

network = Sequential([
    # Conv - Conv - Pooling单元1
    # 64个 3*3 的卷积核,输入输出同大小
    layers.Conv2D(64, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu, input_shape=(32, 24, 1)),
    layers.Conv2D(64, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu),
    # 宽高减半
    layers.MaxPooling2D(pool_size=[2, 2], strides=2, padding='SAME'),

    # Conv - Conv - Pooling单元2,输出通道提升至128,宽高减半
    layers.Conv2D(128, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu),
    layers.Conv2D(128, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu),
    layers.MaxPooling2D(pool_size=[2, 2], strides=2, padding='SAME'),

    # Conv - Conv - Pooling单元3,输出通道提升至256,宽高减半
    layers.Conv2D(256, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu),
    layers.Conv2D(256, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu),
    layers.MaxPooling2D(pool_size=[2, 2], strides=2, padding='SAME'),

    # Conv - Conv - Pooling单元4,输出通道提升至512,宽高减半
    layers.Conv2D(512, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu),
    layers.Conv2D(512, kernel_size=[3, 3], padding='SAME', activation=tf.nn.relu),
    layers.MaxPooling2D(pool_size=[2, 2], strides=2, padding='SAME'),

    layers.Flatten(),

    # 全连接层
    layers.Dense(256, activation=tf.nn.relu),
    layers.Dense(128, activation=tf.nn.relu),
    layers.Dense(64, activation=tf.nn.relu),
    layers.Dense(10, activation=tf.nn.softmax)
])
network.summary()

在上述代码中有几个需要注意的地方:

  1. 第一个卷积层的input_shape的值需要跟样本的宽、高、通道数一一对应。
  2. 在卷积之后与全连接层交接的地方,需要用layers.Flatten()将张量打平,提供全连接层计算。
  3. 由于是分类问题,全连接层输出的激活函数建议使用softmax,他能将所属概率落在0~1中间,并且能拉开不同可能之间的差距,与我们的认知相符。
  4. network.summary()可以在控制台打印神经网络的结构信息。

layers.Conv2D()是卷积函数

  • 第一个参数:卷积核的数量
  • 第二个参数:卷积核的尺寸
  • 第三个参数:是否需要边界填充
  • 第四个参数:选择激活函数

layers.Dense()是全连接函数

  • 第一个参数:神经元数量
  • 第二个参数:选择激活函数

详细的可以自行查找,这里介绍我在代码中用到的。

训练以及保存模型

# 模型训练 训练30个epoch
network.compile(optimizer='adam', loss="sparse_categorical_crossentropy", metrics=["accuracy"])
network.fit(db_train[0], y_train, epochs=30, validation_split=0.1)

# 模型保存
network.save('./AutoDrive.h5')
print('model saved')
del network

由于TensorFlow提供了高度集成的API方便用于模型的训练。有需要获取每个epoch的mse,mae值等就需要自己在底层实现中添加了,有兴趣的朋友可以去了解背后的实现。大致的思路就是:

  1. 初始化共享权值矩阵、偏执向量
  2. 向前传播(梯度跟踪)
  3. 反向传播,求得这个时候的导数
  4. 根据当时的导数×学习率更新权值矩阵

以此来求得极值,补充一下,对于多极值的情况,不同的初始化权值最终得到的效果是不一样的。这个需要根据经验来初始化权值矩阵。

在保存模型中,tensorflow提供了3种保存模型的方法。

  • 张量方式,直接保存网络张量数据是最轻量的一种方式,但是不保存网络机构参数,再导入的时候,需要使用相同的网络结构才能复现。
Model.save_weights(path)
  • 网络模式,这种模式不经保存了模型的参数,还保存了网络结构的信息。
Model.save(path)
  • SaveModel方式,这种方式是为了跨平台部署出现的
tf.saved_model.save(Model, path)

 为了方便,并且不需要考虑跨平台,这里使用的是网络模式。

测试

# 开发作者   :Tian.Z.L
# 开发时间   :2022/3/15  10:00 
# 文件名称   :test.PY
# 开发工具   :PyCharm
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import os
import numpy as np

# 网络加载
network = keras.models.load_model('AutoDrive.h5')
network.summary()

label = ['直行', '左转', '右转']
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# 训练图片的路径
train_dir = 'C:\\Users\\TianZhonglin\\Desktop\\labPatentProject\\TensorFlowLearnning\\AutoDriver\\after'
AUTOTUNE = tf.data.experimental.AUTOTUNE


# 获取图片,存放到对应的列表中,同时贴上标签,存放到label列表中
def get_files(file_dir):
    # 存放图片类别和标签的列表:第0类
    list_0 = []
    label_0 = []
    # 存放图片类别和标签的列表:第1类
    list_1 = []
    label_1 = []
    # 存放图片类别和标签的列表:第2类
    list_2 = []
    label_2 = []

    for file in os.listdir(file_dir):
        # print(file)
        # 拼接出图片文件路径
        image_file_path = os.path.join(file_dir, file)
        for image_name in os.listdir(image_file_path):
            # print('image_name',image_name)
            # 图片的完整路径
            image_name_path = os.path.join(image_file_path, image_name)
            # print('image_name_path',image_name_path)
            # 将图片存放入对应的列表
            if image_file_path[-1:] == '0':
                list_0.append(image_name_path)
                label_0.append(0)
            elif image_file_path[-1:] == '1':
                list_1.append(image_name_path)
                label_1.append(1)
            else:
                list_2.append(image_name_path)
                label_2.append(2)

    # 合并数据
    image_list = np.hstack((list_0, list_1, list_2))
    label_list = np.hstack((label_0, label_1, label_2))
    # 利用shuffle打乱数据
    temp = np.array([image_list, label_list])
    temp = temp.transpose()  # 转置
    np.random.shuffle(temp)

    # 将所有的image和label转换成list
    image_list = list(temp[:, 0])
    image_list = [i for i in image_list]
    label_list = list(temp[:, 1])
    label_list = [int(float(i)) for i in label_list]
    # print(image_list)
    # print(label_list)
    return image_list, label_list


def get_tensor(image_list, label_list):
    ims = []
    for image in image_list:
        # 读取路径下的图片
        x = tf.io.read_file(image)
        # 将路径映射为照片,3通道
        x = tf.image.decode_jpeg(x, channels=1)
        # 修改图像大小
        x = tf.image.resize(x, [32, 24])
        # 将图像压入列表中
        ims.append(x)
    # 将列表转换成tensor类型
    img = tf.convert_to_tensor(ims)
    y = tf.convert_to_tensor(label_list)
    return img, y


def preprocess(x, y):
    # 归一化
    x = tf.cast(x, dtype=tf.float32) / 255.0
    y = tf.cast(y, dtype=tf.int32)
    return x, y

    # 训练图片与标签


image_list, label_list = get_files(train_dir)
x_test, y_test = get_tensor(image_list, label_list)
print('--------------------------------------------------------')
# 载入训练数据集
db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))
db_test = db_test.map(preprocess).batch(2970)
db_test = next(iter(db_test))
print(db_test[0].shape)
db_test = db_test[0]

# 显示前25张图片
for i in range(25):
    plt.subplot(5, 5, i + 1)
    plt.imshow(db_test[i], cmap='gray')
plt.show()
# 改变维度
# testImage = tf.reshape(db_train, (10000, 28, 28, 1))
# 结果预测
result = network.predict(db_test)[0:25]
pred = tf.argmax(result, axis=1)
pred_list = []
for item in pred:
    pred_list.append(label[item.numpy()])
print(pred_list)

测试结果

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: 代码生成是指根据设计好的算法和逻辑,在特定的开发平台上生成可执行代码的过程。基于51单片机智能小车的代码生成过程,通常包括以下几个步骤: 1. 确定算法:根据设计要求和实际情况,选择适合的算法,如PID控制算法等。 2. 编写程序:根据算法和逻辑,在开发平台上编写程序,并进行调试和优化。 3. 生成可执行代码:在开发平台上,将编写好的程序转化为可执行的二进制代码,即生成.hex文件。 4. 烧录程序:将生成的.hex文件通过编程器烧录到51单片机中。 5. 调试和优化:在实际应用中,对代码进行调试和优化,确保程序的稳定性和可靠性。 通过以上步骤,可以实现基于51单片机智能小车的代码生成,从而实现小车智能功能。 ### 回答2: 代码生成是指根据需求和设计规范,通过编程工具和语言来生成相应的代码的过程。基于51单片机智能小车功能,需要使用C语言进行编程。 首先,需要定义引脚的映射关系,包括左右电机的控制引脚,传感器接收引脚等。然后,在主函数中进行初始化设置,包括引脚模式设置、定时器设置以及中断设置等。接下来,编写一个自定义函数来读取传感器的数据,根据传感器的变化来判断小车的运动方向。根据传感器读取数据的结果,可以设计一些判断语句来确定小车的运动方向,比如当左传感器和右传感器均检测到黑线时,小车前进;当左传感器检测到黑线时,小车右转;当右传感器检测到黑线时,小车左转等。 此外,为了实现小车的运动,还需要编写两个函数来控制电机的转动。这两个函数分别用于控制左右电机的转动方向和转速。在小车按照结果行驶的过程中,可以通过调用这两个函数来控制电机的转动,从而实现小车的运动。 最后,在主函数中通过循环的方式不断执行传感器读取和判断的函数,以及电机控制函数,从而让小车能够实现根据黑线的运动。 总体来说,通过以上的代码设计,我们可以实现基于51单片机的智能小车功能。这些代码可以通过编程工具进行编辑和编译,然后通过下载到单片机的方式来实现对小车的控制。 ### 回答3: 代码生成是指根据特定需求和规则自动生成源代码的过程。基于51单片机智能小车的代码生成是根据小车功能的要求和51单片机的特性,通过编程语言和相应的开发环境,生成实现小车功能的源代码。 首先,根据小车的需求,我们需要通过车底部的红外线传感器来检测赛道上的黑线。当小车离开赛道时,传感器将无法检测到黑线,小车需要根据检测结果进行相应的动作调整来重新找回赛道。 基于51单片机,我们可以选择C语言作为编程语言,并使用相应的集成开发环境如Keil等。在生成代码过程中,我们需要先初始化51单片机和红外线传感器的相应引脚,然后设置中断,使得当红外线传感器检测到黑线时,可以触发相应的中断函数。 在中断函数中,我们可以根据不同的检测结果设置不同的动作,比如当检测到黑线时,小车可以直行;当检测不到黑线时,小车可以停止、后退或转向等。通过判断当前检测到的黑线位置和小车本身的位置,可以实现小车根据检测结果进行相应动作的功能。 除此之外,为了使得小车能够实时响应并调整动作,我们可以在主循环中添加相关的代码,根据检测结果和设定的规则进行判断和决策,并发送相应的命令给底层驱动电路,控制小车的运动。 代码生成的过程中,还可以根据具体需求添加其他功能,如避障功能、速度控制等,从而定制化智能小车功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值