大一新生の作品:简单的寻迹小车

(纯萌新,学习单片机半年了,这是寒假回家的作品,师从江科大,写博客纪录我实现后的经验)(比较粗略)

前言

学习寻迹小车,最最重要的莫过于通过反射式红外传感器读取小车的状态并让小车做出相应的反应以达到快速调整姿态。我的循迹小车用的是三个红外传感器,并不是很智能,但是在速度和过不同种类的弯道都可圈可点。

我大致将学习寻迹小车的思路分为3方面:1.小车本身能不能动 2.如何检测小车此时的状态 3.什么状态给小车的轮子什么速度。

本文默认小车可以动了,所以下文主要针对什么赛道赋什么速度。

赛道如图

赛道部分

赛道一般分为:

直接连接:直线赛道,145度左右直赛道,120度左右赛直道,直角直赛道,锐角直赛道。

圆滑连接:半径大的半圆弧、1/4圆弧赛道,半径小的半圆弧、1/4圆弧赛道,和椭圆弧赛道。

难度:

直接连接中能够攻克120度左右,圆滑连接能够将半径大的圆弧赛道和椭圆赛道攻克便是初级目标。

攻克直角直赛道和半径小的圆弧赛道是附加目标。

扫描二维码关注公众号,回复: 16114034 查看本文章

锐角直赛道我用我的三个红外反射模块暂时没有思路,无法实现。(四个可以实现,但是本文主要针对3个)

解决思路:

3个红外模块主要可以分为7种情况。(我的三个模块挨得很近,且中间的模块比两边要突出一些(方便过直角弯))

为了方便我将3个红外模块命名为L(左),I(中),R(右)

从最简单的三种说起:只有L,I,R其中一个检测到赛道。

只有L,则全力左转,只有I,则全力直行,只有R,则全力右转。

其次是两种微调:L和I,I和R中一对检测到赛道。

该情况与上面相差不大,只是转弯力度减小即可。

最后是两种特殊情况:全检测到或全没检测到。

这两种情况大多为硬件太弱的问题,所以当出现这两种情况时,建议让其继续执行之前的命令,比如左转,但是转的时候有段时间三个都没检测到,那么继续执行之前的命令,继续左转直到检测到赛道。用该方式可以很好的过部分急转弯。

特殊问题:直角直赛道

直角直赛道时如果三个模块平行,那么会同时检测不到,转弯力度不够,所以我将中间模块稍微突出,在直角赛道最后会有一小段时间只有左右两个模块能够检测到赛道,此时全力转弯即可过弯。

代码部分

代码没什么可以说的,简单的if语句。思路有了,其实代码也不是很重要。

main函数:

#include "stm32f10x.h"
#include "Delay.h"
#include "Motor.h"
#include "XunJi.h"


int main(void)                //电机范围(速度)-100~100        
{
    int State;
    Motor_Init();
    XunJi_Init();
    
    while(1)
    {
        State=Get_XunJi();
        if(State==1)        //左轮后转,右轮前转,即原地左转
        {
            Motor_L_SetSpeed(-50);
            Motor_R_SetSpeed(50);
        }
        if(State==2)        //微调
        {
            Motor_L_SetSpeed(25);
            Motor_R_SetSpeed(50);
        }
        if(State==3)
        {
            Motor_L_SetSpeed(50);        //速度可以自行调整
            Motor_R_SetSpeed(50);
        }
        if(State==4)
        {
            Motor_L_SetSpeed(50);
            Motor_R_SetSpeed(25);
        }
        if(State==5)
        {
            Motor_L_SetSpeed(50);
            Motor_R_SetSpeed(-50);
        }
    }    
}

寻迹函数:

#include "stm32f10x.h"                  // Device header

void XunJi_Init(void)        //从A7到B1分别为右,中,左
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;            //结构体
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);        //GPIOB的初始配置
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);        //GPIOA的初始配置
}

uint16_t Get_XunJi(void)
{
    static int A;            //A是状态
    if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)==1)    //中间检测到了
    {
        if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==1&&GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)==1)//全检测到了,保持状态
        {
            return(A);
        }
        else if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==1)    //左边检测到了
        {
            A=2;
            return(2);
        }
        else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)==1)    //右边检测到了
        {
            A=4;
            return(4);
        }
        else        //只有中间
        {
            A=3;
            return(3);
        }
    }
    else if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==1)    //只有左边检测到了
    {
        A=1;
        return(1);
    }
    else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)==1)    //只有右边检测到了
    {
        A=5;
        return(5);
    }
    else         //全没检测到,继续之前的状态
    {
        return(A);
    }
}

电机函数:

#include "stm32f10x.h"                  // Device header
#include "PWM.h"

void Motor_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;                    //方向GPIO口初始化
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    PWM_Init();        //初始化PWM
    
}

void Motor_TwoSetSpeed(int8_t Speed)
{
    if(Speed>=0)
    {
        PWM_SetCompare1(Speed);    
        PWM_SetCompare2(Speed);
    }
    if(Speed<=0)
    {
        PWM_SetCompare1(-Speed);
        PWM_SetCompare2(-Speed);
    }
}
void Motor_L_SetSpeed(int8_t Speed)        //左轮控制
{
    if(Speed>=0)
    {    
        GPIO_SetBits(GPIOA,GPIO_Pin_4);
        GPIO_ResetBits(GPIOA,GPIO_Pin_6);
        PWM_SetCompare1(Speed);
    }
    if(Speed<=0)
    {
        GPIO_SetBits(GPIOA,GPIO_Pin_6);
        GPIO_ResetBits(GPIOA,GPIO_Pin_4);
        PWM_SetCompare1(-Speed);
    }
}
void Motor_R_SetSpeed(int8_t Speed)        //右轮控制
{
    if(Speed>=0)
    {    
        GPIO_SetBits(GPIOA,GPIO_Pin_5);
        GPIO_ResetBits(GPIOA,GPIO_Pin_8);
        PWM_SetCompare2(Speed);
    }
    if(Speed<=0)
    {
        GPIO_SetBits(GPIOA,GPIO_Pin_8);
        GPIO_ResetBits(GPIOA,GPIO_Pin_5);
        PWM_SetCompare2(-Speed);
    }
}
void Motor_Stop(void)
{
    PWM_SetCompare1(0);
    PWM_SetCompare2(0);
}
void Motor_Retreat()
{
    GPIO_SetBits(GPIOA,GPIO_Pin_8);
    GPIO_SetBits(GPIOA,GPIO_Pin_6);
    GPIO_ResetBits(GPIOA,GPIO_Pin_5);
    GPIO_ResetBits(GPIOA,GPIO_Pin_4);
}
void Motor_Go()
{
    GPIO_SetBits(GPIOA,GPIO_Pin_4);
    GPIO_SetBits(GPIOA,GPIO_Pin_5);
    GPIO_ResetBits(GPIOA,GPIO_Pin_6);
    GPIO_ResetBits(GPIOA,GPIO_Pin_8);
}

总结:

多调试,多实验,多总结。

猜你喜欢

转载自blog.csdn.net/ChiShangying/article/details/128794692