1.电机模块开发
L9110s概述
接通VCC,GND 模块电源指示灯亮, 以下资料来源官方,具体根据实际调试
IA1输入高电平,IA1输入低电平,【OA1 OB1】电机正转;
IA1输入低电平,IA1输入高电平,【OA1 OB1】电机反转;
IA2输入高电平,IA2输入低电平,【OA2 OB2】电机正转;
IA2输入低电平,IA2输入高电平,【OA2 OB2】电机反转;
接线参考:
B-1A -- PA0
B-1B -- PB1
A-1A -- PA1
A-1B -- PB10
1.1 让小车动起来
代码实现:
motor.c
#include "motor.h" void goForward(void) { // 左轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); // 右轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); } void goBack(void) { // 左轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); // 右轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); } void goLeft(void) { // 左轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); // 右轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); } void goRight(void) { // 左轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); // 右轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); } void stop(void) { // 左轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); // 右轮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); }
motor.h
#ifndef __MOTOR_H__ #define __MOTOR_H__ #include "main.h" void goForward(void); void goBack(void); void goLeft(void); void goRight(void); void stop(void); #endif
main.c
#include "motor.h" //main函数的while循环部分: while (1) { goForward(); HAL_Delay(1000); goBack(); HAL_Delay(1000); goLeft(); HAL_Delay(1000); goRight(); HAL_Delay(1000); stop(); HAL_Delay(1000); }
1.2 串口控制小车方向
- 串口分文件编程进行代码整合——通过现象来改代码
- 接入蓝牙模块,通过蓝牙控制小车
- 添加点动控制,如果APP支持按下一直发数据,松开就停止发数据(蓝牙调试助手的自定义按键不 能实现),就能实现前进按键按下后小车一直往前走的功能
代码实现:
usart.c
#include "usart.h" #include "string.h" #include "stdio.h" #include "motor.h" //串口接收缓存(1字节) uint8_t buf=0; //定义最大接收字节数 200,可根据需求调整 #define UART1_REC_LEN 200 // 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节 uint8_t UART1_RX_Buffer[UART1_REC_LEN]; // 接收状态 // bit15, 接收完成标志 // bit14, 接收到0x0d // bit13~0, 接收到的有效字节数目 uint16_t UART1_RX_STA=0; #define SIZE 12 char buffer[SIZE]; // 接收完成回调函数,收到一个数据后,在这里处理 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // 判断中断是由哪个串口触发的 if(huart->Instance == USART1) { // 判断接收是否完成(UART1_RX_STA bit15 位是否为1) if((UART1_RX_STA & 0x8000) == 0) { // 如果已经收到了 0x0d (回车), if(UART1_RX_STA & 0x4000) { // 则接着判断是否收到 0x0a (换行) if(buf == 0x0a) { // 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1 UART1_RX_STA |= 0x8000; // 灯控指令 if(!strcmp(UART1_RX_Buffer, "M1")) goForward(); else if(!strcmp(UART1_RX_Buffer, "M2")) goBack(); else if(!strcmp(UART1_RX_Buffer, "M3")) goLeft(); else if(!strcmp(UART1_RX_Buffer, "M4")) goRight(); else stop(); memset(UART1_RX_Buffer, 0, UART1_REC_LEN); UART1_RX_STA = 0; } else // 否则认为接收错误,重新开始 UART1_RX_STA = 0; } else // 如果没有收到了 0x0d (回车) { //则先判断收到的这个字符是否是 0x0d (回车) if(buf == 0x0d) { // 是的话则将 bit14 位置为1 UART1_RX_STA |= 0x4000; } else { // 否则将接收到的数据保存在缓存数组里 UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf; UART1_RX_STA++; // 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收 if(UART1_RX_STA > UART1_REC_LEN - 1) UART1_RX_STA = 0; } } } // 重新开启中断 HAL_UART_Receive_IT(&huart1, &buf, 1); } } int fputc(int ch, FILE *f) { unsigned char temp[1]={ch}; HAL_UART_Transmit(&huart1,temp,1,0xffff); return ch; }
1.3 如何进行小车PWM调速
原理:
全速前进是LeftCon1A = 0; LeftCon1B = 1;
完全停止是LeftCon1A = 0;LeftCon1B = 0;
那么单位时间内,比如20ms, 有15ms是全速前进,5ms是完全停止, 速度就会比5ms全速前进,15ms完全停止获得的功率多,相应的速度更快!
开发:借用PWM的舵机控制代码
将控制车轮的4个 GPIO 口配置修改如下,否则小车动不起来。
原因:L9110每个控制口需要一高一低才可以动起来,如果PWM有效电平为高电平,则另一个 GPIO口则需要输出低电平才可以驱动轮子。
代码实现:
main.c
// main函数里 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); while (1) { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 8); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 8); HAL_Delay(1000); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 10); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 10); HAL_Delay(1000); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 15); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 15); HAL_Delay(1000); }
1.4 PWM方式实现小车转向
右转原理: 左轮速度大于右轮
左转原理: 右轮速度大于左轮
左右轮各自调速代码实现:
// main函数里 while (1) { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,8); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,15); HAL_Delay(1000); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,15); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,8); HAL_Delay(1000); }
2.循迹小车
2.1 循迹模块介绍
- TCRT5000传感器的红外发射二极管不断发射红外线
- 当发射出的红外线没有被反射回来或被反射回来但强度不够大时
- 红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态
- 被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和
- 此时模块的输出端为低电平,指示二极管被点亮
- 总结就是一句话,没反射回来,D0输出高电平,灭灯
接线方式
- VCC:接电源正极(3-5V)
- GND:接电源负极 DO:TTL开关信号输出0、1
- AO:模拟信号输出(不同距离输出不同的电压,此脚一般可以不接)
2.2 循迹小车原理
由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致 循迹模块上光敏三极管处于关闭状态,此时模块上一个LED熄灭。在没有检测到黑线时,模块上两个LED常亮
总结就是一句话,有感应到黑线,D0输出高电平 ,灭灯
2.3 循迹小车核心代码
硬件接线
- B-1A -- PA0
- B-1B -- PB1
- A-1A -- PA1
- A-1B -- PB10
- 循迹模块(左)-- PB3
- 循迹模块(右) -- PB4
代码示例:
#define LeftWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3) #define RightWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) // main函数里 while (1) { if (LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_RESET) goForward(); if (LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_RESET) goLeft(); if (LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_SET) goRight(); if (LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_SET) stop(); }
2.4 循迹小车解决转弯平滑问题
原理:两轮都有速度且一轮速度大于另一轮
代码实现:
#define LeftWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3) #define RightWheel_Value HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) // main函数里 while (1) { if(LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_RESET) { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,19); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,19); } if(LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_RESET) { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,15); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,8); } if(LeftWheel_Value == GPIO_PIN_RESET && RightWheel_Value == GPIO_PIN_SET) { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,8); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,15); } if(LeftWheel_Value == GPIO_PIN_SET && RightWheel_Value == GPIO_PIN_SET) { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,0); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,0); } }
STM32智能小车(循迹、跟随、避障、测速、蓝牙、wife、4g、语音识别)总结-2