嵌入式之路,贵在日常点滴

                                                                ---阿杰在线送代码


一、直流电机原理

下面是分析直流电机的物理模型图。其中,固定部分有磁铁,这里称作主磁极;固定部分还有电刷。转动部分有环形铁心和绕在环形铁心上的绕组。(其中2个小圆圈是为了方便表示该位置上的导体电势或电流的方向而设置的)

它的固定部分(定子)上,装设了一对直流励磁的静止的主磁极N和S,在旋转部分(转子)上装设电枢铁心。在电枢铁心上放置了两根导体连成的电枢线圈,线圈的首端和末端分别连到两个圆弧形的铜片上,此铜片称为换向片。换向片之间互相绝缘,由换向片构成的整体称为换向器。换向器固定在转轴上,换向片与转轴之间亦互相绝缘。在换向片上放置着一对固定不动的电刷B1和B2,当电枢旋转时,电枢线圈通过换向片和电刷与外电路接通。
  在电刷上施加直流电压U,电枢线圈中的电流流向为:N极下的有效边中的电流总是一个方向,而S极下的有效边中的电流总是另一个方向。这样两个有效边所受的洛伦兹力的方向一致(可以根据左手法则判定),电枢开始转动。
  具体来说就是,把上图中的+和-分别接到电池的正极和负极,电机即可转动;如果是把上图中的+和-分别接到电池的负极和正极,则电机会反方向转动。电机的转速可以理解为和外接的电压是正相关的(实际是由电枢电流决定)。
  总而言之,如果我们可以调节施加在电机上面的直流电压大小,即可实现直流电机调速,改变施加电机上面直流电压的极性,即可实现电机换向。

二、减速器

  一般直流电机的转速都是一分钟几千上万转的,所以一般需要安装减速器。减速器是一种相对精密的机械零件,使用它的目的是降低转速,增加转矩。减速后的直流电机力矩增大、可控性更强。按照传动级数不同可分为单级和多级减速器;按照传动类型可分为齿轮减速器、蜗杆减速器和行星齿轮减速器。

齿轮减速箱体积较小,传递扭矩大,但是有一定的回程间隙。
蜗轮蜗杆减速机的主要特点是具有反向自锁功能,可以有较大的减速比,但是一般体积较大,传动效率不高,精度不高。
行星减速机其优点是结构比较紧凑,回程间隙小、精度较高,使用寿命很长,额定输出扭矩可以做的很大,但价格略贵。 

三、电机实物接线图解

具体到我们的电机,我们可以看看电机后面的图解。

在这里插入图片描述

上面介绍了一大堆说直流电机只引出两个线,怎么这个电机有 6个线,而且还有两个大焊点呢?其实,根据上面的图解也知道,那两个焊点分别和黄线和棕线是连接在一起的。也就是说只有6 个线,而6P 排线中,中间的四根线(红绿白黑)是编码器的线,只是用于测速,和直流电机本身没有联系。我们在实现开环控制的时候无需使用。
  综上所述,我们只需控制施加在黄线和棕色线两端的直流电压大小和极性即可实现调试和换向。

四、电机编码器 

1.为什么要用电机编码器

电机编码器分两种,光电编码器和霍尔编码器。光电编码器精度更高,价格也比较贵。电机编码器可以测量出电机的角度、速度、正反转。有了电机编码器就可以监控电机的状态从而更好的控制电机。

2.电机编码器的使用

电机编码器有AB两相,AB相输出两个脉冲,编码器的所有信息都融合在这两个脉冲。
一般编码器都有四根线,VCC、GND、A相、B相。AB相接到单片机IO口捕获脉冲。

理想的AB相波形图。

图3.2.1

(1)根据A相超前还是滞后B相来判断正反转。

(2)电机每转一圈的脉冲数目是相同的,所以测量的脉冲数目除上一圈的总数目就是电机当前角度了。如果采用四倍频计数,还要再除上4。
(3)如果每隔一段时间读脉冲数目然后把计数器清0,那么所读的数目除上时间就相当于电机转速。

如果使用STM32,可以用定时器输入捕获的编码器模式来计数。直接读取计数器数值就可以了,而且自带滤波。 

五、为什么要用电机驱动

一般电机接上电源就可以转了,正接正转,反接反转。
如果要用单片机的IO口控制电机就需要电机驱动,原因是IO口功率不够驱动不了电机,而且单片机可能会烧掉。

六、TB6612电机驱动

TB6612FNG可以驱动两个电机,TB6612FNG 模块相对于传统的 L298N 效率上提高很多,体积上也大幅度减少,在额定范围内,芯片基本不发热。PWM控制的频率可达100kHZ。

TB6612 模块测试一个电机的接线图:

在这里插入图片描述 在这里插入图片描述

VM:电机驱动电压,一般为2.5~13.5V
VCC:芯片驱动电压,3.3V或5V
STBY:高电平(3.3V/5V)使能芯片,低电平进入待机状态
PWMA:电机A的PWM控制,接单片机
PWMB:电机B的PWM控制,接单片机
AIN1:电机A的逻辑输入,接单片机
AIN2:电机A的逻辑输入,接单片机
BIN1:电机B的逻辑输入,接单片机
BIN2:电机B的逻辑输入,接单片机
AO1:电机A的输出,接电机A
AO2:电机A的输出,接电机A
BO1:电机B的输出,接电机B
BO2:电机B的输出,接电机B

1.TB6612的接线


tb6612是双电机驱动,即可同时驱动两个电机,有四种电机控制模式:正转/反转/制动/停止

VM :5V-10V电压
VCC:逻辑电平输入(接到C8t6上时,接3.3v或5v都可) 

M1电机控制端:
pwmA:接到c8t6的pwm输出引脚上

(c8t6的pwm是通过定时器输出的,对照数据手册找到相应的定时器pwm输出通道即可)
AIN1\AIN2:接到c8t6的io口

(一个为高电平,另一个为低电平即可使电机转动)
AO1\AO2:接电机线

M2电机控制端:
pwmB:接到c8t6的pwm输出引脚上

(c8t6的pwm是通过定时器输出的,对照数据手册找到相应的定时器pwm输出通道即可)
BIN1\BIN2:接到c8t6的io口

(一个为高电平,另一个为低电平即可使电机转动)
BO1\BO2:接电机线

STBY:这是模块工作状态控制端,高电平工作,低电平不工作

(使用时可连接到c8t6的io口,只需把此io口设置为高电平即可)

GND:接地,连接一个即可

2.tb6612控制电机的正反转和转速


正反转是通过AIN1、AIN2、BIN1、BIN2四个引脚控制的,而电机转速是通过PWMA、PWMB控制的
真值表

可以看出只需改变AIN1、AIN2、BIN1、BIN2的高低电平就可实现电机的正反转

转速的改变是通过改变pwm的占空比来实现的,高电平占空比越小电机转速越慢,本人的理解是电机在单位时间内接到的高电平时间减少,他的速度就会变慢 

七、stm32代码实现

这里我选用的是模式1,有效电平为高 

/*motor.c
#include "motor.h"
#include "stm32f10x.h"                  // Device header
//AIN1->PB13	AIN2->PB12
//BIN1->PB1	BIN2->PB0
void motor_init(void)
{
	GPIO_InitTypeDef GPIO_InitTstrute;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	
	GPIO_InitTstrute.GPIO_Mode = GPIO_Mode_Out_PP;//通用推挽输出
	GPIO_InitTstrute.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_1 | GPIO_Pin_0;
	GPIO_InitTstrute.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitTstrute);						//端口初始化
	
	GPIO_SetBits(GPIOB,GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_1 | GPIO_Pin_0);//输出高
}
/*
TIM1 PWM部分初始化
arr:自动重装值
psc:时钟预分频数
定时时长:时长等于频率的倒数	
	频率:72MHZ/(psc+1) *  (arr+1)
PA11->ENA  TIM1_CH4
PA8 ->ENB  TIM1_CH1
*/
 
void TIM1_PWN_Init(u16 arr, u16 psc)
{
	GPIO_InitTypeDef GPIO_InitTstrute;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitstrute;
	TIM_OCInitTypeDef TIM_OCInitstrute;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//使能定时器1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIO外设时钟
	
	//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIOA.8 和 输出TIM1 CH4的PWM脉冲波形	GPIOA.11
	GPIO_InitTstrute.GPIO_Mode = GPIO_Mode_AF_PP;		//复用推挽输出
	GPIO_InitTstrute.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_11;//TIM1 CH1和TIM_CH4
	GPIO_InitTstrute.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitTstrute);//初始化GPIO
	
	//初始化TIM1
	TIM_TimeBaseInitstrute.TIM_Period = arr;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseInitstrute.TIM_Prescaler = psc;//设置用来作为TIMx时钟频率除数的预分频值 
	TIM_TimeBaseInitstrute.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseInitstrute.TIM_CounterMode = TIM_CounterMode_Up;//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitstrute);//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	
	//初始化TIM1 Channel1 PWM模式	
	TIM_OCInitstrute.TIM_OCMode = TIM_OCMode_PWM1;//选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitstrute.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
	TIM_OCInitstrute.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM1,&TIM_OCInitstrute);							 //根据T指定的参数初始化外设TIM1 OC1
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);	 //使能TIM1在CCR1上的预装载寄存器
	
	//初始化TIM1 Channel4 PWM模式	
	TIM_OCInitstrute.TIM_OCMode = TIM_OCMode_PWM1;	//选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitstrute.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
	TIM_OCInitstrute.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性:TIM输出比较极性高
	TIM_OC4Init(TIM1,&TIM_OCInitstrute);//根据T指定的参数初始化外设TIM1 OC4
	TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable); //使能TIM1在CCR4上的预装载寄存器
	
	TIM_Cmd(TIM1,ENABLE); 				//使能TIM1
	
	TIM_CtrlPWMOutputs(TIM1,ENABLE);//MOE 主输出使能,高级定时器必须开启这个
}	
 
void qian(u16 pwm)
{
	AIN1 = 1;
	AIN2 = 0;		
	BIN1 = 0;
	BIN2 = 1;
	TIM_SetCompare1(TIM1,pwm);//设置TIM1通道1 捕获/比较寄存器值为100可以计算出占空比:为1/20
	TIM_SetCompare4(TIM1,pwm);//设置TIM1通道4 捕获/比较寄存器值为500可以计算出占空比:为5/20
}
 
void hou(u16 pwm)
{
	AIN1 = 0;
	AIN2 = 1;		
	BIN1 = 1;
	BIN2 = 0;
	TIM_SetCompare1(TIM1,pwm);//设置TIM1通道1 捕获/比较寄存器值为100可以计算出占空比:为1/20
	TIM_SetCompare4(TIM1,pwm);//设置TIM1通道4 捕获/比较寄存器值为500可以计算出占空比:为5/20
}
 
void zuo(u16 pwm)
{
	AIN1 = 1;
	AIN2 = 0;		
	BIN1 = 1;
	BIN2 = 0;
	TIM_SetCompare1(TIM1,pwm);//设置TIM1通道1 捕获/比较寄存器值为100可以计算出占空比:为1/20
	TIM_SetCompare4(TIM1,pwm);//设置TIM1通道4 捕获/比较寄存器值为500可以计算出占空比:为5/20
}
 
void you(u16 pwm)
{
	AIN1 = 0;
	AIN2 = 1;		
	BIN1 = 0;
	BIN2 = 1;
	TIM_SetCompare1(TIM1,pwm);//设置TIM1通道1 捕获/比较寄存器值为100可以计算出占空比:为1/20
	TIM_SetCompare4(TIM1,pwm);//设置TIM1通道4 捕获/比较寄存器值为500可以计算出占空比:为5/20
}
 
void tingzhi(void)
{
	AIN1 = 0;
	AIN2 = 0;		
	BIN1 = 0;
	BIN2 = 0;
}
/* motor.h
#ifndef _MOTOR_H
#define _MOTOR_H
#include "stm32f10x.h"
#include "sys.h"
#define AIN1 PBout(13)
#define AIN2 PBout(12)
#define BIN1 PBout(1)
#define BIN2 PBout(0)
//L298N驱动
//AIN1->PB13	AIN2->PB12
//BIN1->PB1	BIN2->PB0
void motor_init(void);
/*
TIM1 PWM部分初始化
arr:自动重装值
psc:时钟预分频数
定时时长:时长等于频率的倒数	
	频率:72MHZ/(psc+1) *  (arr+1)
*/
void TIM1_PWN_Init(u16 arr, u16 psc);
 
void qian(u16 pwm);
void hou(u16 pwm);
void you(u16 pwm);
void zuo(u16 pwm);
void tingzhi(void);
 
#endif