STM32 学习笔记2-智能小车循迹实验

特斯拉镇楼

1、什么是小车循迹?

将小车放在黑色跑道上面,小车沿着黑色跑道运动 → 循迹

黑色跑道

2、小车循迹基本原理

原理:

介绍原理之前,突然记起来,在电子爱好者上  做过 一个循迹小车的项目,那个介绍的相相当详细,和这个基本原理是一样的。

光敏电阻:光照作用下, 光敏电阻器的阻值下降。光敏接触(跑道)黑色线时,电阻上升

LM393 比较两路光敏电阻 R13  R14 的大小,不平衡时,控制压线侧电机停止,第二个电机工作,从而修正方向,使黑色跑道线保持在两轮之间。

 

硬件:
小车底板及附件:支撑,骨架,带四个车辆,前两轮为驱动轮;

可调电位器:10K ,用于调节循迹传感器模块的灵敏度

传感部件:2*反射式光电管 ,用于检测跑道black/white

 四个引脚分别为:1 Anode 正极  2 cathode 负极  3 Emitter 发射极  4  collector 接收极

驱动:两个直流电机,作用为驱动车轮运动

电源:干电池

控制模块: LM393  & 单片机系统

显示模块:LED ,循迹指示灯,当循迹探头检测到黑线,指示灯亮

 背面:白色是发射端,黑色是接受端

正面 

电路图(基本原理与上面介绍的类似,只不过是把用LM393 检测的结果输出给 单片机)

3、小车循迹代码实现 和 分析

先来看主函数  main.c

#include "stm32f10x.h"  //系统库函数
#include "delay.h"       //延时函数
#include "motor.h"      //电机库函数
#include "keysacn.h"     // 按键函数
#include "IRSEARCH.h"    // 循迹库函数


 int main(void)
 {	
	 delay_init();    //延时初始化(在调用延时函数之前,必须先用delay_init()初始化Systick)
	 KEY_Init();       // 初始化  调用按键函数
	 IRSearchInit();          // 循迹初始化
	 TIM4_PWM_Init(7199,0);  //初始化 PWM 让电机转起来
	 STM32_brake(500);     //刹车0.5s 
	 keysacn();		    
		while(1)
		{  
		 SearchRun();     // 循迹函数 
		}
 }

初始化延时, delay_init();,在之前的内容已经谈论过啦,不赘述

初始化按键,     KEY_Init(); 使用的是 GPIO 外设 ,设置和我的学习笔记0 让小灯亮起来类似

//按键初始化函数
//PA15 和PC5 设置为输入
void KEY_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能PORTA PORTC时钟
	
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2;//PC2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置为上拉输入
 	GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC2
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;				 //蜂鸣器PC3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO 50MHz
  GPIO_Init(GPIOC, &GPIO_InitStructure);					 //设定参数初始化 GPIOC.3
}

初始化探头,IRSearchInit();    PA7  PB0

void IRSearchInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB , ENABLE);//使能时钟
	
  GPIO_InitStructure.GPIO_Pin = SEARCH_R_PIN;//  PA7
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//输入上拉模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//端口速度
	GPIO_Init(SEARCH_R_GPIO , &GPIO_InitStructure); 
	
	GPIO_InitStructure.GPIO_Pin = SEARCH_L_PIN;//  PB0
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;// 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;// 
	GPIO_Init(SEARCH_L_GPIO , &GPIO_InitStructure); 
}

初始化 PWM 电机  配置,见学习笔记1   TIM4_PWM_Init(7199,0);

按键读取程序, keysacn();      同时程序中加了一个蜂鸣器作为反馈声,被按下时蜂鸣器响 

void keysacn()
{
  int val;
  val=KEY;  //读取按键
  while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2))//当按键没有被按下时,一直循环
  {
    val=KEY;//
  }
  while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2))//当按键被按下时
  {
    delay_ms(10);	  //延时10ms
    val=KEY;//读取PC2口电平值赋给Val
    if(val==1)  //第二次判断按键是否被按下
    {
      BEEP_SET;		//蜂鸣器响
      while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2))	//判断按时是否被松开
        BEEP_RESET;	//蜂鸣器停止
    }
    else
				BEEP_RESET;//蜂鸣器停止
  }
}

 蜂鸣器定义函数:怎么让蜂鸣器响起来? 蜂鸣器定义为 PC3

#ifndef __KEYSACN_H_
#define __KEYSACN_H_

#include "stm32f10x.h"

void KEY_Init(void);//按键初始化
void keysacn(void);//按键扫描函数

//蜂鸣器IO口定义
#define BEEP_PIN         GPIO_Pin_3
#define BEEP_GPIO        GPIOC
#define BEEP_SET         GPIO_SetBits(BEEP_GPIO,BEEP_PIN)
#define BEEP_RESET       GPIO_ResetBits(BEEP_GPIO,BEEP_PIN)

//¶ÁÈ¡°´¼ü
#define KEY  GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)//读取按键0

#endif

下图为示意,实际为 PC.3口为高电平时,蜂鸣器发声,为低电平时,不工作


        while(1)
        {  
         SearchRun();
        }

         SearchRun();
 

void SearchRun(void)   //循迹控制程序
{
	if(SEARCH_L_IO == WHITE_AREA && SEARCH_R_IO == WHITE_AREA)     //前进控制逻辑
		ctrl_comm = COMM_UP;
	else if (SEARCH_L_IO == BLACK_AREA && SEARCH_R_IO == WHITE_AREA) //左转控制逻辑
		ctrl_comm = COMM_LEFT;
	else if (SEARCH_R_IO == BLACK_AREA & SEARCH_L_IO == WHITE_AREA)  //右转控制逻辑
		ctrl_comm = COMM_RIGHT;
	else ctrl_comm = COMM_STOP;                                    //停止
	
	if(ctrl_comm_last != ctrl_comm)                           // 检测上一次命令为COMM_STOP?
	{
			ctrl_comm_last = ctrl_comm;                              
		 	switch(ctrl_comm)
				{
					case COMM_UP:     STM32_run(50,10);break;    //控制电机
					case COMM_DOWN:   STM32_back(50,10);break;
					case COMM_LEFT:   STM32_Left(50,10);break;
					case COMM_RIGHT:  STM32_Right(50,10);break;
					case COMM_STOP:  STM32_brake(10);break;
					default : break;
				}
	}
}

  • 13
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
循迹和测速是智能小车常见的实验项目。下面是一个简单的stm32f103c8t6智能小车循迹、测速实验程序的源代码。 #include <STM32F10x.h> //定义驱动电机的引脚 #define MOTOR1_A GPIO_Pin_0 #define MOTOR1_B GPIO_Pin_1 #define MOTOR2_A GPIO_Pin_2 #define MOTOR2_B GPIO_Pin_3 //定义传感器的引脚 #define SENSOR_LEFT GPIO_Pin_4 #define SENSOR_MID GPIO_Pin_5 #define SENSOR_RIGHT GPIO_Pin_6 //定义速度常量 #define SPEED 1000 //定义测速的时间常量 #define INTERVAL 100 int main(void) { //初始化引脚和定时器 GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //配置引脚输出模式 GPIO_InitStructure.GPIO_Pin = MOTOR1_A | MOTOR1_B | MOTOR2_A | MOTOR2_B; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = SENSOR_LEFT | SENSOR_MID | SENSOR_RIGHT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //配置定时器,用于测速 TIM_TimeBaseStructure.TIM_Period = INTERVAL - 1; TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //循迹、测速逻辑 while(1) { //根据传感器的状态调整车辆的方向 if(GPIO_ReadInputDataBit(GPIOA, SENSOR_LEFT) == Bit_RESET && GPIO_ReadInputDataBit(GPIOA, SENSOR_MID) == Bit_SET && GPIO_ReadInputDataBit(GPIOA, SENSOR_RIGHT) == Bit_RESET) { //只中间传感器检测到 GPIO_SetBits(GPIOA, MOTOR1_A); GPIO_ResetBits(GPIOA, MOTOR1_B); GPIO_SetBits(GPIOA, MOTOR2_A); GPIO_ResetBits(GPIOA, MOTOR2_B); } else if(GPIO_ReadInputDataBit(GPIOA, SENSOR_LEFT) == Bit_SET && GPIO_ReadInputDataBit(GPIOA, SENSOR_MID) == Bit_RESET && GPIO_ReadInputDataBit(GPIOA, SENSOR_RIGHT) == Bit_SET) { //只两侧传感器检测到 GPIO_ResetBits(GPIOA, MOTOR1_A); GPIO_SetBits(GPIOA, MOTOR1_B); GPIO_ResetBits(GPIOA, MOTOR2_A); GPIO_SetBits(GPIOA, MOTOR2_B); } else if(GPIO_ReadInputDataBit(GPIOA, SENSOR_LEFT) == Bit_SET && GPIO_ReadInputDataBit(GPIOA, SENSOR_MID) == Bit_SET && GPIO_ReadInputDataBit(GPIOA, SENSOR_RIGHT) == Bit_RESET) { //只右侧传感器检测到 GPIO_ResetBits(GPIOA, MOTOR1_A); GPIO_SetBits(GPIOA, MOTOR1_B); GPIO_SetBits(GPIOA, MOTOR2_A); GPIO_ResetBits(GPIOA, MOTOR2_B); } else { //其他情况,停止车辆 GPIO_ResetBits(GPIOA, MOTOR1_A); GPIO_ResetBits(GPIOA, MOTOR1_B); GPIO_ResetBits(GPIOA, MOTOR2_A); GPIO_ResetBits(GPIOA, MOTOR2_B); } //启动定时器,测量小车的速度 TIM_Cmd(TIM2, ENABLE); //等待定时器计数完成 while(TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) == RESET); //停止定时器,重置计数值 TIM_Cmd(TIM2, DISABLE); TIM_SetCounter(TIM2, 0); } } 以上代码是一个简单的stm32f103c8t6智能小车循迹、测速实验程序。其中使用了引脚控制驱动电机的转向,通过传感器检测来调整小车的方向。通过定时器测量小车的速度,并在一定时间间隔内重复这个过程。代码中使用了定时器2来测量速度,依据传感器状态控制小车的转向,根据需要可以自行调整转向的逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值