proface:整个小车是我很久之前做的,可能会有一些问题想不起来是怎么解决的,或许有一些知识点会说错,希望大家多包涵!!!!
当时因为电池电量不足了,所以我把轮胎拆了,才能勉强动起来,所以就成这个样子了!!!
我用的是32单片机的最小系统板-c8t6,这个最小系统是Cortex-M3内核的32位微控制器,它有的内部资源,我列举在下边:
GPIO | 37个GPIO,分别为PA0-PA15、PB0-PB15、PC13-PC15、PD0-PD1 |
ADC | 2个12bit ADC合计12路通道,外部通道:PA0到PA7+PB0到PB1, 内部通道:温度传感器通道ADC_Channel_16和内部参考电压通道ADC_Channel_17 |
Timer定时器 | 4个16bit定时器/计数器,分别为TIM1、TIM2、TIM3、TIM4 TM1带死区插入,常用于产生PWM控制电机 |
2个看门狗定时器(独立看门狗IWDG、窗口看门狗WWDG) | |
1个24bit向下计数的滴答定时器systick | |
通信资源 | 2*IIC,2*SPI,3*USART,1*CAN |
系统时钟 | 内部8MHz时钟HSI最高可倍频到64MHz,外部8MHz时钟HSE最高可倍频到72MHz |
L298N电机驱动模块是最常用的一款电机驱动模块,广泛使用于二路电机调速,接下来我简单介绍一下我使用的方法。
首先,有两种供电方式的选择,一种是对A端口直接进行直流电源12v的供电(但注意,无论采用哪种接入方式,此控制板必须与MCU公地),另外一种是5v供电的方式,但是这种供电方式的驱动能力不佳,我当时是使用的4节1.5v的电池供的电 ,但前提是需要把12v的电源供电口和5v的供电口接在一起(亲测有效)。右边下面第一个A通道使能和最后一个B通道使能,这两个端口是起到控制电机速度的,如果不需要控制电机速度,直接把跳线帽接上就可以,此时电机的速度就是固定的,如果需要控制电机的速度,则A、B通道使能就需要两路可调占空比的PWMs中间四个端口是控制左右两个电机的正、反转,停止的,详细操作如下表。
IN1 | IN2 |
IN3 | IN4 | ||
A端口 | 正转 | 高 | 低 | / | / |
反转 | 低 | 高 | / | / | |
停止 | 低 | 低 | / | / | |
高(无效) | 高(无效) | / | / | ||
B端口 | 正转 | / | / | 高 | 低 |
反转 | / | / | 低 | 高 | |
停止 | / | / | 低 | 低 | |
/ | / | 高(无效) | 高(无效) |
产生PWM波的代码:
void TIM3_PWM_Init(u16 arr,u16 psc) //设置定时器的初值和预分频系数
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//TIM3通道2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//TIM3通道1
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_Cmd(TIM3, ENABLE);
}
初始化控制电机转动方向的代码
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_3);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_5);
TCRT5000红外循迹模块是循迹小车中最常用的模块,原理大概就是红外发射二级管一直发射红外线,当发射的红外线反射回来的特别微弱或者没有被反射回来时,数字输出引脚(D0)会输出高电平,反之有强烈的光反射回来时,数字输出引脚(D0)就会输出低电平。A0这个引脚我们这里不需要用它,它是用来检测反射光强弱的,是模拟信号输出。
void xunji(void)
{
Read_xunji_Date(); //读循迹线值
qianjin();
if(xunji_1==0&&xunji_2==0&&xunji_3==0&&xunji_4==0)//0000
{
qianjin();
delay_ms(10);
}
if(xunji_1==0&&xunji_2==1&&xunji_3==1&&xunji_4==0)//0110
{
qianjin();
delay_ms(10);
}
if(xunji_1==0&&xunji_2==1&&xunji_3==0&&xunji_4==0)//0100
{
zuozhuan();
delay_ms(10);
}
if(xunji_1==0&&xunji_2==0&&xunji_3==1&&xunji_4==0)//0010
{
youzhuan();
delay_ms(10);
}
if(xunji_1==1&&xunji_2==0&&xunji_3==0&&xunji_4==0)//1000
{
zuozhuan();
delay_ms(10);
}
if(xunji_1==0&&xunji_2==0&&xunji_3==0&&xunji_4==1)//0001
{
youzhuan();
delay_ms(10);
}
}
这个模块的原理我在这就不介绍了,在前面的文章,我已经介绍了,需要的可以点击链接进入查看,(18条消息) 基于单片机的防撞系统设计_小张_Serendipity !的博客-CSDN博客https://blog.csdn.net/qq_62291061/article/details/130455304?spm=1001.2014.3001.5502计算测距距离的代码
//通过定时器4计数器值推算距离
float Hcsr04GetLength(void )
{
u32 t = 0;
int i = 0;
float lengthTemp = 0;
float sum = 0;
while(i!=5)
{
TRIG_Send_up;
delay_us(20);
TRIG_Send_down;
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9) == 0);
OpenTimerForHc();
i = i + 1;
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9) == 1);
CloseTimerForHc();
t = GetEchoTimer();
lengthTemp = ((float)t/58.0);//cm
sum = lengthTemp + sum ;
}
lengthTemp = sum/5.0;
return lengthTemp;
}
舵机的应用是最广泛的,可以作为智能车的转向轮调节,sg90舵机模块内是有控制电路的,控制信号通过信号线输入到内部的控制电路中,调制芯片将输入的信号进行调制,获得直流偏置电压。然后再由内部的基准电路产生周期为20ms,宽度为1.5ms的基准信号,将直流偏置电压和电位器电压进行比较,从而获得输出的电压差。由电压差控制舵机的转动,这个电压差的正负控制舵机正反转。通过调节不同大小的占空比控制舵机转动不同的角度。下面是对应关系。
实物图
控制关系
t = 0.5ms——————-舵机会转动 0 °
t = 1.0ms——————-舵机会转动 45°
t = 1.5ms——————-舵机会转动 90°
t = 2.0ms——————-舵机会转动 135°
t = 2.5ms——————-舵机会转动180
蓝牙模块我用的是HC-05,与c8t6通过串口通信协议进行数据传输,控制小车运动,需要使用一个手机蓝牙APP调试助手,大家可以自己去应用商店下载,我附下载的地方:
链接:https://pan.baidu.com/s/1mE3EkYYM3kPFaOUbA2lMBw
提取码:5888
可以看到这是蓝牙的操控界面,在这个界面,按下不同的按钮,手机会送给蓝牙不同的指令,各个指令的介绍如下:
指令G————对应执行前进;
指令J————对应执行右转;
指令H————对应执行左转;
指令K————对应执行后退;
指令A————对应执行停止;
具体代码
void lanyacontral(void) //蓝牙控制
{
if(flag == 'G')
{
qianjin();
}
if(flag == 'J')
{
youzhuan();
}
if(flag == 'H')
{
zuozhuan();
}
if(flag == 'K')
{
houtui();
}
if(flag == 'A')
{
stop();
}
}
以上就是做这个小车的一些过程,功能还不是很多,后期打算把PID控制和WiFi通信加进去,最后贴上工程所有的源代码,有需要的请自取,如果对你有帮助,希望能给个小爱心,不胜感激哦!!!
(18条消息) 基于stm32c8t6的循迹避障小车资源-CSDN文库https://download.csdn.net/download/qq_62291061/88014618?spm=1001.2014.3001.5503