红外循迹——开环(俗称:死程序)

编程入门 行业动态 更新时间:2024-10-09 12:29:53

红外循迹——<a href=https://www.elefans.com/category/jswz/34/1761342.html style=开环(俗称:死程序)"/>

红外循迹——开环(俗称:死程序)

目录

一、前言

二、代码

三、总结


一、前言

学习的过程是先易后难的,所以我先为大家讲解普通的死程序去循迹,后面再讲PID控制的循迹。好了,废话少说,直接来程序思路。

首先,我们要知道,让小车向前跑,但是黑线是弯的,这个时候就需要去转向,比如黑线在小车的左侧,我们需要左边加一个传感器,检测到左边的黑线,传给小车一个信号,让小车左转,顺着黑线走;同理黑线在右边,我们用上述一样的方法;所以总结一下,给小车多加几个传感器,反馈黑线位置,让小车知道怎么转。

具体的要结合程序,大家就一目了然了,在这里先跟大家说几个点:

1,注意别买错红外传感器,本人上过太多的当了,希望大家别和我一样,少花一些冤枉钱,最重要的是少浪费一些时间。

如果大家是买单个的,不要买这类这个模块完全没用,就买这个样子的好一点,但是这种单个的红外传感器,检测效果差,而且只能识别黑线,不同的环境,检测效果不一样,要自己去调灵敏度,相当的麻烦,如果有小伙伴是应付一下期末检测,那这个也勉勉强强。

2,如果大家是买多路的合在一起的那种,我不建议大家去买这类

 虽然很便宜只要10块左右,但是一点用都没有,完全没有效果,还不如用单个的呢,如果大家是做着玩玩,就可以买亚博的,但是大家要注意,亚博的传感器,他的位置跟普通的多路传感器的位置不一样,而且市面上大部分你买到的红外传感器,检测到黑线都是给高电平,而亚博是给低电平,这一点是值得注意的。

如果是要搞竞赛的小伙伴们,就用这种灰度传感器,灵敏度自调,且不仅检测黑线,还检测红线。

 3,大家注意在定义管脚的时候,有些管脚是不能直接用的,需要修改部分程序。就比如STM32F103C8T6的PC3大家查了就知道它是电源指示灯的管脚。

4,循迹模块的路数越多,越准越稳。

二、代码

xunji.h

#ifndef __XUNJI_H
#define	__XUNJI_H//这里的xunji_x就是代表读取到相应管脚的高低电平#define xunji_1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
#define xunji_2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
#define xunji_3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)
#define xunji_4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)void xunji_config(void);
void Read_xunji_Date(void);  //读循迹模块返回的值#endif

xunji.c

#include "stm32f10x.h"                  // Device header
#include "xunji.h"#include "Motor.h"void xunji_config(void)	
{GPIO_InitTypeDef GPIO_InitStructure;	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PC端口时钟GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12 | GPIO_Pin_13  | GPIO_Pin_14 | GPIO_Pin_15;	//选择对应的引脚GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU ;//配置GPIO模式,输入上拉,这里是检测的作用,所以用上拉输入    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PC端口
}void Read_xunji_Date(void)
{xunji_1;xunji_2;xunji_3;xunji_4;//红外检测到黑线,令xunji_x=1,意思就是红外检测到黑线发送高电平if(xunji_1==0&&xunji_2==0&&xunji_3==0&&xunji_4==0)//没有检测到黑线{CarGo();//小车直行  }if(xunji_1==1&&xunji_2==0&&xunji_3==0&&xunji_4==0)//最左边检测到黑线{CarBigRight();	  //左转大}if(xunji_1==0&&xunji_2==0&&xunji_3==0&&xunji_4==1)//最右边检测到黑线{CarBigLeft(); //右转大}if(xunji_1==0&&xunji_2==1&&xunji_3==0&&xunji_4==0)//依次类推,不过多赘述{CarGo();//小车直行		  }if(xunji_1==0&&xunji_2==1&&xunji_3==1&&xunji_4==0){CarGo();//小车直行		  }if(xunji_1==0&&xunji_2==0&&xunji_3==1&&xunji_4==0){CarGo();//小车直行		  }if(xunji_1==1&&xunji_2==1&&xunji_3==0&&xunji_4==0){CarRight();	  //左转小}if(xunji_1==0&&xunji_2==0&&xunji_3==1&&xunji_4==1){CarLeft();	  //右转小}}

pwm.c

#include "stm32f10x.h"                  // Device header
//这里设置的ARR,PSC就是让PWM最大为100,更直观,方便的使用
void PWM_Init(void){//	用结构体初始化输出比较单元,不同函数不同的GPIO(A0)//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO的时钟//GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);//部分重映射
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//关闭调试端口的复用RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_Initstructure;GPIO_Initstructure.GPIO_Mode= GPIO_Mode_AF_PP;//复用推挽输出GPIO_Initstructure.GPIO_Pin= GPIO_Pin_2;GPIO_Initstructure.GPIO_Speed= GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Initstructure);GPIO_Initstructure.GPIO_Mode= GPIO_Mode_AF_PP;//复用推挽输出GPIO_Initstructure.GPIO_Pin= GPIO_Pin_1;GPIO_Initstructure.GPIO_Speed= GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Initstructure);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period=100- 1;//ARRTIM_TimeBaseInitStructure.TIM_Prescaler=720 - 1;//PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);TIM_OCInitTypeDef TIM_OCInitStructure;//结构体变量需要赋值TIM_OCStructInit(&TIM_OCInitStructure);//结构体赋初始值的函数TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//输出比较模式TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出比较的极性TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出比较的使能TIM_OCInitStructure.TIM_Pulse =0;//设置CCR的TIM_OC3Init(TIM2,&TIM_OCInitStructure);//注意函数区别TIM_OC3PreloadConfig(TIM2 , TIM_OCPreload_Enable);TIM_OC2Init(TIM2,&TIM_OCInitStructure);TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);TIM_Cmd(TIM2,ENABLE);
}
void PWM_SetCompare3(uint16_t Compare3){TIM_SetCompare3(TIM2,Compare3);}
void PWM_SetCompare2(uint16_t Compare2){TIM_SetCompare2(TIM2,Compare2);}

Motor.c

#include "stm32f10x.h"                  // Device header#include "PWM.h"
void Motor_Init(void)//定义要使用的管脚
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_Initstructure;GPIO_Initstructure.GPIO_Mode= GPIO_Mode_Out_PP;GPIO_Initstructure.GPIO_Pin= GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;GPIO_Initstructure.GPIO_Speed= GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Initstructure);GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);PWM_Init();
}//如果你们想让小车倒着走,只需要将GPIO_SetBits与	GPIO_ResetBits交换一下就可以了void CarGo(void)//小车直行函数
{TIM_SetCompare2(TIM2 , 60);//数值越小速度越慢TIM_SetCompare3(TIM2 , 60);  GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_SetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);
}void CarBigLeft(void)//小车右转大函数
{TIM_SetCompare2(TIM2 ,0);TIM_SetCompare3(TIM2, 60);
GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_SetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);
}void CarBigRight(void)//小车左转大函数
{TIM_SetCompare2(TIM2, 60);TIM_SetCompare3(TIM2 , 0);
GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_SetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);}
void CarLeft(void)//小车右转小函数
{TIM_SetCompare2(TIM2 , 40);TIM_SetCompare3(TIM2, 60);
GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_SetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);
}void CarRight(void)//小车左转小函数
{TIM_SetCompare2(TIM2, 60);TIM_SetCompare3(TIM2 , 40);
GPIO_SetBits(GPIOA, GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_5);GPIO_SetBits(GPIOA, GPIO_Pin_6);GPIO_ResetBits(GPIOA, GPIO_Pin_7);}

main.c

//提高PWM的频率,让电机在堵转的时候无声,人耳听到的频率在20Hz-20kHz
#include "stm32f10x.h"                  // Device header#include "Delay.h"
#include "OLED.h"
#include "Motor.h"
#include "xunji.h"int main(void)
{SystemInit();	//开启系统时钟xunji_config();//循迹管脚的初始化OLED_Init();Motor_Init();while (1){Read_xunji_Date(); //读循迹线值//车前4个循迹模块从左到右分别是xunji_1,xunji_2,xunji_3,xunji_4}}

三、总结

说实话,我当时就是自己一个人慢慢摸索,网上查资料,当时觉得好难啊,确确实实很累,没有人指导自己,但是我不断地坚持学习,我克服了许多困难,现在我觉得这个循迹再简单不过,虽然我谈不上有什么多大的进步,但是我一直在成长,看着自己比昨天更厉害,这种感觉真的很好,相信大家也会学有所成!

其实,我还发现一个小BUG,就是有时候电脑没办法打开百度网盘的链接,但是手机可以,这就很神奇。

链接:=yl66 
提取码:yl66

更多推荐

红外循迹——开环(俗称:死程序)

本文发布于:2024-02-14 00:51:46,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1761228.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:开环   俗称   程序

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!