一、使用模块
1.小车底板、3个轮子
2.TB6612两路电机驱动模块
3.5路红外循迹模块(读到白色 给高电平,读到黑色,给低电平)
4.STM32F103C8核心板
5.OLED屏幕(4针)
6.诺干杜邦线
实物图

二、代码构思
1.通过核心板的PA8-PA12引脚接收红外模块的五路信号,白色为高电平,黑色为低电平。
2.开启定时2的PWM生成通道1、2来驱动两个轮子(我这里使用了PA0和PA1引脚)
3.PA6、PA7、PA8和PA9来外接OLED屏幕(引脚对应GND、VDD、SCK、SDA)
三、设计思路
两路电机驱动模块:通过控制定时器的占空比来实现对轮子速度的控制,利用差速来实现拐弯。
5路红外循迹模块:通过读取红外模块给的信号,来判断小车行驶的路线是否偏左或者偏右。
OLED模块:将占空比值显示出来,方便调参(可有可无)。
四、引脚配置及代码
1.引脚配置

2.代码
#include "main.h"
#include "tim.h"
#include "gpio.h"
#include "OLED.h"
void SystemClock_Config(void);
void Getgpio_Val(void);//读取五路红外模块引脚
void Set_LeftAin(uint8_t Ain1,uint8_t Ain2); //控制左轮顺时针/逆时针旋转
void Set_RightBin(uint8_t Bin1,uint8_t Bin2);//控制右轮顺时针/逆时针旋转
uint8_t Right_val,Left_val;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
OLED_Init();
//PA0
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
//PA1
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
Set_STBY(1);
while (1)
{
//将占空比在OLED上循环显示
Right_val = TIM2->CCR2;
Left_val = TIM2->CCR1;
OLED_Printf(0, 0, OLED_8X16, "R:%d ", Right_val);
OLED_Printf(0, 16, OLED_8X16, "L:%d ", Left_val);
OLED_Update();
//读取五路红外模块引脚
Getgpio_Val();
}
}
/* USER CODE BEGIN 4 */
/*
PA8 - PA12来接收五路红外模块的电平信号 对应OUT1-OUT5 白色高电平 黑色低电平
程序逻辑:当PA10为低电平时,且其他口为高电平,表示正常
当PA11/12为低电平,表示偏左行驶了,降低右轮速度使他转回轨迹
当PA8/9为低电平,表示偏右行驶了,降低左轮速度使他转回轨迹
参数:无参
*/
void Getgpio_Val(void)
{
//正常直行
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_10)== RESET)
{
Set_LeftAin(1,0);
Set_RightBin(1,0);
ControlGoSt(20,20);
}
//偏左1级
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11) == RESET)
{
Set_RightBin(0,1);
ControlRight(15);
}
//偏左2级
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12) == RESET)
{
Set_RightBin(0,1);
ControlRight(25);
}
//偏右1级
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9) == RESET)
{
Set_LeftAin(0,1);
ControlLeft(15);
}
//偏右2级
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8) == RESET)
{
Set_LeftAin(0,1);
ControlLeft(25);
}
else
{
Set_LeftAin(1,0);
Set_RightBin(1,0);
ControlGoSt(15,15);
}
}
/*
功能:控制左轮顺时针/逆时针旋转
参数:uint8_t Ain1,uint8_t Ain2(1为使能,0为断开)
PS:可以优化成一个参数
*/
void Set_LeftAin(uint8_t Ain1,uint8_t Ain2)
{
if(Ain1 == 1) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
else HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
if(Ain2 == 1) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
else HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);
}
/*
功能:控制右轮顺时针/逆时针旋转
参数:uint8_t Bin1,uint8_t Bin2(1为使能,0为断开)
PS:可以优化成一个参数
*/
void Set_RightBin(uint8_t Bin1,uint8_t Bin2)
{
if(Bin1 == 1) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET);
else HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET);
if(Bin2 == 1) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET);
else HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET);
}
/* USER CODE END 4 */
占空比控制电机模块(函数名需要到.h文件下声明)
//可以放在.h文件下宏定义
#define R_TURN 40
#define L_TURN 40
//直行函数
void ControlGoSt(uint8_t cnt1,uint8_t cnt2)
{
TIM2 -> CCR1 = cnt1;
TIM2 -> CCR2 = cnt2;
}
//右转函数
void ControlRight(uint8_t cnt1)
{
TIM2 -> CCR2 = cnt1;
//转弯轮
TIM2 -> CCR1 = R_TURN;
}
//左转函数
void ControlLeft(uint8_t cnt1)
{
TIM2 -> CCR1 = cnt1;
//转弯轮
TIM2 -> CCR2 = L_TURN;
}
//使能前轮/后轮转动
void Set_STBY(uint8_t behine)
{
if(behine == 1) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_SET);
else HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_RESET);
}
五、实际效果视频
五路红外模块寻迹小车(无PID简易开源HAL库版)
1万+

被折叠的 条评论
为什么被折叠?



