(纯萌新,学习单片机半年了,这是寒假回家的作品,师从江科大,写博客纪录我实现后的经验)(比较粗略)
前言
学习寻迹小车,最最重要的莫过于通过反射式红外传感器读取小车的状态并让小车做出相应的反应以达到快速调整姿态。我的循迹小车用的是三个红外传感器,并不是很智能,但是在速度和过不同种类的弯道都可圈可点。
我大致将学习寻迹小车的思路分为3方面:1.小车本身能不能动 2.如何检测小车此时的状态 3.什么状态给小车的轮子什么速度。
本文默认小车可以动了,所以下文主要针对什么赛道赋什么速度。
赛道如图
赛道部分
赛道一般分为:
直接连接:直线赛道,145度左右直赛道,120度左右赛直道,直角直赛道,锐角直赛道。
圆滑连接:半径大的半圆弧、1/4圆弧赛道,半径小的半圆弧、1/4圆弧赛道,和椭圆弧赛道。
难度:
直接连接中能够攻克120度左右,圆滑连接能够将半径大的圆弧赛道和椭圆赛道攻克便是初级目标。
攻克直角直赛道和半径小的圆弧赛道是附加目标。
锐角直赛道我用我的三个红外反射模块暂时没有思路,无法实现。(四个可以实现,但是本文主要针对3个)
解决思路:
3个红外模块主要可以分为7种情况。(我的三个模块挨得很近,且中间的模块比两边要突出一些(方便过直角弯))
为了方便我将3个红外模块命名为L(左),I(中),R(右)
从最简单的三种说起:只有L,I,R其中一个检测到赛道。
只有L,则全力左转,只有I,则全力直行,只有R,则全力右转。
其次是两种微调:L和I,I和R中一对检测到赛道。
该情况与上面相差不大,只是转弯力度减小即可。
最后是两种特殊情况:全检测到或全没检测到。
这两种情况大多为硬件太弱的问题,所以当出现这两种情况时,建议让其继续执行之前的命令,比如左转,但是转的时候有段时间三个都没检测到,那么继续执行之前的命令,继续左转直到检测到赛道。用该方式可以很好的过部分急转弯。
特殊问题:直角直赛道
直角直赛道时如果三个模块平行,那么会同时检测不到,转弯力度不够,所以我将中间模块稍微突出,在直角赛道最后会有一小段时间只有左右两个模块能够检测到赛道,此时全力转弯即可过弯。
代码部分
代码没什么可以说的,简单的if语句。思路有了,其实代码也不是很重要。文章来源:https://www.toymoban.com/news/detail-599187.html
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);
}
总结:
多调试,多实验,多总结。文章来源地址https://www.toymoban.com/news/detail-599187.html
到了这里,关于大一新生の作品:简单的寻迹小车的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!