Arduino_mage2560 加 TB6612稳压版驱动MG513直流电机

写在前面:要驱动电机首先需要通过单片机输入控制信号到TB6612电机驱动板再通过TB6612驱动直流电机,所以先了解这仨兄弟再进行程序编写。有任何不清楚的地方可以在评论区提出哦!!如果你所使用的型号有所不同,理论上只需在代码稍微修改下即可。

目录

1.如何让直流电机转动

1.1 如何实现电机调速:

 1.2 PWM介绍:

 2.TB6612电机驱动板的作用

3.mage2560控制电机

 3.1:TB6612跟mage2560接线

3.2:程序编写

4.电机测速

        4.1:测速原理

 4.2:mage2560接收转速信号

              4.2.1:接线

        4.3:程序编写


1.如何让直流电机转动

说起来简单,只需要将电机线正负极接上12V的电压就行咯!

1.1 如何实现电机调速:

        1.如果我们可以调节施加在电机上面的电压大小, 即可实现直流电机调速。当然,由于Arduino可以输出PWM信号,在此我们使用PWM来控制电压大小

        2.改变施加电机上面电压的极性,即可实现电机正反转。

1.2 PWM介绍:

PWM中文叫做脉冲宽度调制,通过调节脉冲宽度改变占空比以改变平均输出电压

占空比
是一个脉冲周期内,高电平的时间与整个周期时间的比例

模拟出相应电压

 2.TB6612电机驱动器的作用

 电机驱动器的作用主要有仨:

  1. 精确控制:驱动器可以精确地控制电机的速度、位置和扭矩,以满足各种复杂的应用需求。
  2. 保护电机:驱动器可以监测电机的运行状态,如电流、电压和温度等,当检测到异常情况时,可以及时切断电源,以保护电机免受损坏。
  3. 提供多种控制方式:驱动器可以提供多种控制方式,如模拟量控制、脉冲控制、现场总线控制等,以满足不同应用场景的需求。
  4. 增强系统灵活性:通过驱动器,可以将电机与上位机或其他控制系统进行连接,实现更高级别的自动化控制和远程监控。

TB6612能通过额外的12V电源,来保证电机有充足电压驱动。

TB6612带稳压模块

2.1.理论上TB6612接上电机 同时 电源输入接口接上12V电源后,即可通过单片机输入PWM信号来驱动电机并控制速度,但是由于TB6612限制需要STBY引脚置1后,才会有PWM信号输入(才能驱动电机),由此列出真值表↓

TB6612真值表

2.3.而从上述 真值表 我们可以知道,TB6612的IN引脚的 高低电平决定了电机转动状态,IN1高电平正转 IN2高电平反转,IN为同值时制动停止 所以我们需要通过单片机输入相应的信号控制电机,如图所示,TB6612上面正好有两对IN引脚:

        AIN1AIN2BIN1 BIN2 分别连接 AO1AO2 BO1BO2 也就是俩电机正负极 ,来输入控制信号。此时就该考虑如何使用单片机输入控制信号。↓

3.mage2560控制电机

The first: TB6612的IN引脚 PWM引脚 需要信号输入,以及STBY置1。所以,需要在mage2650找到一个PWM输出口以及数字信号输出口。

Arduino_mage2560

 3.1:TB6612跟mage2560接线

             ps:在此之前 请先准备一些公对母杜邦线,同时TB6612需要外接12V电源给电机供电

TB6612---mage2560接线
TB6612丝印标识mage2560主板引脚
PWMA3(PWM)
AIN24
AIN15
STBY7
BIN18
BIN29
PWMB10(PWM)
GNDGND
5V(稳压版可向2560供电)5V

3.2:程序编写

     在此请先下载相关的IDE并确保接线准确无误后就可以根据接线编写程序了,思路如下:

  1. 定义相关接线引脚
  2. 初始化各个引脚
  3. 用PWM俩引脚控制电机转速 
  4. 使用IN引脚控制电机正反转                              

        实现:(烧录成功后两个电机会以最大速度正转)

//定义引脚名称
#define PWMA 3  //3为模拟引脚,用于PWM控制
#define AIN1 5
#define AIN2 4
#define PWMB 10  //10为模拟引脚,用于PWM控制
#define BIN1 8
#define BIN2 9
#define STBY 7  //2、4、8、12、7为数字引脚,用于开关量控制
#define Voltage A0 //使用模拟引脚

int PwmA, PwmB;
double V;

void setup() {
  //TB6612电机驱动模块控制信号初始化
  pinMode(AIN1, OUTPUT);//控制电机A的方向,(AIN1, AIN2)=(1, 0)为正转,(AIN1, AIN2)=(0, 1)为反转
  pinMode(AIN2, OUTPUT);
  pinMode(BIN1, OUTPUT);//控制电机B的方向,(BIN1, BIN2)=(0, 1)为正转,(BIN1, BIN2)=(1, 0)为反转
  pinMode(BIN2, OUTPUT);
  pinMode(PWMA, OUTPUT);//A电机PWM
  pinMode(PWMB, OUTPUT);//B电机PWM
  pinMode(STBY, OUTPUT);//TB6612FNG使能, 置0则所有电机停止, 置1才允许控制电机
  
  //初始化TB6612电机驱动模块
  digitalWrite(AIN1, 1);
  digitalWrite(AIN2, 0);
  digitalWrite(BIN1, 1);
  digitalWrite(BIN2, 0);
  digitalWrite(STBY, 1);
  analogWrite(PWMA, 0);
  analogWrite(PWMB, 0);

 //初始化串口,用于输出电池电压
  Serial.begin(9600);
  pinMode(Voltage,INPUT); //初始化作为输入端
}

/**************************************************************************
函数功能:设置指定电机转速
入口参数:指定电机motor,motor=1(2)代表电机A(B); 指定转速pwm,大小范围为0~255,代表停转和满速
返回  值:无
**************************************************************************/
void SetPWM(int motor, int pwm)
{
  if(motor==1&&pwm>=0)//motor=1代表控制电机A,pwm>=0则(AIN1, AIN2)=(1, 0)为正转
  {
    digitalWrite(AIN1, 1);
    digitalWrite(AIN2, 0);
    analogWrite(PWMA, pwm);
  }
  else if(motor==1&&pwm<0)//motor=1代表控制电机A,pwm<0则(AIN1, AIN2)=(0, 1)为反转
  {
    digitalWrite(AIN1, 0);
    digitalWrite(AIN2, 1);
    analogWrite(PWMA, -pwm);
  }
  else if(motor==2&&pwm>=0)//motor=2代表控制电机B,pwm>=0则(BIN1, BIN2)=(0, 1)为正转
  {
    digitalWrite(BIN1, 0);
    digitalWrite(BIN2, 1);
    analogWrite(PWMB, pwm);
  }
  else if(motor==2&&pwm<0)//motor=2代表控制电机B,pwm<0则(BIN1, BIN2)=(1, 0)为反转
  {
    digitalWrite(BIN1, 1);
    digitalWrite(BIN2, 0);
    analogWrite(PWMB, -pwm);
  }
}

void loop() 
{
  SetPWM(1, 255);//电机AB同时满速正转
  SetPWM(2, 255);
  V=analogRead(Voltage); //读取模拟引脚A0模拟量
  Serial.print(V*0.05371);  //对模拟量转换并通过串口输出
  Serial.println("V");
  delay(500);//正转3s
  
//  SetPWM(1, 0);//电机AB停止
//  SetPWM(2, 0);
//  delay(1000);//停止1s
//  
//  SetPWM(1, 128);//电机AB同时半速正转
//  SetPWM(2, 128);
//  delay(3000);//半速正转3s
//  
//  SetPWM(1, 0);//电机AB停止
//  SetPWM(2, 0);
//  delay(1000);//停止1s
//  
//  SetPWM(1, -255);//电机AB同时满速反转
//  SetPWM(2, -255);
//  delay(3000);//反转3s
//  
//  SetPWM(1, 0);//电机AB停止
//  SetPWM(2, 0);
//  delay(1000);//停止1s
//  
//  SetPWM(1, 255);//电机A满速正转
//  SetPWM(2, -255);//电机B满速反转
//  delay(3000);//持续3s
//  
//  SetPWM(1, 0);//电机AB停止
//  SetPWM(2, 0);
//  delay(1000);//停止1s
}

4.电机测速

        4.1:测速原理

                MG513电机采用的是霍尔式编码器,其原理是在圆盘上均匀分布若干不同的磁极,当电机旋转时就可输出若干脉冲信号,为了判断方向,输出的脉冲信号A相跟B相会有相位差,顺时针转动时A相下降沿对应B相高电平,逆时针时A相上升沿对应B相高电平。那如何计算转速呢,既然有输出脉冲信号,直接计算A或者B相单位时间内输出的脉冲数量就行了,但是 但是 但是  由于减速器的存在,计算出来的转速并不等于输出轴转速,所以 所以 所以 我们得知道电机的转速比!以及霍尔编码器的线数(编码器旋转一周能产生的脉冲数) 通过线数×减速比我们可以得知输出轴旋转一圈输出的脉冲数量。有了这个参数,我们就可以用单位时间内产生的脉冲数来计算电机输出轴转速了。

参考文档:http://t.csdnimg.cn/kUeIH

 4.2:mage2560接收转速信号

      知道了转速之后有什么用呢 答案是那三个字母 P~I~D!当然这不在本文章讨论范围之内,当务之急是让mage2560知道电机的转速。

              4.2.1:接线

        还是熟悉的图,现在主要了解一下中间四条编码电机线的用处。

         需要传输的就是编码器AB相这两条线的数据,所以考虑的问题也就是如何将这两条线接到TB6612再从TB6612输出到mage2560

        

TB6612-mage2560编码器数据传输接线
TB6612mage560
E1A21
E1B20
E2A19
E2B18

                         将俩电机的AB相输出线分别接在mage2560中断口

        4.3:程序编写

                        思路:

                               1.定义相关引脚

                               2.二频计数编写

                               3.四倍频计数

                               3.确定输出轴单圈转速及计算周期

#include "Arduino.h"

int reducation = 30; //减速比,根据电机参数设置,比如 15 | 30 | 60
int pulse = 13; //编码器旋转一圈产生的脉冲数该值需要参考商家电机参数
int per_round = pulse * reducation * 4;//车轮旋转一圈产生的脉冲数,四倍频计数乘以4 
long start_time = millis();//一个计算周期的开始时刻,初始值为 millis();
long interval_time = 50;//一个计算周期 50ms
double current_vel_l;//左轮转速
double current_vel_r;//右轮转速
volatile int countl = 0;//左轮正转,那么每计数一次自增1,如果是反转,那么每计数一次自减1
volatile int countr = 0;//右轮正转,那么每计数一次自增1,如果是反转,那么每计数一次自减1
int motor_lA = 21;//中断口是2
int motor_lB = 20;//中断口是3
int motor_rA =19;
int motor_rB =18;
int pwma = 3;
int ain1 = 9;
int ain2 = 8;
int stby = 10;
int pwmb = 5;
int bin1 = 6;
int bin2 = 7;
int led = 13;


void count_lA(){
  //2倍频计数实现
  //手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 2
  if(digitalRead(motor_lA) == HIGH){

    if(digitalRead(motor_lB) == HIGH){//A 高 B 高
      countl++;  
    } else {//A 高 B 低
      countl--;  
    }


  } else {

    if(digitalRead(motor_lB) == LOW){//A 低 B 低
      countl++;  
    } else {//A 低 B 高
      countl--;  
    }  

  }

}
//与A实现类似
//4倍频计数实现
//手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 4
void count_lB(){
  if(digitalRead(motor_lB) == HIGH){

    if(digitalRead(motor_lA) == LOW){//B 高 A 低
      countl++;
    } else {//B 高 A 高
      countl--;
    }


  } else {

    if(digitalRead(motor_lA) == HIGH){//B 低 A 高
      countl++;
    } else {//B 低 A 低
      countl--;
    }

  }

}

void count_rA(){
  //2倍频计数实现
  //手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 2
  if(digitalRead(motor_rA) == HIGH){

    if(digitalRead(motor_rB) == HIGH){//A 高 B 高
      countr++;  
    } else {//A 高 B 低
      countr--;  
    }


  } else {

    if(digitalRead(motor_rB) == LOW){//A 低 B 低
      countr++;  
    } else {//A 低 B 高
      countr--;  
    }  

  }

}
void count_rB(){
  if(digitalRead(motor_rB) == HIGH){

    if(digitalRead(motor_rA) == LOW){//B 高 A 低
      countr++;
    } else {//B 高 A 高
      countr--;
    }


  } else {

    if(digitalRead(motor_rA) == HIGH){//B 低 A 高
      countr++;
    } else {//B 低 A 低
      countr--;
    }

  }

}
//停止
void Stop(){
  digitalWrite(ain1,LOW);
  digitalWrite(ain2,LOW);
  digitalWrite(bin1,LOW);
  digitalWrite(bin2,LOW);
}
//正转
void up(){

    digitalWrite(ain1,HIGH);
    digitalWrite(ain2,LOW);
    digitalWrite(bin1,HIGH);
    digitalWrite(bin2,LOW);
    delay(500);
}
//反转
void back(){
  digitalWrite(ain1,LOW);
  digitalWrite(ain2,HIGH);
  digitalWrite(bin1,HIGH);
  digitalWrite(bin2,LOW);
  delay(2000);
}
//计算当前电机转速
void get_current_vel(){
  long right_now = millis();  
  long past_time = right_now - start_time;//计算逝去的时间
  if(past_time >= interval_time){//如果逝去时间大于等于一个计算周期
    //1.禁止中断
    noInterrupts();
    //2.计算转速 转速单位可以是秒,也可以是分钟... 自定义即可(目前单位为分)
    current_vel_l = (double)countl / per_round / past_time * 1000 * 60;//左轮
    current_vel_r = (double)countr / per_round / past_time * 1000 * 60;//右轮
    //3.重置计数器
    countl = 0;
    countr = 0;
    //4.重置开始时间
    start_time = right_now;
    //5.重启中断
    interrupts();

    Serial.println(current_vel_l);
    Serial.println(current_vel_r);

  }
}
//主函数
void setup() {
  Serial.begin(57600);//设置波特率  
  pinMode(motor_lA,INPUT);
  pinMode(motor_lB,INPUT);
  pinMode(motor_rA,INPUT);
  pinMode(motor_rB,INPUT);
  attachInterrupt(3,count_lA,CHANGE);
  attachInterrupt(2,count_lB,CHANGE);

  attachInterrupt(4,count_rA,CHANGE);
  attachInterrupt(5,count_rB,CHANGE);
  pinMode(pwma,OUTPUT);
  pinMode(ain1,OUTPUT);
  pinMode(ain2,OUTPUT);
  pinMode(pwmb,OUTPUT);
  pinMode(bin1,OUTPUT);
  pinMode(bin2,OUTPUT);
  pinMode(stby,OUTPUT);
  pinMode(led,OUTPUT);
  digitalWrite(stby,HIGH);
  analogWrite(pwma,20);
  analogWrite(pwmb,20);
}

void loop() {
  delay(10);
  get_current_vel();
      up();
      delay(2000);



}

                        

        

        

  • 27
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值