1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
寒假由于时间较长,自己就想做一个智能车玩玩,第一个做的是蓝牙小车,不过比较简单,我就不打算具体另开一个部分,到时候挑一些与避障小车不一样的部分说一下。我这个小车行走速度比较慢,还是存在一定瑕疵,线也比较凌乱,大体功能可以实现。
先贴小车的图片: 小车主要分为几个部分: 1.STM32F103RCT6,当然用来执行各种命令的,因为用的是学习板,占地比较大,以后有时间改成C8T6的核心板,这样占地小一些。 2.L298N电机驱动模块,主要用来驱动左右两个电机,这个模块下面介绍。 3.电池,这里我买的是一款航模电池 1800mah 20c 焊接好T插头的电池,输出的是12V电压 4.分电板,主要是把电池的12V分成一个12V和一个5V输出 5.舵机,用的是SG90模拟舵机,这个舵机是花费时间最多的,因为总和我想要的结果不太一样 6.超声波测距模块,用的是HC-SR04模块,具体使用我上一篇说过了 7.蓝牙模块,用的HC-05这个蓝牙模块主要是用在蓝牙小车,后来放在避障小车上用来输出前方障碍物数据 8.小车底盘+电机,这个在某宝上一搜就有,而且驱动方法都差不多。我这里用的是直流电机。还有步进电机,但是我没有采用 这一篇我主要来说一下怎样让小车跑起来,就是电机怎么动。 想让小车跑起来,最重要的就是电机,电机驱动主要是需要两个接口。 一.直流电机 这个是我用的小车电机的说明,其中我们想要驱动电机就是在“电机线-”和“电机线+”一个高电压一个低电压,就会实现电机的转动,这里高低电压的接法没有要求接法不同只是影响正反转而已。至于其他的与编码器相关的可以不用连线,这些是测量电机转速的。在电压一定的情况下,电流越大,相应的转速也应该越快。 正常用L298N模块可以驱动电机并达到很高的转速,我这里尝试了一下直接用单片机驱动,发现也可以使电机转起来但是速度相比较用模块来说要慢很多,我猜测应该和电流有很大关系。 二.L298N模块 这个就是L298N驱动模块的样子 其中前面三个端子 ,中间的接地,注意要与单片机共地,否则将无法正常驱动电机,左面的端子是+12V输入,用来给L298N模块供电,就是电源输出的+12V电压,右面的端子是+5V输出,注意不要把这5V当作输入,建议不要用这个5V做为单片机的供电端。 左右两边各有两个端子,分别是OUT1,OUT2和OUT3,OUT4,用来驱动两路电机,这里只需要把OUT与电机的的电机线连接到一起即可完成。 在前面三个端子旁边有四个排针,这四个排针是用来控制左右两边的OUT,这四个排针分别是IN1 IN2 IN3 IN4 ,排针左右两边有两个用跳帽盖上的排针,分别是ENA ENB目的是使能那四个IN。用跳帽连接默认是已经使能,拔下跳帽另外加信号就可以继续使用。 这是不同情况下的电机转动情况,后期可以用两种方法调节电机速度: 一.给EN使能,之后调节IN1 IN2 之间的电压差(通过调节PWM波占空比的方式实现)来控制速度。 二.是控制EN的电压也是通过条件PWM占空比来实现。我这里采用的就是这种方法。 这里我初始化四个IO口分别来控制四个IN端,来控制其正转反转。 void gpio_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); //使能PA,PB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //PA.4 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.4 // GPIO_SetBits(GPIOA,GPIO_Pin_4); //PA.4 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PA.5 端口配置, 推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz //GPIO_SetBits(GPIOA,GPIO_Pin_5); //PA.5 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.10端口配置, 推挽输出 GPIO_Init(GPIOB, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PB.11 端口配置, 推挽输出 GPIO_Init(GPIOB, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz } 这里我把几种电机转动情况来分类用函数来调用 void stop() { PAout(4)=0; PAout(5)=0; PBout(10)=0; PBout(11)=0;//停止 } void front() { PBout(10)=0; PBout(11)=1;//前进 PAout(4)=0; PAout(5)=1; } void left() { PAout(4)=0; PAout(5)=1; PBout(10)=1; PBout(11)=0;//左转 } void right() { PAout(4)=1; PAout(5)=0; PBout(10)=0; PBout(11)=1;//右转 } void turnleft() { PAout(4)=0; PAout(5)=1; PBout(10)=0; PBout(11)=0;//一电机停止 左转 } void turnright() { PAout(4)=0; PAout(5)=0; PBout(10)=0; PBout(11)=1;//一电机停止 右转 } void back() { PAout(4)=1; PAout(5)=0; PBout(10)=1; PBout(11)=0;//后退 } 这样就可以驱动轮胎转动,也就可以驱动小车任意方向运动。 下面是我设置了两路PWM波给两个EN信号,来控制电机速度,进而控制小车速度,我只用了普通的定时器来输出PWM波,没有用到高级定时器的刹车功能。 PWM1: #include "pwm.h" //PWM输出初始化 //arr:自动重装值 //psc:时钟预分频数 void TIM3_PWM4_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_GPIOB , ENABLE); //使能GPIO外设时钟使能 //设置该引脚为复用输出功能,输出TIM3 CH4的PWM脉冲波形 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM_CH4 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC4Init(TIM3, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx TIM_CtrlPWMOutputs(TIM3,ENABLE); //MOE 主输出使能 TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); //CH4预装载使能 TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3 } PWM2: #include "pwm2.h" //PWM输出初始化 //arr:自动重装值 //psc:时钟预分频数 void TIM3_PWM3_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_GPIOB , ENABLE); //使能GPIO外设时钟使能 //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //TIM_CH1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC3Init(TIM3, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx TIM_CtrlPWMOutputs(TIM3,ENABLE); //MOE 主输出使能 TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); //CH3预装载使能 TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3 两路PWM控制占空比 TIM_SetCompare3(TIM3,2400);//左轮电机转速 TIM_SetCompare4(TIM3,2530);//右轮电机转速 控制占空比函数数值越大转速越慢,在实际中,会遇到小车两个轮转速不一样,这里我没有用算法来调整,我采用手动调整到大概可以走直线,硬件的缺陷用软件来弥补。 到现在就可以用单片机+L298N模块来驱动电机,可以实现小车的任意方向行驶啦 具体代码之后上传 |
|
|
|
只有小组成员才能发言,加入小组>>
3318 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9063 浏览 16 评论
4088 浏览 18 评论
1183浏览 3评论
609浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
601浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2336浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1897浏览 2评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 02:06 , Processed in 1.177467 second(s), Total 80, Slave 61 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号