基于stm32的智能小车作品(循迹避障蓝牙)(上)

基于stm32的智能小车作品(循迹避障蓝牙)(上)

  • 前言
  • 一、材料准备
  • 二、AD画板+焊接
    • 1.原理图
    • 2.pcb图
    • 3.裸板成品
    • 4.焊好后成品
  • 三、让轮子动起来并实现pwm调速
    • 1.接线
    • 2.实现pwm调速
  • 四、循迹小车制作
    • 1.tcrt5000l接线
    • 2.循迹模块用法
    • 3.循迹小车主函数
  • 总结
  • 整个工程文件的网盘链接

前言

观前提示:本文用来记录和分享我自己做智能小车的经历。本人小白一枚,从码龄可以看出,文章肯定有写的不好的和不正确的地方,欢迎大佬们在评论区指导。
我做智能小车的过程中参考了这几位大佬的文章制作
https://blog.csdn.net/weixin_43924857/article/details/100185086
https://blog.csdn.net/nishiwodebocai21/article/details/85624173
https://blog.csdn.net/Rendezvous1/article/details/108314776

基于stm32的智能小车作品(循迹避障蓝牙)(下)的链接:点击此处

下面开始正文。

一、材料准备

基于stm32的智能小车作品(循迹避障蓝牙)(上)_第1张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第2张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第3张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第4张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第5张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第6张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第7张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第8张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第9张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第10张图片
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第11张图片

序号 名称
1 18650电池两节
2 电池盒
3 stm32f103c8t6最小系统板
4 小车底盘和四个电机
5 5路tcrt5000l循迹模块
6 HY SRF05超声波模块
7 JDY-31蓝牙模块
8 st link下载器
9 主板需要的元器件
10 杜邦线若干

为什么没电机驱动和电源模块呢?
因为电机驱动和电源模块集成在主板上。这里说一下,电机驱动芯片用的是tb6612fng

二、AD画板+焊接

注意:我画的板好像有问题,作为一个大一新生还没学电路的我并不知道哪里出现了问题,这个问题的主要体现在我最后的成品之后,c8t6的PB引脚好像无法拉高电平,总之就是PB引脚不能正常使用,如果有大佬知道原因,希望能在评论区告诉我,谢谢。

下面是我画的板

1.原理图

基于stm32的智能小车作品(循迹避障蓝牙)(上)_第12张图片

2.pcb图

基于stm32的智能小车作品(循迹避障蓝牙)(上)_第13张图片

3.裸板成品

基于stm32的智能小车作品(循迹避障蓝牙)(上)_第14张图片

4.焊好后成品

基于stm32的智能小车作品(循迹避障蓝牙)(上)_第15张图片
主板下载百度网盘链接:点此下载 密码:owd3

三、让轮子动起来并实现pwm调速

我用的驱动是tb6612fng,我的电机最大驱动电压为5v,在这里我只说明驱动的接线,想知道这个驱动的详情请自行搜索学习

1.接线

从上面原理图可以看出
第一个驱动的pwm口分别连接PA6、PA7,AIN1、AIN2、BIN1、BIN2分别连接PB4、PB5、PB6、PB7。
第二个驱动的pwm口分别连接PB0、PB1,AIN1、AIN2、BIN1、BIN2分别连接PB12、PB13、PB14、PB15。
基于stm32的智能小车作品(循迹避障蓝牙)(上)_第16张图片
由图可一看出pwm的四个引脚对应TIM3的四个通道。
但是在我写程序的时候遇到前面说的PB引脚的问题,因此我只用了通道2和通道4,最后四个电机这样接线基于stm32的智能小车作品(循迹避障蓝牙)(上)_第17张图片
一个通道同时控制两个电机,实测可以正常使用。
综述所述,我只用控制两个pwm口:PA7和PB1,四个IN口PB6、PB7和PB14、PB15就可以让轮子动起来。

2.实现pwm调速

先放代码
这是moter.c 文件的代码:

void CarGo(void)
{
	//数值越大速度越慢
	TIM_SetCompare2(TIM3 , 300);
 
	TIM_SetCompare4(TIM3 , 300);	
	

	   GPIO_SetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_15);


}

void CarStop(void)
{
    TIM_SetCompare2(TIM3 , 900);
	
	TIM_SetCompare4(TIM3 , 900);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_SetBits(GPIOB,GPIO_Pin_7);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_SetBits(GPIOB,GPIO_Pin_15);

}

void CarLeftAround(void)
{
	    TIM_SetCompare2(TIM3 , 400);
	
	TIM_SetCompare4(TIM3 , 400);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	
	   GPIO_ResetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_SetBits(GPIOB,GPIO_Pin_15);

}

void CarRightAround(void)
{
		    TIM_SetCompare2(TIM3 , 400);
	
	TIM_SetCompare4(TIM3 , 400);
	
	   GPIO_ResetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_SetBits(GPIOB,GPIO_Pin_7);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_15);

}


void CarBack(void)
{
	TIM_SetCompare2(TIM3 , 300);

	TIM_SetCompare4(TIM3 , 300);
	

	   GPIO_ResetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_SetBits(GPIOB,GPIO_Pin_7);


	   GPIO_ResetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_SetBits(GPIOB,GPIO_Pin_15);

}

void CarLeft(void)
{
	TIM_SetCompare2(TIM3 , 300);

	TIM_SetCompare4(TIM3 , 900);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_15);

}

void CarBigLeft(void)
{
	TIM_SetCompare2(TIM3 , 100);

	TIM_SetCompare4(TIM3 , 900);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_15);

}

void CarRight(void)
{
	TIM_SetCompare2(TIM3 , 900);

	TIM_SetCompare4(TIM3 , 300);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_15);

	
}

void CarBigRight(void)
{
	TIM_SetCompare2(TIM3 , 900);

	TIM_SetCompare4(TIM3 , 100);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_6);    //控制右边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_7);
	
	   GPIO_SetBits(GPIOB,GPIO_Pin_14);    //控制左边轮胎
		GPIO_ResetBits(GPIOB,GPIO_Pin_15);

	
}


void TIM3_PWM_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure; 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 , ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
	
	
	TIM_TimeBaseStructure.TIM_Period = 899;
	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseInit(TIM3 , &TIM_TimeBaseStructure);
	
	//端口复用
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 	
	GPIO_Init(GPIOA, &GPIO_InitStructure);   
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 	
	GPIO_Init(GPIOB, &GPIO_InitStructure);   
	

	//PWM通道2
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 900;
	TIM_OC2Init(TIM3 , &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(TIM3 , TIM_OCPreload_Enable);
	

	//PWM通道4
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_Pulse = 900;
	TIM_OC4Init(TIM3 , &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(TIM3 , TIM_OCPreload_Enable);
	
	TIM_Cmd(TIM3 , ENABLE);
}
//配置电机的引脚  
//注意:由于PB引脚的问题,这四个引脚还需在xunji.c的文件中同时配置成上拉输入才能使调速、前进、后退这些功能正常使用
void GPIO_init_Init(void)
{
	 GPIO_InitTypeDef  GPIO_InitStructure;	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIO的外设时钟

    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_14|GPIO_Pin_15;//选择要用的GPIO引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置引脚模式为推挽输出模式						 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置引脚速度为50MHZ         
    GPIO_Init(GPIOB,&GPIO_InitStructure);//调用库函数,初始化GPIO
	
}

注意:由于PB引脚的问题,这四个引脚还需在xunji.c的文件中同时配置成上拉输入才能使调速、前进、后退这些功能正常使用。可以下拉到下面看xunji.c的代码,这里就不重复放出来了。

四、循迹小车制作

1.tcrt5000l接线

基于stm32的智能小车作品(循迹避障蓝牙)(上)_第18张图片
OUT1、OUT2、OUT3、OUT4、OUT5按顺序接PA1、PA2、PA3、PA4、PA5。

2.循迹模块用法

基于stm32的智能小车作品(循迹避障蓝牙)(上)_第19张图片
从图中可以知道当检测是白线时是高电平,反之低电平时就是检测到黑线

下面放代码:
xunji.h:

#ifndef __XUNJI_H
#define	__XUNJI_H

#include "stm32f10x.h"

#define L1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)
#define L2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)
#define M  GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)
#define R2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4)
#define R1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5) // L1 L2 M R2 R1 

void xunji_config(void);
void Read_xunji_Date(void);  //读循迹模块返回的值

#endif

xunji.c:

#include "xunji.h"

	
	
void xunji_config(void)	
{
  GPIO_InitTypeDef GPIO_InitStructure;	
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟
	
	//配置电机引脚,不知道什么原因要在这里配置成上拉才能实现pwm调速
  GPIO_InitStructure.GPIO_Pin =   GPIO_Pin_6 | GPIO_Pin_7|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);  //初始化PB端口
	

  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); // 使能PA端口时钟
	
	//配置红外引脚
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1 | GPIO_Pin_2  | GPIO_Pin_3 | GPIO_Pin_4| GPIO_Pin_5;;	//选择对应的引脚
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//配置GPIO模式,浮空输入       
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PC端口

}

//读取红外的信号
void Read_xunji_Date(void)
{
	L1;
	L2;
	M;
	R2;
	R1;
}

3.循迹小车主函数

int main(void)
{
	SystemInit();	// 配置系统时钟为72M 
    delay_init();    //延时初始化		
	xunji_config();   //循迹初始化
	TIM3_PWM_Init();	//电机pwm   TIM3
	CH_SR04_Init();  //超声波定时器    TIM4
	USART_Config();	//蓝牙串口

  while(1)
  {	
Read_xunji_Date(); //读循迹线值
	  
	  //车前4个循迹模块从左到右分别是 L1,L2,M,R2 ,R1
   
	 if(L1==1&&L2==1&&M==1&&R2==1&&R1==1)//11111
	  {
	  CarGo();		  //如果都没有读取到黑线,直走
	  delay_ms(10);
	  }

	  if(L1==1&&L2==1&&M==0&&R2==1&&R1==1)//11011
	  {
	  CarGo();        //如果中间一个读取到黑线,直走
	  delay_ms(10);
	  }	  
  
	 if(L1==1&&L2==0&&M==0&&R2==0&&R1==1)//10001
	  {
	  CarGo();        //如果中间三个读取到黑线,直走
	  delay_ms(10);
	  }	  

	  if(L1==1&&L2==0&&M==1&&R2==1&&R1==1)//10111
	  {
	  CarBigLeft();   //如果第二个读取到黑线,左转
	  delay_ms(10);
	  }

	  if(L1==1&&L2==1&&M==1&&R2==0&&R1==1)//11101
	  {
	  CarBigRight();   //如果第四个读取到黑线,右转
	  delay_ms(10); 
	  }

	  if(L1==0&&L2==1&&M==1&&R2==1&&R1==1)//01111
	  {
	  CarBigLeft();   //如果第一个读取到黑线,左转
	  delay_ms(10);
	  }

	  if(L1==1&&L2==1&&M==1&&R2==1&&R1==0)//11110
	  {
	  CarBigRight();   //如果第五个读取到黑线,左转
	  delay_ms(10); 
	  }
  
  }	
  
}

总结

至此循迹小车就简单的做完了,这是我第一次做的作品,随便用这种方式记录下来。
循迹的方法比较简单,只是为了能实现循迹功能。
整个过程会分两篇,下篇就把超声波和蓝牙写完。

整个工程文件的网盘链接

点此下载
提取码:pdqg

你可能感兴趣的:(单片机,stm32,嵌入式)