PWM驱动直流电机

这篇具有很好参考价值的文章主要介绍了PWM驱动直流电机。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、实验目的

二、实验要求

三、硬件部分

1. 主控模块

2. 电器驱动模块

3. 直流电机

 四、软件部分

1. 主程序

2.定时器输出PWM波原理

 五、实验总结


一、实验目的

  1. 掌握MSP432 PWM波的输出配置
  2. 掌握直流电机驱动的方法

二、实验要求

  1. 按键控制小车的前进方向。
  2. 实现小车加速前进,减速后退运动。

三、硬件部分

        本实验系统总体框图如图3.1所示,系统的电路原理图如图3.2所示。系统采用MSP432P401R作为系统主控,通过改变输出PWM波的占空比以及GPIO引脚的输出高低电平,经H桥电路电机驱动模块提供电机转动所需的电压和电流,以实现对电机的驱动,进而控制TI-RSLK小车的前进方向以及行驶速度。

PWM驱动直流电机

图3.1  系统总体框图

PWM驱动直流电机

 图3.2 系统电路原理图

1. 主控模块

        系统采用MSP432P401R芯片作为系统主控,MSP432是在MSP430单片机基础上,以32位ARM Cortex-M4F为内核的MCU,具有浮点单元和存储器保护单元,频率最高达48MHz。具有低功耗,片上外设资源丰富的特点。其引脚图如图3.3所示。

PWM驱动直流电机

 图3.3 MSP432P401R引脚图

2. 电器驱动模块

        系统采用DRV8838 H桥电机驱动器作为电机驱动模块,以实现对本实验中直流电机的驱动。该输出驱动器由配置为H桥的N沟道功率MOSFET组成,以驱动电机绕组。DRV8838电机驱动器的引脚图如图3.4所示,且DRV883X电机驱动器应用电路图如图3.5所示。

PWM驱动直流电机

PWM驱动直流电机

        本实验中,主控芯片P1.6、P1.7引脚分别连接左右两个DRV8838模块的PH管脚,通过IO端口输出高低电平控制直流电机的转向,进而控制小车的前行方向;主控芯片的P3.6、P3.7引脚分别连接左右两个DRV8838模块的nSLEEP管脚,通过IO端口输出高低电平控制直流电机的休眠,进而控制小车的启停;主控芯片的P2.6、P2.7引脚分别连接左右两个DRV8838模块的EN管脚,通过输出不同占空比的PWM波控制输送到电机的电功率,进而控制直流电机的转速,最后实现控制小车的行驶速度。

3. 直流电机

        系统采用如图3.6所示的直流有刷电机,该电机自带AB双相增量式磁性霍尔编码器,且电机响应频率为1-10KHz。根据洛伦兹力定律,电机将电能转换为机械能,这种机械动力为车轮提供扭矩,使车轮转动以实现小车的移动。

PWM驱动直流电机

 四、软件部分

1. 主程序

PWM驱动直流电机

 图4.1 主程序流程图

2.定时器输出PWM波原理

        实验采用定时器输出占空比可变的PWM波来实现对直流电机的驱动。MSP432P041R的Timer_A模块可主要分为两个部分:主计数器和捕获/比较模块。主计数器负责定时、计时/计数,计数值(TAR寄存器的值)被送到各个捕获/比较模块中,它们可在无需CPU干预情况下根据触发触发条件和计数器值自动完成某些测量和输出功能。当捕获/比较模块工作在比较模式时,每个捕获/比较模块将不断地将自身的比较值寄存器与主计数器的计数值进行比较,一旦相等,就将自动改变定时器输出引脚的输出电平,从而可在无需CPU干预的情况下输出PWM波、可变单稳态脉冲、移向方波、相位调制等常用波形。在本实验中,定时器A采用增减计数工作模式,输出采用翻转/复位模式,定时器输出PWM波的原理图如图4.2所示。

   

PWM驱动直流电机

图4.2 定时器输出PWM波的原理图

        图4.2是小车右轮直流电机的PWM驱动原理图,分析该图可知,定时器输出PWM波的周期由TA0CCR0寄存器比较值决定,占空比由TA0CCR0寄存器比较值和TA0CRR3寄存器比较值的比值决定。因此通过改变TA0CCR3寄存器的值,即可改变右直流电机的转速,进而控制右轮的转速。

#include "msp.h"
#include "../inc/Clock.h"

void PWM_Init(uint16_t period, uint16_t Rduty, uint16_t Lduty);
void PWM_Rduty(uint16_t Rduty);
void PWM_Lduty(uint16_t Lduty);
void Motor_Init(void);
void Motor_Stop(void);
void Motor_Forward(uint16_t leftDuty, uint16_t rightDuty);
void Motor_Right(uint16_t leftDuty, uint16_t rightDuty);
void Motor_Left(uint16_t leftDuty, uint16_t rightDuty);
void Motor_Backward(uint16_t leftDuty, uint16_t rightDuty);
void route1(uint16_t leftDuty,uint16_t rightDuty);
void route2(void);
void circle_R(uint16_t leftDuty,uint16_t rightDuty);
void circle_L(uint16_t leftDuty,uint16_t rightDuty);

/**
 * main.c
 */
void main(void)
{
    uint8_t button;

	WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;		// stop watchdog timer
    Clock_Init48MHz();
    LaunchPad_Init();//initialize the LEDS and buttons
    Motor_Init();
    Motor_Stop();
    while(1){
        while(LaunchPad_Input() == 0);  //wait for the input of the button(P1.0,P1.4)
        while(LaunchPad_Input()){       //wait until releasing
            button = LaunchPad_Input();
            if(button==0x03)            //when P1.0 and P1.4 both input,
                while(LaunchPad_Input());//reserve the status until releasing, to avoid mistakes
        }
        switch(button){
        case 0x01:                      //P1.1 input
            LaunchPad_Output(0x02);     //green
            Motor_Left(5000,5000);
            Clock_Delay1ms(2000);
            break;
        case 0x02:                      //P1.4 input
            LaunchPad_Output(0x04);     //blue
            Motor_Right(5000,5000);
            Clock_Delay1ms(2000);
            break;
        case 0x03:                      //P1.1 and P1.4 both input
            LaunchPad_Output(0x07);     //white
            route2();
            Clock_Delay1ms(2000);
            break;
        }
        Motor_Stop();
        LaunchPad_Output(0x01);         //red
        }

    }

//***************************PWM_Init*******************************
// PWM outputs on P2.6(TA0.3), P2.7(TA0.4)
// Inputs:  period : the value of TA0CCR0 //the Period of PWM is 2*period*8*(1/12M)
//          Rduty  : the value of TA0CCR3 //the duty cycle of PWM_P2.6 is Rduty/period
//          Lduty  : the value of TA0CCR4 //the duty cycle of PWM_P2.7 is Lduty/period
// Outputs: none
// SMCLK = 48MHz/4 = 12 MHz, 83.33ns
// Counter counts up to TA0CCR0 and back down
// Let Timerclock period T = 8/12MHz = 666.7ns
// period of P7.3 squarewave is 4*period*666.7ns
// P2.6=1 when timer equals TA0CCR3 on way down, P2.6=0 when timer equals TA0CCR3 on way up
// P2.7=1 when timer equals TA0CCR4 on way down, P2.7=0 when timer equals TA0CCR4 on way up
void PWM_Init(uint16_t period, uint16_t Rduty, uint16_t Lduty){
    if(Rduty >= period) return; // bad input
    if(Lduty >= period) return; // bad input
    P2->DIR |= 0xC0;          // P2.6, P2.7 output
    P2->SEL0 |= 0xC0;         // P2.6, P2.7 Timer0A functions
    P2->SEL1 &= ~0xC0;        // P2.6, P2.7 Timer0A functions
    TIMER_A0->CCTL[0] = 0x0080;      // CCI0 toggle
    TIMER_A0->CCR[0] = period;       // Period is 2*period*8*83.33ns is 1.333*period
    TIMER_A0->EX0 = 0x0000;          // divide by 1
    TIMER_A0->CCTL[3] = 0x0040;      // CCR3 toggle/reset
    TIMER_A0->CCR[3] = Rduty;        // CCR3 duty cycle is Rduty/period
    TIMER_A0->CCTL[4] = 0x0040;      // CCR4 toggle/reset
    TIMER_A0->CCR[4] = Lduty;        // CCR4 duty cycle is Lduty/period
    TIMER_A0->CTL = 0x02F0;        // SMCLK=12MHz, divide by 8, up-down mode
      //TA0CTL register
      // bit  mode
      // 9-8  10    TASSEL, SMCLK=12MHz
      // 7-6  11    ID, divide by 8
      // 5-4  11    MC, up-down mode
      // 2    0     TACLR, no clear
      // 1    0     TAIE, no interrupt
      // 0          TAIFG
}

//change the duty
void PWM_Rduty(uint16_t Rduty){
  if(Rduty >= TIMER_A0->CCR[0]) return; // bad input
  TIMER_A0->CCR[3] = Rduty;        // CCR13 duty cycle is Rduty/period
}

void PWM_Lduty(uint16_t Lduty){
  if(Lduty >= TIMER_A0->CCR[0]) return; // bad input
  TIMER_A0->CCR[4] = Lduty;        // CCR4 duty cycle is Lduty/period
}

//*******************Motor_Init*******************************
// Initialize GPIO pins for output
// P1.6 : R_DIR, to control the direction of the right motor(0-forward, 1-backward)
// P1.7 : L_DIR, to control the direction of the left motor(0-forward, 1-backward)
// P3.6 : R_nSLP, to enable or disable the right driver(0-disable, 1-enable)
// P3.7 : L_nSLP, to enable or disable the left  driver(0-disable, 1-enable)
// Input: none
// Output: none
void Motor_Init(void){
  // write this as part of Lab 13
    P1->SEL0 &= ~0xC0;
    P1->SEL1 &= ~0xC0;  // configure as GPIO
    P1->DIR |= 0xC0;    // make P1.6 & P1.7 out
    P1->OUT &= ~0xC0;

    P3->SEL0 &= ~0xC0;
    P3->SEL1 &= ~0xC0;  // configure as GPIO
    P3->DIR |= 0xC0;    // make P3.6 & P3.7 out
    P3->OUT &= ~0xC0;   // low current sleep mode
}

void Motor_Stop(void){
    P1->OUT &= ~0xC0;
    P2->OUT &= ~0xC0;   // off
    P3->OUT &= ~0xC0;   // low current sleep mode
}

void Motor_Forward(uint16_t leftDuty, uint16_t rightDuty){
    P1->OUT &= ~0xC0;   // set direction of motors
    PWM_Init(15000, rightDuty, leftDuty);     //Period of the PWM is 2*15000*8/12M=20ms
    P3->OUT |= 0xC0;    // activate motors
}

void Motor_Right(uint16_t leftDuty, uint16_t rightDuty){
    P1->OUT &= ~0x80;   // left wheel forward
    P1->OUT |= 0x40;    // right wheel backward
    PWM_Init(15000, rightDuty, leftDuty);
    P3->OUT |= 0xC0;    // activate motors
}

void Motor_Left(uint16_t leftDuty, uint16_t rightDuty){
    P1->OUT &= ~0x40;   // right wheel forward
    P1->OUT |= 0x80;    // left wheel backward
    PWM_Init(15000, rightDuty, leftDuty);
    P3->OUT |= 0xC0;    // activate motors
}

void Motor_Backward(uint16_t leftDuty, uint16_t rightDuty){
    P1->OUT |= 0xC0;   // set direction of motors
    PWM_Init(15000, rightDuty, leftDuty);
    P3->OUT |= 0xC0;    // activate motors
}
//*********************route************************************
/*
 * route 1:forward->backward->right->forward->left->forward->stop
 */
void route1(uint16_t leftDuty,uint16_t rightDuty){
    Motor_Forward(leftDuty, rightDuty);
    Clock_Delay1ms(1000);
    Motor_Backward(leftDuty, rightDuty);
    Clock_Delay1ms(1000);
    Motor_Right(leftDuty, rightDuty);
    Clock_Delay1ms(200);
    Motor_Forward(leftDuty, rightDuty);
    Clock_Delay1ms(1000);
    Motor_Left(leftDuty, rightDuty);
    Clock_Delay1ms(200);
    Motor_Forward(leftDuty, rightDuty);
    Clock_Delay1ms(1000);
    Motor_Stop();
}

/*
 * route2:run by diffent speed(20%->40%->80%)
 */
void route2(void){
    int rightDuty = 2000;
    int leftDuty = 2000;
    P1->OUT &= ~0xC0;   // direction of motors:forward
    PWM_Init34(10000, rightDuty, leftDuty);     //period=10000*(8/12M)s , duty=20%
    P3->OUT |= 0xC0;    // activate motors
    Clock_Delay1ms(1000);
    PWM_Duty3(rightDuty*2); //40%
    PWM_Duty4(leftDuty*2);
    Clock_Delay1ms(1000);
    PWM_Duty3(rightDuty*4); //80%
    PWM_Duty4(leftDuty*4);
    Clock_Delay1ms(1000);

    P1->OUT |= 0xC0;   // set direction of motors:backward
    Clock_Delay1ms(1000);
    PWM_Duty3(rightDuty*2); //40%
    PWM_Duty4(leftDuty*2);
    Clock_Delay1ms(1000);
    PWM_Duty3(rightDuty); //20%
    PWM_Duty4(leftDuty);
}

///*
// * spin in circle
// */
void circle_R(uint16_t leftDuty,uint16_t rightDuty){
    P1->OUT &= ~0x80;   // left wheel forward
    P1->OUT |= 0x40;    // right wheel backward
    PWM_Init(15000, rightDuty, leftDuty);
    //P3->OUT |= 0xC0;    // activate motors
    P3->OUT &= ~0x40;   //active left motor and close right motor
    P3->OUT |= 0x80;
    Clock_Delay1ms(3000);
    Motor_Stop();
}


 五、实验总结

        本实验中使用的智能小车是差分驱动的,即左右车轮分别使用两个电机驱动,然而由于电机自身的驱动差异性,以及运转过程中路况的影响,都会导致左右轮速度不同,从而在直线行驶过程中出现“偏移”现象。该问题很难通过开环控制消除,因此我们需要引入闭环控制,通过编码器监测左右两个电机转速,反馈并控制输出PWM波新占空比,以实现直线行驶。文章来源地址https://www.toymoban.com/news/detail-483843.html

到了这里,关于PWM驱动直流电机的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【51单片机】直流电机的驱动和PWM调速

    51单片机驱动直流电机与 PWM 调速是通过使用 51 单片机来控制直流电机的转速和方向。51 单片机通过控制电机的电流来实现驱动,并通过生成 PWM 信号来调节电机的转速。使用 PWM 调速可以使得直流电机的转速精确可控,并且减少了电机的功率损耗。在 51 单片机的控制系统中,

    2023年04月09日
    浏览(38)
  • 【STM32学习】——定时器输出比较功能&PWM脉宽调制&通用/高级定时器输出比较通道&舵机/直流电机简介&PWM驱动呼吸灯/舵机/直流电机代码实操

    声明:学习笔记根据b站江科大自化协stm32入门教程编辑,仅供学习交流使用!

    2024年02月03日
    浏览(52)
  • 一文搞懂如何使用STM32驱动直流电机(普通PWM输出和L298N、高级定时器输出带死区双通道互补PWM和IR2110S及自举电路、H桥电路和电机正反转)

    笔者从开始接触嵌入式单片机开始,就和驱动电机相伴而走。从最开始的直接买L298N驱动模块直接驱动直流电机,到现在自己设计PCB电路板驱动直流电机,可以说是和电机驱动共同成长了。现在笔者将这一过程的收获记录下来,希望对大家有所帮助。 不用详细了解L298N芯片和

    2024年02月02日
    浏览(45)
  • PWM控制直流电机

    一,TB6612电机驱动模块       直流电机属于大功率器件,GPIO无法直接驱动,需要电机驱动模块配合,才能驱动直流电机. TB6612可以驱动2个直流电机。由IN1,IN2控制电机旋转方向,由PWM控制电机旋转速度。 二,代码部分 核心代码还是为PWM部分,直流电机初始化也只是多初始化

    2023年04月27日
    浏览(36)
  • PWM如何控制直流电机

    智能车基础可是控制电机呀!如何设置频率,如何控制车的加速,减速,正反转状态~。是这篇文章要弄明白的 对于普通的 直流(有刷)电机 ,在其两个电极上接上合适的直流电源后,电机就可以满速转动,电源反接后,电机就反向转动。实际情况是我们要能控制电机的正反

    2024年01月18日
    浏览(44)
  • 12. 直流电机调速(PWM)

    直流电机介绍 •直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转 •直流电机主要由永磁体(定子)、线圈(转子)和换向器组成 •除直流电机外,常见的电机还有步进电机、舵机、无刷电机、空

    2024年02月11日
    浏览(40)
  • STM32PWM控制直流电机

    PWM介绍 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用 微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽 度的控制 PWM的原理: 假定定时器工作在向上计数 PWM 模式,且当 CNT=CCRx 时输出 1。那么就可以

    2024年02月08日
    浏览(45)
  • 【Arduino32】PWM控制直流电机速度

    震动传感器:1个 红黄绿LED灯:各一个 旋钮电位器:1个 直流电机:1个 1K电阻:1个 220欧电阻:3个 杜邦线:若干

    2024年02月07日
    浏览(35)
  • 51单片机-PWM调速(直流电机,智能小车的电机调速)

    这次来对PWM做一个总结 最近学习时,发现PWM控制在很多地方都会用到,比如使用PWM来控制电机的速度,使用PWM来生成想要的波形。 那么到底什么是PWM呢? PWM即 脉冲宽度调制 ,在具有惯性的系统中,可以通过对 一系列脉冲的宽度进行调制 ,来等效的获得所需要的模拟参量。

    2024年02月02日
    浏览(45)
  • STM32第八课:PWM控制直流电机

            TB6612FNG是一款新型驱动器件,能独立双向控制2个直流电机,它具有很高的集成度,同时能提供足够的输出能力,运行性能和能耗方面也具有优势因此在集成化、小型化的电机控制系统中,它可以作为理想的电机驱动器件。                           

    2024年03月24日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包