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

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配置开始修改,把下拉输入改成了浮空输入模式,整个问题迎刃而解。

  • 11
    点赞
  • 133
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值