认识电机
直流电机
直流电机(Direct Current Machine)是指能将直流电能转换成机械能(直流电动机)或将机械能转换成直流电能(直流发电机)的旋转电机。
它是能实现直流电能和机械能互相转换的电机。当它作电动机运行时是直流电动机,将电能转换为机械能;作发电机运行时是直流发电机,将机械能转换为电能。主要用于电动工具、洗衣机、空气净化器、玩具等小家电中,用于传输转矩和增加设备的灵活性。
直流减速电机
直流减速电机,即齿轮减速电机,是在普通直流电机的基础上,加上配套齿轮减速箱。齿轮减速箱的作用是,提供较低的转速,较大的力矩。同时,齿轮箱不同的减速比可以提供不同的转速和力矩。这大大提高了,直流电机在自动化行业中的使用率。
N20减速电机是一种广泛应用于电子设备、玩具、工业机器人、医疗器械、包装设备、办公设备、家用电器等领域的精密减速电机。它的电机结构紧凑、精度高、噪音小、承载能力强,可以在高速运转时保持平稳的运行状态,广泛应用于各种需要高精度、高效率、高可靠性的场合。
如下图所示, 我们可以看到N20减速电机其实是在普通电机的基础上增加了齿轮减速箱,从而实现了降低转速增大扭矩的目的.
减速器的原理
要想理解减速器的原理, 我们先来回顾一下初二物理的杠杆原理。如下图所示,在杠杆的一端放置一个球,我们要撬动这个球,假设F不变,如何才能轻松的撬动这个球呢? 我们就需要来计算力矩,力矩的公式:力矩=力臂*力
- 力矩(torque)是描述一个力如何使物体产生旋转的物理量。
- 力臂是力与旋转轴之间的垂直距离。
- 当力臂增大时,同样大小的力将产生更大的力矩,从而使物体更容易旋转。这就是为什么使用扳手时,手柄越长,旋转螺丝或螺母就越容易的原因。
如下图所示,我将当前案例的力臂划分出来。当F不变,我们增加力臂,就可以轻松将球撬动. 这也就是为什么有人吹牛,给我一个支点我能撬起月球.
明白了上面的原理, 下面我们再来分析一下电机的减速器, 上面介绍的是一个比较复杂的减速器,下面我们以两个齿轮为例,来解释一下为什么增加了减速箱之后,电机转速降低,力矩增大.
当电机转动之后,绿色小圆产生的力矩为M1 = FR, 那么红色圆输出的力矩为:M2 = F2R
在本次课程中,我们所使用的是这种TT马达, 它同样是普通电机加上减速齿轮构造而成.
接线方式如下:
驱动芯片介绍
注意: 模块已经默认是启动的状态,所以EEP引脚不焊, ULT引脚如不需要,也可以不焊
PWM方式控制
下面我们来介绍一下如何使用PWM方式驱动电机, 电机连接在驱动模块上面, 每个电机由两路PWM控制.
若想电机转动, 我们只需要将其中一路PWM复制, 另外一路PWM置为0即可
- 正转: PWM1=pwm, PWM2=0
- 反转: PWM1=0, PWM2=pwm
下图为电机转动时, 电流的流向图
电路原理图
示例代码
PWM控制
timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, 0);
timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3,pwm);
定时器初始化示例
#include "bsp_drv8833.h"
#include <stdio.h>
#define RCU_MOTOR_L1 RCU_GPIOA
#define PORT_MOTOR_L1 GPIOA
#define PIN_MOTOR_L1 GPIO_PIN_0
#define TIMER_MOTOR_L1 TIMER4
#define TIMER_MOTOR_CHANNEL TIMER_CH_0
#define RCU_MOTOR_L2 RCU_GPIOA
#define PORT_MOTOR_L2 GPIOA
#define PIN_MOTOR_L2 GPIO_PIN_1
#define TIMER_MOTOR_L2 TIMER4
#define TIMER_MOTOR_L2_CHANNEL TIMER_CH_1
#define RCU_MOTOR_R1 RCU_GPIOA
#define PORT_MOTOR_R1 GPIOA
#define PIN_MOTOR_R1 GPIO_PIN_2
#define TIMER_MOTOR_R1 TIMER4
#define TIMER_MOTOR_R1_CHANNEL TIMER_CH_2
#define RCU_MOTOR_R2 RCU_GPIOA
#define PORT_MOTOR_R2 GPIOA
#define PIN_MOTOR_R2 GPIO_PIN_3
#define TIMER_MOTOR_R2 TIMER4
#define TIMER_MOTOR_R2_CHANNEL TIMER_CH_3
#define MAX_PWM_VALUE 9999
void bsp_drv8833_gpio_init(){
rcu_periph_clock_enable(RCU_MOTOR_L1);
gpio_af_set(PORT_MOTOR_L1,GPIO_AF_2,PIN_MOTOR_L1);
gpio_mode_set(PORT_MOTOR_L1,GPIO_MODE_AF,GPIO_PUPD_PULLDOWN,PIN_MOTOR_L1);
gpio_output_options_set(PORT_MOTOR_L1,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,PIN_MOTOR_L1);
gpio_bit_write(PORT_MOTOR_L1,PIN_MOTOR_L1,RESET);
rcu_periph_clock_enable(RCU_MOTOR_L2);
gpio_af_set(PORT_MOTOR_L2,GPIO_AF_2,PIN_MOTOR_L2);
gpio_mode_set(PORT_MOTOR_L2,GPIO_MODE_AF,GPIO_PUPD_PULLDOWN,PIN_MOTOR_L2);
gpio_output_options_set(PORT_MOTOR_L2,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,PIN_MOTOR_L2);
gpio_bit_write(PORT_MOTOR_L2,PIN_MOTOR_L2,RESET);
/**********************************************************/
rcu_periph_clock_enable(RCU_MOTOR_R1);
gpio_af_set(PORT_MOTOR_R1,GPIO_AF_2,PIN_MOTOR_R1);
gpio_mode_set(PORT_MOTOR_R1,GPIO_MODE_AF,GPIO_PUPD_PULLDOWN,PIN_MOTOR_R1);
gpio_output_options_set(PORT_MOTOR_R1,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,PIN_MOTOR_R1);
gpio_bit_write(PORT_MOTOR_R1,PIN_MOTOR_R1,RESET);
rcu_periph_clock_enable(RCU_MOTOR_R2);
gpio_af_set(PORT_MOTOR_R2,GPIO_AF_2,PIN_MOTOR_R2);
gpio_mode_set(PORT_MOTOR_R2,GPIO_MODE_AF,GPIO_PUPD_PULLDOWN,PIN_MOTOR_R2);
gpio_output_options_set(PORT_MOTOR_R2,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,PIN_MOTOR_R2);
gpio_bit_write(PORT_MOTOR_R2,PIN_MOTOR_R2,RESET);
}
void bsp_drv8833_timer_init(){
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
rcu_periph_clock_enable(RCU_TIMER4);
timer_parameter_struct timer_parameter;
timer_oc_parameter_struct timer_oc_parameter;
timer_deinit(TIMER4);
timer_struct_para_init(&timer_parameter);
timer_parameter.period = 10000 - 1;
timer_parameter.prescaler = 240 - 1;
timer_init(TIMER4,&timer_parameter);
// 输出参数的初始化
timer_channel_output_struct_para_init(&timer_oc_parameter);
timer_oc_parameter.outputstate = TIMER_CCX_ENABLE;
// 通道配置
timer_channel_output_config(TIMER4,TIMER_CH_0,&timer_oc_parameter);
timer_channel_output_config(TIMER4,TIMER_CH_1,&timer_oc_parameter);
timer_channel_output_config(TIMER4,TIMER_CH_2,&timer_oc_parameter);
timer_channel_output_config(TIMER4,TIMER_CH_3,&timer_oc_parameter);
// 初始占空比配置
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_0,0);
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_1,0);
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_2,0);
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_3,0);
timer_channel_output_mode_config(TIMER4,TIMER_CH_0,TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER4,TIMER_CH_1,TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER4,TIMER_CH_2,TIMER_OC_MODE_PWM0);
timer_channel_output_mode_config(TIMER4,TIMER_CH_3,TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER4,TIMER_CH_0,TIMER_OC_SHADOW_ENABLE);
timer_channel_output_shadow_config(TIMER4,TIMER_CH_1,TIMER_OC_SHADOW_ENABLE);
timer_channel_output_shadow_config(TIMER4,TIMER_CH_2,TIMER_OC_SHADOW_ENABLE);
timer_channel_output_shadow_config(TIMER4,TIMER_CH_3,TIMER_OC_SHADOW_ENABLE);
timer_primary_output_config(TIMER4,ENABLE);
timer_enable(TIMER4);
}
void bsp_drv8833_init(void){
bsp_drv8833_gpio_init();
bsp_drv8833_timer_init();
}
void bsp_drv8833_set(int left, int right){
if(left > MAX_PWM_VALUE) left = MAX_PWM_VALUE;
if(left < -MAX_PWM_VALUE) left = -MAX_PWM_VALUE;
if(right > MAX_PWM_VALUE) right = MAX_PWM_VALUE;
if(right < -MAX_PWM_VALUE) right = -MAX_PWM_VALUE;
if(left > 0){
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_0,left);
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_1,0);
}else{
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_0,0);
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_1,-left);
}
if(right < 0){
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_2,0);
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_3,right);
}else{
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_2,-right);
timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_3,0);
}
}
void bsp_drv8833_test(){
bsp_drv8833_init();
int pwm = 0;
while(1){
pwm += 300;
bsp_drv8833_set(pwm,pwm);
delay_1ms(2000);
if(pwm > MAX_PWM_VALUE) pwm = 0;
printf("pwm: %d\n",pwm);
}
}