基于STM32智能⼩车蓝⽛遥控实验(有代码含上位机)
⼩车设计
利⽤STM32作为智能⼩车的主控制器来驱动智能⼩车的直流电机⼯作,电机驱动芯⽚采⽤L298N微型集成电路电机驱动芯⽚,配合
STM32核⼼板使⽤实现四个直流电机运⾏和pwm软件调速,通过改变直流电机占空⽐的电压来改变平均电压的数值,从⽽改变电机的转速变化来驱动轮式机器⼈运⾏。轮式机器⼈⾏驶的状态有:前进、后退、左转、右转和停⽌。当轮式机器⼈在⾏驶过程中遇到障碍物,红外避障检测模块检测周围障碍物,轮式机器⼈⾃动停⽌或转向。通过WIFI⽆线信号作为传输媒介,以上位机或⼿机作为控制端来控制机器⼈的运动以及将摄像头所拍摄的视频信息在控制端界⾯中显⽰,这样便可观察轮式机器⼈周围的环境并对机器⼈进⾏实时监控。主要设计步骤有:
(1)根据提出⽅案的功能需求对智能⼩车进⾏结构设计。
(2)根据主控制器的基本结构和特点,设计总体硬件电路模块。总体硬件电路模块的设计包括电机驱动电路设计、红外避障电路设计、⽆线传输电路设计等。
(3)选择符合系统设计需求的系统软件,并在该软件的基础上编写驱动代码和应⽤软件代码。针对系统
功能的具体要求,从系统信号稳定传输的⾓度出发,对电机驱动、调速、⽆线路由器系统的改造、视频信息的接受与发送、红外避障模块的改造和控制端界⾯的设计等进⾏详细的分析与设计,并完成代码的编写与调试。
(4)把硬件开发板和软件平台结合起来,对视频监控智能⼩车整个系统进⾏了整体测试。对测试中出现的问题进⾏相关的改进⼯作,进⼀步提⾼系统⼯作的可靠性和稳定性。
根据提出⽅案的功能需求,对轮式机器⼈的整体结构进⾏设计,采⽤双⾯覆铜加硬的PCB板料作为轮式机器⼈的底盘,其优点是:不易变形、不易折断、轻量化、不易造成短路;选⽤抗⼲扰TT马达,其加⼊压敏抗组的转⼦可抵抗电机突然启动产⽣的⽕花⼲扰,避免触发信号错误,可有效降低马达启动噪⾳,并在启动时可提供更⼤电流,使马⼒更强;使⽤航模级抗滑橡胶轮胎内带海绵表⾯平整不易变形,在避障⾏⾛时刹车不易撞上障碍物。马达⽤马达锁⽚固定到机器⼈底盘上,轮⼦通过轴与马达相连。
在这⾥插⼊图⽚描述在这⾥插⼊图⽚描述
其余硬件设备均固定到机器⼈底盘上,包括电池座、红外避障传感器、wifi模块、摄像头、STM32单⽚机主控模块和L298N电机驱动芯⽚。机器⼈底盘俯视图⽰意图如图:
系统硬件设计
cs高手硬件系统主要由单⽚机主控模块、电源模块、电机驱动模块、红外避障模块控制终端模块和⽆线视频监控模块组成。硬件系统框图如图:
在这⾥插⼊图⽚描述
(1)主控模块
主控模块采⽤STM32F103为主控制器,STM32F103属于中低端的32位ARM微控制器,该系列芯⽚是意法半导体(ST)公司出品,其内核是Cortex-M3。该系列芯⽚按⽚内Flash的⼤⼩可分为三⼤类:⼩容量(16K和32K)、中容量(64K和128K)、⼤容量(256K、384K和512K)。芯⽚集成定时器,CAN,ADC,SPI,I2C,USB,UART,等多种功能。STM32F103可使⽤keil C语⾔编译,⽀持STLink-SWD在线调试,主要⽤于收集信息、处理数据、协调系统中的每个功能模块预计要完成的任务。在这⾥插⼊图⽚描述
(2)电源模块
电源模块在机器⼈的运⾏过程中,需要给单⽚机、电机、各⼤模块及传感器供电。为了保证系统的可靠供电,所以选择可充电的18650锂电池,如图3.5所⽰。**18650是锂离⼦电池的⿐祖–⽇本SONY公司当年为了节省成本⽽定下的⼀种标准性的锂离⼦电池型号,其中18表⽰直径为18mm,65表⽰长度
为65mm,0表⽰为圆柱形电池。**常见的18650电池分为锂离⼦电池、磷酸铁锂电池。锂离⼦电池电压为标称电压为3.7v,充电截⽌电压为4.2v,磷酸铁锂电池标称电压为3.2V,充电截⽌电压为3.6v容量通常为1200mAh-3350mAh,常见容量是2200mAh-2600mAh。
(3)电机驱动模块
电机驱动模块采⽤L298N为电机驱动芯⽚,其原理图如图3.6所⽰。L298N是ST公司⽣产的⼀种⾼电压、⼤电流电机驱动芯⽚。该芯⽚采⽤15脚封装。主要特点是:⼯作电压⾼,最⾼⼯作电压可达46V;输出电流⼤,瞬间峰值电流可达3A,持续⼯作电流为2A;额定功率
25W。内含两个H桥⾼电压⼤电流全桥式驱动器,可以⽤来驱动直流电动机和步进电动机、继电器线圈等感性负载;采⽤标准逻辑电平信号控制;具有两个使能控制端,在不受输⼊信号影响的情况下允许或禁⽌器件⼯作有⼀个逻辑电源输⼊端,使内部逻辑电路部分在低电压下⼯作;可以外接检测电阻, 将变化量反馈给控制电路。使⽤L298N芯⽚驱动电机,该芯⽚可以驱动⼀台两相步进电机或四相步进电机,也可以驱动两台直流电机,并联时可以驱动四台电机。此次研究将L298N配合STM32核⼼板⽆缝对插使⽤,实现⽆损扩展并对四个马达进⾏驱动和PWM调速。
控制终端模块有PC上位机和安卓⼿机两种,两种控制界⾯都能实现对于智能⼩车的各种运动状态的控制。
本模块采⽤720p⾼清USB摄像头,可以对轮式机器⼈的运动状态以及周围环境进⾏视频采集,然后将采集的视频数据通过⽆线信号返回到控制界⾯显⽰,以达到实时监控的⽬的。**USB接⼝是⽬前应⽤⽐较⼴泛的⼀种接⼝模式,⼏乎所有的产品都能⽀持,即插即⽤,具有强⼤的扩充能⼒,⽤起来⼗分⽅便。**依靠USB连接⽆线路由器获得的电压就能否满⾜摄像头正常⼯作需求的电压,这样就不⽤再接外部电压,使得电路设计更加简单⽅便。USB摄像头虽然在采集动态画⾯与成像清晰度上仍然⽆法与接⼝摄像头相⽐,但是其接⼝简单,即插即⽤,⼰经成为设计者的⾸选。本模块主要是⽤来完成轮式机器⼈与各个控制界⾯之间的通信,由于机器⼈移动性的特点,所以系统选⽤⽆线通信进⾏数据传输。⽆线通信的实现主要由⽆线路由器实现,通过⽆线路由器可以搭建⼀个局域⽹,并且在这局域⽹的基础上可以运⾏多种底层协议。控制终端与轮式机器⼈进⾏信号的控制和交互就是采⽤这种传输模式。⾸先运⾏于控制终端的⽹络程序通过局域⽹与轮式机器⼈建⽴起连接,待连接建⽴成功后,⽤户就可以使⽤控制终端的⽤户界⾯软件向轮式机器⼈发送各种控制指令和获取摄像头视频信息等数据。本系统设计将数字摄像头的驱动加载在⽆线路由器固件当中,当主控制器发出采集视频指令,摄像头开始⼯作。
系统软件设计
软件的设计包括:主程序的设计、电机驱动程序设计、红外循障程序设计、视频采集程序设计、⽆线数据传输程序设计。
(1)电机驱动程序
电机的驱动主要是对L298N驱动芯⽚的操作,运⽤PWM调速⽅法完成对电机进⾏驱动控制。脉冲宽度调制(PWM),简称脉宽调制,是利⽤微处理器的数字输出来对模拟电路进⾏控制的⼀种⾮常有效的技术。PWM波的产⽣可以通过时钟频率、⾃动重装值等参数进⾏设置,从⽽调节PWM波的占空⽐和输出频率,即对脉冲宽度的控制,PWM原理如图:
由图我们先假定定时器⼯作正处于向上计数PWM模式,且当CNT⼩于CCRx 时,输出0,当CNT⼤于等于CCRx 时输出 1。那么就可以得到如上的PWM⽰意图:当CNT值⼩于CCRx的时候,IO输出低电平(0),当CNT值⼤于等于CCRx的时候,IO输出⾼电平(1),当CNT达到ARR值的时候,重新归零,然后重新向上计数,依次循环改变CCRx的值,就可以改变PWM输出的占空⽐,改变ARR的值,就可以
改变PWM输出的频率,这就是PWM输出的原理。由此可知PWM 技术就是把直流电压斩成⼀系列脉冲,通过改变脉冲的占空⽐获得所需的输出电压。
由图L298N芯⽚的原理图,引脚A,B可⽤于输⼊PWM脉宽调制信号对电机进⾏调速控制。如果⽆须调速可将两引脚接5V,使电机⼯作在最⾼速状态,既将短接帽短接。假设驱动的两台直流电机分别为M1和M2,当输⼊信号端IN1接⾼电平输⼊端IN2接低电平时,电机M1正转。当信号端IN1接低电平,IN2接⾼电平,电机M1反转。控制另⼀台电机是同样的⽅式,输⼊信号端IN3接⾼电平,输⼊端IN4接低电平,电机M2正转(反之则反转)。PWM信号端A控制M1调速,PWM信号端B控制M2调速 。可通过单⽚机IO⼝状态来控制⼩车运⾏,电机具体运⾏⽅式如图
电机驱动程序使⽤了单⽚机定时器的PWM功能,通过输出频率及占空⽐可变的PWM波来驱动电机。具体实现⽅法为:⾸先,使能定时器和相关IO⼝时钟。其次,对定时器进⾏初始化并设置其⾃动重转载值和预分频值,将计数模式设置为向上计数模式。最后,再使能预装载寄存器,使能定时器,通过改变⽐较值CCRX,达到不同的占空⽐效果。智能⼩车电机驱动程序流程图如图所⽰(以M1为例):
1900年是闰年吗
在这⾥插⼊图⽚描述
蓝⽛
·蓝⽛( Bluetooth® ) : 是⼀种⽆线技术标准,可实现固定设备、 移动设备和楼宇个⼈域⽹之间的短距离数据交换(使⽤2.4—
星际争霸2剧情2.485GHz的ISM波段的UHF⽆线电波) 。 蓝⽛技术最初由电信巨头爱⽴信公司于1994年创制, 当时是作为RS232数据线的替代⽅案。 蓝⽛可连接多个设备, 克服了数据同步的难题。
如今蓝⽛由蓝⽛技术联盟(Bluetooth SpecialInterest Group, 简称SIG) 管理。 蓝⽛技术联盟在全球拥有超过25,000家成员公司,
它们分布在电信、计算机、 ⽹络、 和消费电⼦等多重领域。 IEEE将蓝⽛技术列为IEEE 802.15.1, 但如今已不再维持该标准。 蓝⽛技术联盟负责监督蓝⽛规范的开发, 管理合蓝⽛技术联盟的标准才能以“蓝⽛设备” 的名义进⼊市场。 蓝⽛技术拥有⼀套专利⽹络, 可发放给符合标准的设备。
与STM32接线⽅法 STM32F103C8T6
TXD----接PB11 RXD—接PB10
蓝⽛模块安装
· 蓝⽛模块上有RXD TXD GND VCC 注意位置⽅向
· 分别接到核⼼板J2上的 TD TX GND VCC
· RXD 对应 核⼼板J2 TD
· TXD 对应 核⼼板J2 TX
· GND 对应 核⼼板J2 GND
· VCC 对应 核⼼板J2 5V
TXD: 发送端, ⼀般表⽰为⾃⼰的发送端, 正常通信必须接另⼀个设备的RXD。
RXD: 接收端, ⼀般表⽰为⾃⼰的接收端, 正常通信必须接另⼀个设备的TXD。
正常通信时候本⾝的TXD永远接设备的RXD!
⾃收⾃发: 正常通信时RXD接其他设备的TXD, 因此如果要接收⾃⼰发送的数据顾名思义, 也就是
⾃⼰接收⾃⼰发送的数据, 即⾃⾝的TXD直接连接到RXD, ⽤来测试本⾝的发送和接收是否正常,是最快最简单的测试⽅法, 当出现问题时⾸先做该测试确定是否产品故障。也称回环测试。
软件部分代码
串⼝配置代码
#include "uart.h"
#include "interface.h"
//UART function
//UART3 TxD GPIOB10  RxD GPIOB11
void USART3Conf(u32 baudRate)
{
NVIC_InitTypeDef  NVIC_InitStruct;//定义⼀个设置中断的结构体
USART_InitTypeDef USART_InitSturct;//定义串⼝1的初始化结构体二年级上册语文期中考试卷人教版
GPIO_InitTypeDef GPIO_InitStruct;//定义串⼝对应管脚的结构体
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE);//打开串⼝管脚时钟
//USART3_Tx_Pin Configure
内蒙古旅游景点GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;//输出引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;//设置最⾼速度50MHz
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//推挽复⽤输出
GPIO_Init(GPIOB ,&GPIO_InitStruct);//将初始化好的结构体装⼊寄存器
//USART3_Rx_Pin Configure
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//GPIO模式悬浮输⼊
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;//输⼊引脚
GPIO_Init(GPIOB,&GPIO_InitStruct);//将初始化好的结构体装⼊寄存器
/
/USART3 Configure
USART_InitSturct.USART_BaudRate = baudRate;//波特率9600
USART_InitSturct.USART_WordLength = USART_WordLength_8b;//数据宽度8位
USART_InitSturct.USART_StopBits = USART_StopBits_1;//⼀个停⽌位
USART_InitSturct.USART_Parity = USART_Parity_No;//⽆奇偶校验
USART_InitSturct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitSturct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//使能发送与接收
USART_Init(USART3 ,&USART_InitSturct);//将初始化好的结构体装⼊寄存器
//USART1_INT Configure
//USART1_INT Configure
USART_ITConfig(USART3 , USART_IT_RXNE , ENABLE);//使能接收中断
/
/ USART_ITConfig(USART3 , USART_IT_TXE , ENABLE);
USART_Cmd(USART3 , ENABLE);//打开串⼝
USART_ClearFlag(USART3 , USART_FLAG_TC);//解决第⼀个数据发送失败的问题
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority =2;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//打开该中断
NVIC_Init(&NVIC_InitStruct);
}
void PutChar(u8 Data)
{
USART_SendData(USART3 , Data);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC)== RESET);//等待发送完毕
}
void PutStr(char*str)//发送⼀个字符串
{
while(*str !='\0')
{
USART_SendData(USART3 ,*str++);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC)== RESET);//等待发送完毕
}
}
void PutNChar(u8 *buf , u16 size)
{
申世京和李妍熙u8 i;
while(USART_GetFlagStatus(USART3, USART_FLAG_TC)== RESET);//防⽌第⼀字节丢失for(i=0;i<size;i++)
{
USART_SendData(USART3 , buf[i]);
while(USART_GetFlagStatus(USART3, USART_FLAG_TC)== RESET);//等待发送完毕
}
}
电机驱动代码
#include "motor.h"
#include "interface.h"
#include "stm32f10x.h"
//GPIO配置函数
void MotorGPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = FRONT_LEFT_F_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(FRONT_LEFT_F_GPIO,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FRONT_LEFT_B_PIN;
GPIO_Init(FRONT_LEFT_B_GPIO,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FRONT_RIGHT_F_PIN;
GPIO_Init(FRONT_RIGHT_F_GPIO,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FRONT_RIGHT_B_PIN;
GPIO_Init(FRONT_RIGHT_B_GPIO,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BEHIND_LEFT_F_PIN;