The freshman's work: a simple tracing car

(Purely new, I have been learning MCU for half a year. This is a work I came home from during the winter vacation. I learned from Jiang Ke University and wrote a blog to record my experience after I realized it.) (roughly)

foreword

The most important thing in learning to trace the car is to read the state of the car through the reflective infrared sensor and let the car respond accordingly to quickly adjust its attitude. My tracking car uses three infrared sensors, which is not very smart, but it is remarkable in speed and through different kinds of curves.

I roughly divide the idea of ​​learning the tracking car into three aspects: 1. Whether the car itself can move 2. How to detect the state of the car at this time 3. What state gives the wheels of the car what speed.

In this article, the car can move by default, so the following is mainly for which track to assign what speed.

The track is shown in the picture

track part

Tracks are generally divided into:

Direct connection: straight track, straight track around 145 degrees, straight track around 120 degrees, straight track with right angle, straight track with acute angle.

Smooth connection: semi-circular arc, 1/4 arc track with large radius, semi-circular arc, 1/4 arc track with small radius, and elliptical arc track.

Difficulty:

The primary goal is to be able to overcome about 120 degrees in the direct connection, and to be able to overcome the arc track and the elliptical track with a large radius in the smooth connection.

Conquering right-angle straight tracks and small-radius arc tracks is an additional goal.

I have no idea to use my three infrared reflective modules for the sharp-angle straight track, and I can't realize it. (Four can be achieved, but this article is mainly aimed at 3)

Solutions:

The 3 infrared modules can be mainly divided into 7 situations. (My three modules are very close together, and the middle module protrudes a little more than the two sides (convenient for right-angle bends))

For convenience, I named the 3 infrared modules L (left), I (middle), R (right)

Let's start with the simplest three: only one of L, I, and R detects the track.

If there is only L, turn left with all your strength, if only I, go straight with all your strength, and if only R, turn right with all your strength.

This is followed by two fine-tunings: L and I, where a pair of I and R detects the track.

This situation is not much different from the above, except that the turning force is reduced.

Finally, there are two special cases: all detected or none detected.

These two situations are mostly caused by the hardware being too weak, so when these two situations occur, it is recommended to let it continue to execute the previous command, such as turning left, but when turning left, the three are not detected for a while, then continue Execute the previous command and continue to turn left until the track is detected. Some sharp turns can be navigated well in this way.

Special Issue: Straight Tracks at Right Angles

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

代码部分

代码没什么可以说的,简单的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);
}

总结:

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

Guess you like

Origin blog.csdn.net/ChiShangying/article/details/128794692