今天同样做三个实验 1、L298电机驱动实验 2、红外光电实验 3、超声波模块
一、L298电机驱动
L298N是ST公司的产品,内部包含4通道逻辑驱动电路,是一种电机的专用驱动器,即内含两个H桥的高电压大电流双全桥式驱动器,接收标准TTL逻辑电平信号,可驱动46V、2A以下的电
实验原理:
OUT1、 OUT2 和 OUT3、 OUT4 之间分别接 2 个电动机。
IN1、 IN2、 IN3、 IN4 引脚从单片机接输入控制电平,控制电机的正反转。
ENA, ENB (控制速度)接控制使能端,控制电机的停转。
左侧电机方向 |
| 右侧电机方向 |
|
|
| |
|
|
|
|
|
| |
pa2 | pb9 | pa1 | pc9 | 小车状态 | (左侧占空比)Pa0 | Pa3(右侧占空比) |
0 | 1 | 0 | 1 | 前行 | 相等 | 相等 |
1 | 0 | 1 | 0 | 后退 | 相等 | 相等 |
1 | 0 | 0 | 1 | 左转 |
|
|
0 | 1 | 1 | 0 | 右转 |
|
|
|
|
|
|
|
|
|
pa2 | pb9 | pa1 | pc9 |
|
0 | 1 | 0 | 1 | 左右两侧前行 |
1 | 0 | 1 | 0 | 左右两侧后退 |
|
|
|
| 微左转? |
|
|
|
| 微右转? |
|
|
|
| 左转? |
|
|
|
| 右转? |
对于电机的调速,我们采用 PWM 调速的方法。其原理就是开关管在一个周期内的导通时间是 t,周期为 T,则电机两端的平均电压 U=Vcc*(t/T)=a*Vcc。其中, a=t/T(占空比), Vcc 是电源电压。电机的转速与电机两端的电压成比例,而电机两端的电压与控制波形的占空比成正比例,占空比越大,电机转的越快。
参考代码:
将控制器的 PA2、 PB9、 PA1、 PC9 口分别连接到 298 的 IN1~IN4 上,
将拥有 PWM 的 PA0、 PA3连接到 298 的 ENA、 ENB,
通过改变 PA2、 PB9、 PA1、 PC9 口上的高低电平变化以控制小车的前进方向,
通过改变 PA0、 PA3 口上的高低电平的占空比以控制电机的转速
将 PA2、 PB9、 PA1、 PC9 口配置为 Output, PA0、 PA3 配置为 PWM 输出。
Counter Settings:
• 预分频器, NUCLEOF072RB 的工作频率默认为 8MHz,经 800 分频之后的工作频率为 10Khz。
• 计数模式,向下还是向下计数
• 计数周期:0~999,这样一个计数周期下来,时间刚好是 100 毫秒。
通过修改各通道的 Pulse 值修改各通道输出 PWM 占空比
参考代码(占空比修改)
使用 HAL 库中的__HAL_TIM_SetCompare 修改脉冲宽度来修改占空比,函数原型描述如下
|
|
//正常轮占空比
#define full_speed 200
//停止轮
#define null_speed 0
/*矫正时 ,低速轮占空比*/
#define correct_speed 100
#define MOTOR_A_CON1_GPIO GPIOA
#define MOTOR_A_CON1_PIN GPIO_PIN_2
#define MOTOR_A_CON2_GPIO GPIOB
#define MOTOR_A_CON2_PIN GPIO_PIN_9
#define MOTOR_A_EN_GPIO GPIOA
#define MOTOR_A_EN_PIN GPIO_PIN_0
#define MOTOR_B_CON1_GPIO GPIOA
#define MOTOR_B_CON1_PIN GPIO_PIN_1
#define MOTOR_B_CON2_GPIO GPIOC
#define MOTOR_B_CON2_PIN GPIO_PIN_9
#define MOTOR_B_EN_GPIO GPIOA
#define MOTOR_B_EN_PIN GPIO_PIN_3
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
void Change_Pulse(uint16_t left,uint16_t right)
{
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, left);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4, right);
}
//-----------------------------------------------
void Correct_Left(void)
{
Change_Pulse(correct_speed,full_speed);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_SET);
}
//------------------------------------------------
void Correct_Right(void)
{
Change_Pulse(full_speed,correct_speed);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_SET);
}
//-----------------------------------------------------
void Straight(void)
{
Change_Pulse(full_speed,full_speed);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_SET);
}
//-----------------------------------------------------
void Stop(void)
{
Change_Pulse(null_speed,null_speed);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_RESET);
}
二、红外光电实验
实验原理:
由原理图可看出,我们接线方法为中间接输出,两边分别对应电源和地。
发射到黑色,被吸收, 所以检测不到, 表现为红外管变暗, 这时输出高电平,
传感器灯 | 传感器io输出 |
亮,有障碍物 | 低 |
暗 | 高 |
我们通过查询方式来判断相应光电开关的状态改变,在循迹中,适当延时处理,就可以调整行驶方向。
软件配置:
引脚:从左至右 PC7 PC6 PB12 PB15 PB14
模块:从左至右 P18 P27 P26 P9 P8
参考代码:
#define Left1_GPIO GPIOC //×ó²à̽ͷ
#define Left1_PIN GPIO_PIN_7
#define Left2_GPIO GPIOC //×ó²à̽ͷ
#define Left2_PIN GPIO_PIN_6
#define Middle_GPIO GPIOB //¾àÀë̽²â
#define Middle_PIN GPIO_PIN_12
#define Right1_GPIO GPIOB //ÓÒ²à̽ͷ
#define Right1_PIN GPIO_PIN_15
#define Right2_GPIO GPIOB //ÓÒ²à̽ͷ
#define Right2_PIN GPIO_PIN_14
#define Left1 HAL_GPIO_ReadPin(Left1_GPIO,Left1_PIN)
#define Left2 HAL_GPIO_ReadPin(Left2_GPIO,Left2_PIN)
#define Middle HAL_GPIO_ReadPin(Middle_GPIO,Middle_PIN)
#define Right1 HAL_GPIO_ReadPin(Right1_GPIO,Right1_PIN)
#define Right2 HAL_GPIO_ReadPin(Right2_GPIO,Right2_PIN)
禁止超声波1秒的定时器
// HAL_UART_Receive_IT(&huart1,RxData, 6);
if(Left1 == GPIO_PIN_RESET)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);//Red
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
}
else if(Left2 == GPIO_PIN_RESET)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);//Green
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
}
else if(Middle == GPIO_PIN_RESET)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);//Blue
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
}
else if(Right1 == GPIO_PIN_RESET)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);//Yellow
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
}
else if(Right2 == GPIO_PIN_RESET)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);//White
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
}
三、超声波模块
实验原理:该模块共有4个引脚Vcc,Trig,Echo,GND
在模块上电以后,给Trig管脚一个持续20us以上的高电平,该模块可以开始工作。这时,该模块会自动从这一个“大喇叭”发送8个40KHZ的方波,并将Echo管脚拉高,然后自动检测是否有信号返回。如果返回,Echo管脚便拉低,那么Echo高电平持续的时间就是超声波从发送到接收的时间。我们要做的就是开启超声波模块,然后再通过Echo知道超声波从发送到接收的时间就可以。
软件配置:
在例程中我们通过查询方式来判断相应光电开关的状态改变,在循迹中,适当延时处理,就
参考代码:可考以调
定时器中断服务函数,主要是控制采样频率和保证Trig发出一个20us的高电平
HAL_TIM_Base_Start_IT(&htim6);
int ultrasonic = 0; //超声波是否工作,0代表没有工作
int ultrasonic_time;
unsigned char b[4]={0};
#define Echo_GPIO GPIOC
#define Echo_PIN GPIO_PIN_2
#define Trig_GPIO GPIOC
#define Trig_PIN GPIO_PIN_3
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==&htim6)
{
HAL_TIM_Base_Stop_IT(&htim6);
ultrasonic=0; //超声波模块还未工作
HAL_GPIO_WritePin(Trig_GPIO, Trig_PIN, GPIO_PIN_SET);
HAL_TIM_Base_Start_IT(&htim7);
}
else if(htim==&htim7)
{
HAL_GPIO_WritePin(Trig_GPIO,Trig_PIN, GPIO_PIN_RESET);
ultrasonic=1; //此时trig有了一个20us的电平,超声波模块开始工作
HAL_TIM_Base_Stop_IT(&htim7);
HAL_TIM_Base_Start_IT(&htim6);
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_6);
if(GPIO_Pin==GPIO_PIN_2)
{
if(HAL_GPIO_ReadPin(Echo_GPIO, Echo_PIN))
{
ultrasonic_time=__HAL_TIM_GET_COUNTER(&htim6);
}
else if(ultrasonic==1)
{
ultrasonic=0;
ultrasonic_time=__HAL_TIM_GET_COUNTER(&htim6)-ultrasonic_time;
ultrasonic_time=ultrasonic_time*170/100; //转换成距离cm
ultrasonic_time=ultrasonic_time%1000; b[0]=ultrasonic_time/100+'0';
ultrasonic_time=ultrasonic_time%100;
b[1]=ultrasonic_time/10+'0';
b[2]=ultrasonic_time%10+'0';
ultrasonic_time=0;
HAL_UART_Transmit(&huart1,b,3,10);
}
}
}
参考代码
整行驶方向。参考代码