您的位置:首页 > 其它

【单片机项目】制作一辆基于STM32的智能小车——三路循迹模块

2020-04-22 02:52 585 查看

1.引脚定义:
GND接地,VCC供电,X1、X2、X3各自对应一对红外探头

2.实验原理:
红外传感器巡线的基本原理是利用物体的反射性质,当红外线发射到黑色上时会被黑线吸收掉,当红外线发射到不同的颜色的材料上会有不同反射到红外的接手管上,已产生不同大小的光电流,从而影响三路引脚输入电平高低。

3.注意:

  1. 红外探头发出的红外光是人眼无法看到的。
  2. 为了避免太阳光对红外传感器产生影响,所以我们需要在室内使用该模块。
  3. 工作电压: 3.3v~5v


    remote.h
#ifndef __REMOTE_H
#define __REMOTE_H

#define left GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)
#define	mid GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)
#define	right GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)

void remote_init(void);

void run_left(void);
void run_right(void);
void run_forth(void);
void run_back(void);
void run_stop(void);

#endif

remote.c

#include "remote.h"
#include "sys.h"

void remote_init()
{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //开启IO口对应的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3;			//PA2 PA3
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;						//PB0
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}

void run_forth()
{
TIM_SetCompare1(TIM4,780);
TIM_SetCompare2(TIM4,899);
TIM_SetCompare3(TIM4,782);
TIM_SetCompare4(TIM4,899);
}

void run_left()
{
TIM_SetCompare1(TIM4,860);
TIM_SetCompare2(TIM4,899);
TIM_SetCompare3(TIM4,760);
TIM_SetCompare4(TIM4,899);
}

void run_right()
{
TIM_SetCompare1(TIM4,760);
TIM_SetCompare2(TIM4,899);
TIM_SetCompare3(TIM4,860);
TIM_SetCompare4(TIM4,899);
}

void run_back()
{
TIM_SetCompare1(TIM4,899);
TIM_SetCompare2(TIM4,800);
TIM_SetCompare3(TIM4,899);
TIM_SetCompare4(TIM4,800);
}

void run_stop()
{
TIM_SetCompare1(TIM4,899);
TIM_SetCompare2(TIM4,899);
TIM_SetCompare3(TIM4,899);
TIM_SetCompare4(TIM4,899);

}

main.c

#include "sys.h"
#include "delay.h"
//#include "usart.h"
#include "led.h"
#include "oled.h"
#include "motor.h"
#include "timer.h"
#include "remote.h"
//#include "tick_ulsonic.h"
//#include "ultrasonic.h"

/***********************************************************************************************
本来是一个三路巡线模块,但因为模块质量问题,中间识别能力较差,故只使用左右两路,逻辑上也可以实现。
****************************************************************************************************************/

void pointleft(void); //OLED方向指示
void pointright(void);
void pointforth(void);
void pointback(void);

int main(void)
{
u8 i=0;
u8 val1;
u8 val2;
SystemInit();
delay_init();	    //延时函数初始化	  nms<=1864
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);// 或使用JTAG_Set(0X01);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
LED_Init();
//	uart_init(115200);
LED_Init();		  	//初始化与LED连接的硬件接口
OLED_Init();
pwm_init(899,0);
//	Tim3_Config();
//	ulsonic0_config();		//  ECHO PA2        TRIG PA3
//	ulsonic1_config();		//  ECHO PA13        TRIG PA14
remote_init();
delay_ms(1800);	 delay_ms(1800);	 delay_ms(1800);
run_forth();
while(1)												//基于实际操作环境,在纸张内返回引脚口读取0,纸张外读取1。
{

val1=left;
val2=right;
switch(val1+val2)
{
case 2 :	run_back();pointback();	//两边跑离纸面
break;

case 1 :	if(val1==1)			 //一边跑离纸面
{run_right();pointright();
}
else{
run_left();pointleft();
}
break;

case 0 : 	run_forth();pointforth();		//在纸面内

break;
default: break;
}
OLED_ShowNumber(20,20,val1,1,14);
OLED_ShowNumber(60,20,val2,1,14);
OLED_Refresh_Gram();
i++;
if(i==10)
{
LED=!LED;
i=0;
}
delay_ms(50);

}

}

void pointright()
{
OLED_Clear();
OLED_ShowString(40,10,"O");
OLED_ShowString(60,20,"O");
OLED_ShowString(80,30,"O");
OLED_ShowString(60,40,"O");
OLED_ShowString(40,50,"O");
OLED_Refresh_Gram();
}

void pointleft()
{
OLED_Clear();
OLED_ShowString(80,10,"O");
OLED_ShowString(60,20,"O");
OLED_ShowString(40,30,"O");
OLED_ShowString(60,40,"O");
OLED_ShowString(80,50,"O");
OLED_Refresh_Gram();
}

void pointforth()
{
OLED_Clear();
OLED_ShowString(60,10,"OO");
OLED_ShowString(50,20,"O  O");
OLED_ShowString(40,30,"O    O");
OLED_Refresh_Gram();

}

void pointback()
{
OLED_Clear();
OLED_ShowString(60,50,"OO");
OLED_ShowString(50,40,"O  O");
OLED_ShowString(40,30,"O    O");
OLED_Refresh_Gram();

}

我用屎黄色的草稿纸铺的“跑道"

该次功能实现中,三路引脚都能正常运行,但逻辑判断中只用到了左右两路,因为个人试验没有高精度要求,小车在该环境下已经能非常流畅准确的判断、运行。若使用三路引脚判断,可以实现急转弯等更高级的功能,这里不详细说明。

注:在调试中一直遇到读IO口Byte是,1和0显示不准确和不灵敏等问题,在经历了很长一段时间的不断尝试和思考后,最后从最简单的IO配置开始修改,把下拉输入改成了浮空输入模式,整个问题迎刃而解。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
梁朝伟h 发布了8 篇原创文章 · 获赞 2 · 访问量 354 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: