精华内容
下载资源
问答
  • 自动控制的经典理论,详细描述了PWM控制芯片的工作原理及内部架构,值得一看!
  • 摘要:介绍了PWM控制电路的基本构成及工作原理,给出了美国Silicon General公司生产的高性能集成PWM控制器SG3524的引脚排列和功能说明,同时给出了其在不间断电源中的应用电路。 关键词:PWM SG3524 控制器引言开关...
  • 开关电源一般都采用脉冲宽度调制(PWM)技术,其特点是频率高,效率高,功率密度高,可靠性高。然而,由于其开关器件工作在高频通断状态,高频的快速瞬变过程本身就是一电磁骚扰(EMD)源,它产生的EMI信号有很宽的...
  •  TDA16888是西门子公司生产的一款高性能、高集成度的PFC/PWM二合一单片控制器,其引脚功能见表2:  3.L4981  L4981是意法半导体公司生产的一款有源功率因数校正芯片,采用平均电流型控制方式,可与其他电路...
  • ENC28J60 SPI以太网控制芯片 ESP8266EX WIFI-芯片 FT232RL USB转串口 GD5800 串口MP3语音芯片 HL2202 灯光控制芯片 HT1621 LCD驱动芯片 HT9032D 来电显示芯片 HT9200A 双音多频DTMF信号发生器 HX711 电子秤AD芯片 L...
  • 最近在做一个项目需要用到PWM信号进行控制,查资料时发现有的是直接用单片机输出PWM信号对电路进行控制,有的是先用单片机控制专用的PWM芯片,然后再...顺便说一下我的项目要用到单片机,PWM控制的是MOS管,谢谢各位!
  • 摘要:随着集成电路设计技术的发展,在片上...随着超大规模集成电路的迅速发展,半导体工业进入深亚微米时代,器件特征尺寸越来越小,芯片规模越来越大,可以在单芯片上集成上百万到数亿只晶体管。如此密集的集成度使我
  • 高性能工业级16位高精度I2C转PWM接口SOC芯片 ● 接口标准 - 符合飞利浦的I2C标准规范,目前支持的速度为小于100kbit。建议使用50k - 1个使能脚(ZW10I8xE后缀带E的),低功耗应用中可以让芯片进入休眠模式...

    ZW10I8X系列

    高性能工业级16位高精度I2C转PWM接口SOC芯片

    接口标准

    - 符合飞利浦的I2C标准规范,目前支持的速度为小于100kbit。建议使用50k

    - 1个使能脚(ZW10I8xE后缀带E的),低功耗应用中可以让芯片进入休眠模式。

    - 总线可以并联3个(外部地址定义)或者32个(内部地址)设备进行,进行一主多从的控制模式。

    PWM输出特性

    - PWM输出范围70Hz-850KHz可调。

    - PWM频率为16位精度(70Hz)。

    - 占空比调节方式(0-128)。

    高精度内部振荡器

    - 出厂时精度校准为 ±1%。

    - 内部带晶振故障检测电路。

    超宽的工作电压

    - 宽工作电压范围。(2.5V-5.5V)。

    - 工业级和扩展级温度范围。

    - 上电自复位无需外部电路。

    - 上电电压检测电路,低电压自锁电路。

    超低的功耗

    - 3V 25 条件下的功耗 

    - 工作模式 2.2mA 。

    - 空闲模式 0.5mA 。

    - 掉电模式 <1 uA 。

    I/O和封装

    - 超小的封装SOT8,DIP8脚封装。特别适合便携式低功耗的应用。

    电气特性

    - 工作温度 -55°C 到+125°C。

    - 存储温度 -65°C到 +150°C。

    - 各个引脚对地的电压VCC+0.5V。

    - 最大工作电压6.0V。

    - 每个I/O引脚的DC 电流40.0 mA。

    - VCC 与GND 引脚的DC 电流200.0 mA。

     






    展开全文
  • 电机控制程序的三方面要点: 一、定时器的输出通道设置 二、电机频率的设定 三、占空比输入函数的设计 对于电机来说,转速与转向是最...一个定时器输出四路PWM控制四个电机。 在硬件上需要四个正反转控制引脚,四个PWM

    电机控制程序的三方面要点:

    一、定时器的输出通道设置
    二、电机频率的设定
    三、占空比输入函数的设计

    对于电机来说,转速与转向是最重要的表现。这里的程序是针对四个直流无刷电机来编写的。
    控制四个电机,是需要电机驱动板的,因为驱动电机需要的是电压,而芯片定时器外设所具有的的PWM输出的GPIO引脚,输出的是0/1组成的PWM波,而不是电压。所以我们需要电机驱动板来进行两者的转变。

    我常用的是做智能车用的DR8701E芯片的驱动板。一个定时器输出四路PWM控制四个电机。

    在硬件上需要四个正反转控制引脚,四个PWM输出引脚。具体信息详见my_motor.h。

    电机频率的设定:
    电机频率设定公式:
    ARR :自动重装载寄存器的值

    // CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
    // PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
    // 占空比P=CCR/(ARR+1)

    倒推一下
    (72MHZ= 72 000 000 HZ)

    -》假如电机想设定的频率是10kHZ=10 000HZ
    -》得出周期是T=1/f=1/10000s
    -》得出等式 1/10 000=ARR*(PSC+1)/72 000 000
    -》得出 ARR=7200,PSC=0

    然后配置PWM的输出结构体内容即可。

    ARR的值就是我们能输出的最大PWM值。

    占空比的设定:
    输出的CCR值(0~~ARR-1)
    // 占空比P=CCR/(ARR+1)

    详细代码如下:

    my_motor.c

    #include "my_motor.h"
    
    
    
    static void Dir_GPIO_Init(void)
    {
    	
       GPIO_InitTypeDef GPIO_InitStructure;
    
    	
      RCC_APB2PeriphClockCmd(Motor1_Dir_Gpio_Clk, ENABLE); //使能PB端口时钟
      GPIO_InitStructure.GPIO_Pin = Motor1_Dir_Gpio_Pin;	//端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50M
      GPIO_Init(Motor1_Dir_Gpio_Pork, &GPIO_InitStructure);	
    
    	 RCC_APB2PeriphClockCmd(Motor2_Dir_Gpio_Clk, ENABLE); //使能PB端口时钟
      GPIO_InitStructure.GPIO_Pin = Motor2_Dir_Gpio_Pin;	//端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50M
      GPIO_Init(Motor2_Dir_Gpio_Pork, &GPIO_InitStructure);	
    
    	 RCC_APB2PeriphClockCmd(Motor3_Dir_Gpio_Clk, ENABLE); //使能PB端口时钟
      GPIO_InitStructure.GPIO_Pin = Motor3_Dir_Gpio_Pin;	//端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50M
      GPIO_Init(Motor3_Dir_Gpio_Pork, &GPIO_InitStructure);	
    
    	 RCC_APB2PeriphClockCmd(Motor4_Dir_Gpio_Clk, ENABLE); //使能PB端口时钟
      GPIO_InitStructure.GPIO_Pin = Motor4_Dir_Gpio_Pin;	//端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50M
      GPIO_Init(Motor4_Dir_Gpio_Pork, &GPIO_InitStructure);	
    
    }
    
    
    ///*
    // * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
    // * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
    // * 另外三个成员是通用定时器和高级定时器才有.
    // *-----------------------------------------------------------------------------
    // *typedef struct
    // *{ TIM_Prescaler            都有
    // *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有
    // *  TIM_Period               都有
    // *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
    // *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
    // *}TIM_TimeBaseInitTypeDef; 
    // *-----------------------------------------------------------------------------
    // */
    
    /* ----------------   PWM信号 周期和占空比的计算--------------- */
    // ARR :自动重装载寄存器的值
    // CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
    // PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
    // 占空比P=CCR/(ARR+1)
    
    
    static void Pwm_GPIO_Init(void)
    {
    	
       GPIO_InitTypeDef GPIO_InitStructure;
    
    	
      RCC_APB2PeriphClockCmd(Motor1_Pwm_Gpio_Clk, ENABLE); //使能PB端口时钟
      GPIO_InitStructure.GPIO_Pin = Motor1_Pwm_Gpio_Pin;	//端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50M
      GPIO_Init(Motor1_Pwm_Gpio_Pork, &GPIO_InitStructure);	
    
    	 RCC_APB2PeriphClockCmd(Motor2_Pwm_Gpio_Clk, ENABLE); //使能PB端口时钟
      GPIO_InitStructure.GPIO_Pin = Motor2_Pwm_Gpio_Pin;	//端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50M
      GPIO_Init(Motor2_Pwm_Gpio_Pork, &GPIO_InitStructure);	
    
    	 RCC_APB2PeriphClockCmd(Motor3_Pwm_Gpio_Clk, ENABLE); //使能PB端口时钟
      GPIO_InitStructure.GPIO_Pin = Motor3_Pwm_Gpio_Pin;	//端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50M
      GPIO_Init(Motor3_Pwm_Gpio_Pork, &GPIO_InitStructure);	
    
    	 RCC_APB2PeriphClockCmd(Motor4_Pwm_Gpio_Clk, ENABLE); //使能PB端口时钟
      GPIO_InitStructure.GPIO_Pin = Motor4_Pwm_Gpio_Pin;	//端口配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50M
      GPIO_Init(Motor4_Pwm_Gpio_Pork, &GPIO_InitStructure);	
    }
    
      static void GENERAL_TIM_Mode_Config(void )
     {
    	   // 开启定时器时钟,即内部时钟CK_INT=72M
    	GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);
    /*--------------------时基结构体初始化-------------------------*/
    	// 配置周期,这里配置为100K
    	
      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    	TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;	
    	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
    	TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;	
    	// 时钟分频因子 ,配置死区时间时需要用到
    	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		
    	// 计数器计数模式,设置为向上计数
    	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;		
    	// 重复计数器的值,没用到不用管
    	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	
    	// 初始化定时器
    	TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
    
    
    	/*--------------------输出比较结构体初始化-------------------*/	
    	// 占空比配置
    
    
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	// 配置为PWM模式1
    	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    	// 输出使能
    	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    	// 输出通道电平极性配置	
    	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    	
    	
    // 输出比较通道 1
    	TIM_OCInitStructure.TIM_Pulse = 0 ;
    	TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);
    	TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
    		
    	// 输出比较通道 2
    	TIM_OCInitStructure.TIM_Pulse =0 ;
    	TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
    	TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
    	
    
    // 输出比较通道 3
    	TIM_OCInitStructure.TIM_Pulse = 0 ;
    	TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);
    	TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
    		
    	// 输出比较通道4
    	TIM_OCInitStructure.TIM_Pulse =0 ;
    	TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);
    	TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
    	
    		// 使能计数器
    	TIM_Cmd(GENERAL_TIM, ENABLE);
     }
    
     
     void Motor_Init(void )
     {
    	 Dir_GPIO_Init();
    	 Pwm_GPIO_Init();
    	 GENERAL_TIM_Mode_Config();
     }
     
     
     float constrain_float(float amt, float low, float high)
    {
        return ((amt)<(low)?(low):((amt)>(high)?(high):(amt)));
    }
     
    void MotorCtrl(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4)
    {
    
        /* 限幅  */
        constrain_float(motor1, -ATOM_PWM_MAX, ATOM_PWM_MAX);
        constrain_float(motor2, -ATOM_PWM_MAX, ATOM_PWM_MAX);
        constrain_float(motor3, -ATOM_PWM_MAX, ATOM_PWM_MAX);
        constrain_float(motor4, -ATOM_PWM_MAX, ATOM_PWM_MAX);
    
             if(0<=motor1) //电机1   正转 设置占空比为 百分之 (1000/TIMER1_PWM_DUTY_MAX*100)
             {
              	GPIO_SetBits(Motor1_Dir_Gpio_Pork,Motor1_Dir_Gpio_Pin);
                TIM_SetCompare1(GENERAL_TIM,motor1);
             }
             else                //电机1   反转
             {
             GPIO_ResetBits(Motor1_Dir_Gpio_Pork,Motor1_Dir_Gpio_Pin);
                  TIM_SetCompare1(GENERAL_TIM,-motor1);
             }
    
             if(0<=motor2) //电机2   正转
             {
              	GPIO_SetBits(Motor2_Dir_Gpio_Pork,Motor2_Dir_Gpio_Pin);
                  TIM_SetCompare2(GENERAL_TIM,motor2);
             }
             else                //电机2   反转
             {
                  GPIO_ResetBits(Motor2_Dir_Gpio_Pork,Motor2_Dir_Gpio_Pin);
                  TIM_SetCompare2(GENERAL_TIM,-motor2);
             }
    
             if(0<=motor3) //电机3   正转
             {
               	GPIO_SetBits(Motor3_Dir_Gpio_Pork,Motor3_Dir_Gpio_Pin);
               TIM_SetCompare3(GENERAL_TIM,motor3);
             }
             else                //电机3   反转
             {
                  GPIO_ResetBits(Motor3_Dir_Gpio_Pork,Motor3_Dir_Gpio_Pin);
               TIM_SetCompare3(GENERAL_TIM,-motor3);
             }
    
             if(0<=motor4) //电机4   正转
             {
               	GPIO_SetBits(Motor4_Dir_Gpio_Pork,Motor4_Dir_Gpio_Pin);
                 TIM_SetCompare4(GENERAL_TIM,motor4);
             }
             else                //电机4   反转
             {
                  GPIO_ResetBits(Motor4_Dir_Gpio_Pork,Motor4_Dir_Gpio_Pin);
                 TIM_SetCompare4(GENERAL_TIM,-motor4);
             }
    }
     
    

    my_motor.h

    #ifndef MY_MOTOR_H
    #define MY_MOTOR_H
    
    
    #include "stm32f10x.h"
    
    /* 控制电机正反转输出引脚*/
    #define Motor1_Dir_Gpio_Clk     RCC_APB2Periph_GPIOC
    #define Motor1_Dir_Gpio_Pork    GPIOC
    #define Motor1_Dir_Gpio_Pin     GPIO_Pin_1
    
    #define Motor2_Dir_Gpio_Clk     RCC_APB2Periph_GPIOC
    #define Motor2_Dir_Gpio_Pork    GPIOC
    #define Motor2_Dir_Gpio_Pin     GPIO_Pin_2
    
    #define Motor3_Dir_Gpio_Clk     RCC_APB2Periph_GPIOC
    #define Motor3_Dir_Gpio_Pork    GPIOC
    #define Motor3_Dir_Gpio_Pin     GPIO_Pin_3
    
    #define Motor4_Dir_Gpio_Clk     RCC_APB2Periph_GPIOC
    #define Motor4_Dir_Gpio_Pork    GPIOC
    #define Motor4_Dir_Gpio_Pin     GPIO_Pin_4
    
    
    
    
    /*PWM波输出引脚*/
    #define Motor1_Pwm_Gpio_Clk     RCC_APB2Periph_GPIOA
    #define Motor1_Pwm_Gpio_Pork    GPIOA
    #define Motor1_Pwm_Gpio_Pin     GPIO_Pin_0
    
    
    #define Motor2_Pwm_Gpio_Clk     RCC_APB2Periph_GPIOA
    #define Motor2_Pwm_Gpio_Pork    GPIOA
    #define Motor2_Pwm_Gpio_Pin     GPIO_Pin_1
    
    
    #define Motor3_Pwm_Gpio_Clk     RCC_APB2Periph_GPIOA
    #define Motor3_Pwm_Gpio_Pork    GPIOA
    #define Motor3_Pwm_Gpio_Pin     GPIO_Pin_2
    
    #define Motor4_Pwm_Gpio_Clk     RCC_APB2Periph_GPIOA
    #define Motor4_Pwm_Gpio_Pork    GPIOA
    #define Motor4_Pwm_Gpio_Pin     GPIO_Pin_3
    
    
    #define ATOM_PWM_MAX 200
    
    
    
    /************通用定时器TIM参数定义,只限TIM2、3、4、5************/
    // 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意
    // 我们这里默认使用TIM3
    
    #define            GENERAL_TIM                   TIM5
    #define            GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
    #define            GENERAL_TIM_CLK               RCC_APB1Periph_TIM5
    #define            GENERAL_TIM_Period             (200-1) 
    #define            GENERAL_TIM_Prescaler         (7200-1)  
     
    
     void Motor_Init(void );
     void MotorCtrl(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4);
    
    #endif /*  MY_MOTOR_H */
    
    
    展开全文
  • 在介绍几种典型电机微控制器8XC196MC、TMS320C240和ADMC311结构的基础上,着重对这些芯片如何实现PWM控制等交流电机控制系统所必需的性能进行了分析比较,以便为交流感应电机(ACIM)、步进电机(SM)等电机控制系统的...
  •  TDA16888是西门子公司生产的一款高性能、高集成度的PFC/PWM二合一单片控制器,其引脚功能见表2:  3.L4981  L4981是意法半导体公司生产的一款有源功率因数校正芯片,采用平均电流型控制方式,可与其他电路...
  • PID算法与直流电机的PWM技术控制

    万次阅读 多人点赞 2020-01-10 13:36:25
    PID控制算法是工业控制领域使用最广泛的算法之一,嵌入式系统是工业领域和生活中最常见的智能系统之一。本文介绍了PID控制算法在嵌入式系统中的直流电机控制的一些最常用、最有效的一些场景。

       PID控制算法是工业控制领域使用最广泛的算法之一,嵌入式系统是工业领域和生活中最常见的智能控制系统之一。本文以单片机控制两个带编码器的直流电机使二者转速保持一致为例讲PID算法与直流电机的PWM技术控制。本文围绕下面几个问题展开:

    什么是PID控制算法?

       PID控制算法即比例、积分、微分控制算法。PID控制分为两种:模拟PID和数字PID,前者处理的是连续信号,后者处理的是离散信号。因为单片机只能处理离散信号,本文主要谈后者。对于后者,又分为两种常用的算法即增量式数字PID和位置式数字PID,其中增量式用的更多,所以本文以增量式数字PID为例。PID控制的数学原理比较复杂,限于作者水平,大家可以点击这里进一步了解其控制原理。另外,根据实际控制需求,PID控制算法不一定三个环节都要用,一般常用的还有PI控制、PD控制。
    在这里插入图片描述

    典型的闭环控制系统结构图

    PID控制结构框图

    PID控制算法的典型的结构图
      PID控制算法的设计过程中最重要的一个环节就是确定三个参数值的大小的确定,即PID参数整定。为了方便叙述,我们直接用上面的链接里的思路,即确定三个系数A、B、C的大小。其中 :

    A = Kp + Ki + Kd,B = Kp + 2 * Kd,C = Kd。 ------- (1)
    Kp,Ki,Kd分别是PID控制器的三个参数。
    注:上图直接从链接中截取
    注:上图直接从链接中截取
       从本人实际的调试经历中,对于电机控制,我一般设置三个参数的大小关系为:Kp>>Kd,Ki,至于具体的数值以及Kp,Ki的相对大小需要根据控制需求和调试过程中输出的情况做一些调整,必要的话,还可能需要做一些算法上的调整,下面分情况详述:

    1. 先定性分析比例、积分、微分三个环节的控制作用:
      比例环节:即时成比例地反应控制系统的偏差信号e(t),偏差一旦产生,控制器立即产生控制作用以减小误差。当偏差e=0时,控制作用也为0。因此,比例控制是基于偏差进行调节的,即有差调节。
      积分环节:能对误差进行记忆,主要用于消除静差,提高系统的无差度,积分作用的强弱取决于积分时间常数Ti,Ti越大,积分作用越弱,反之则越强。值得注意的是,积分作用不宜设置过强,否则控制器输出振荡,会出现两个电机一个转另一个不转或转的慢并轮流交替循环这种极端现象,如果这两个电机是某个小车的两个转向轮,那么小车将会一直走“S”曲线。
      微分环节:能反映偏差信号的变化趋势(变化速率),并能在偏差信号值变得太大之前,在系统中引入一个有效的早期修正信号,从而加快系统的动作速度,减小调节时间。微分系数同样不能太大,否则会降低系统的稳定性。按照上面举的小车的例子,微分作用过大表现在处于稳定状态(即小车保持直线行驶)的小车受到一点点扰动就需要花很长的时间调整回来甚至再也调整不回来了。
         从时间的角度讲,比例作用是针对系统当前误差进行控制,积分作用则针对系统误差的历史,而微分作用则反映了系统误差的变化趋势,这三者的组合是“过去、现在、未来”的完美结合。
    2. 根据上面的定性分析,可以把两个电机的转速差(有正负之分)以一定的频率记录下来并绘制响应曲线(即输出-时间曲线),这个过程可以在上位机上完成,只需要打开单片机的串口,把输出的数据发给上位机即可。然后根据响应曲线调节,三个环节的调节顺序是:先调Kp是输出曲线表现为等幅振荡或近似等幅振荡,然后加上Ki,使输出曲线收敛,最后加上Kd,使响应曲线完全达到控制要求(一般响应快、稳定时无误差、超调小为宜)。
    3. 讲一些特殊情况下的控制算法调整。
      1)控制器的输出溢出,这种情况可能控制作用过强导致,这时要按Ki,Kd,Kp的顺序一个一个地适当减小三个系数,极端情况下可使Ki=0,Kd=0,Kp很小,然后 再看输出曲线。
      2)输出一直在振荡,怎么调控制参数都没用,这时要考虑硬件的问题,或者其他软件问题。
      3)除了上面两种常见的情况,也可以事先了解一下常用的PID控制器的改进方法,比如:死区控制法、遇限削弱积分法、积分分离法、有效偏差法、微分先行法等。再复杂的情况,比如大滞后,可以用串级PID控制算法,对于某一种强扰动也可加上前馈控制算法等。
    直流编码电机的控制与转速的检测

    先上图看一下它长什么样子:
    带编码器的直流减速电机

    带编码器的直流减速电机

       编码器:所谓编码,就是它可以把电机的角位移或者角速度信号转换为电脉冲信号,通过对脉冲信号的检测可以确定电机的转速。在上面的结构图中,编码器就是传感器,它将电机转速经测量变速传给单片机。
    编码器的驱动:我们用stm32f10xxx系列的单片机作为主控芯片,stm32单片机的定时器外设资源丰富,并且它的通用定时器本身就带有控制编码电机的工作模式,简直就是“量身定做”!
       直流电机的控制:直流电机的转速控制用PWM技术实现,调节PWM的占空比可以线性地改变电机两端的电压,从而控制电机的转速,控制结构图如下:
    在这里插入图片描述

    直流电机的控制流程
       上面的电机驱动本质是一个功率放大器,将单片机产生的、一定占空比的PWM矩形波转为一定电压电流的模拟信号,进而驱动电机。
    程序实现的问题

    程序流程如下:
    程序流程
    下面挑重要的几步讲一下,然后总的源代码程序工程会以压缩包的形式共享出来。

    1. 初始化
       初始化这一步主要完成一些全局变量、外设的赋值和配置工作。具体是:PID控制相关参数的初始化,定时器、串口等其他辅助性的外设的配置:

    	delay_init(); //延时函数初始化
    	TIM5_PWM_Init(1000,9); //PWM初始化 8KHz	
    	TIM3_ENC_Init();  //编码器初始化
    	TIM4_ENC_Init();  //编码器初始化
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级配置
    	pid_init();
    	uart_init(115200); //初始化串口,波特率设置为115200
    

    2. PID参数设置

    	do //下面的循环语句是为了调节PID参数,串口接收到'0',跳出循环
    	{
    			switch(go) //注意大小写
    			{
    				case 'P': mts.Kp += val; go = 0; break;
    				case 'I': mts.Ki += val; go = 0; break;
    				case 'D': mts.Kd += val; go = 0; break;
    				case 'p': mts.Kp -= val; go = 0; break;
    				case 'i': mts.Ki -= val; go = 0; break;
    				case 'd': mts.Kd -= val; go = 0; break;
    				default: break;
    			}
    			delay_ms(10);
    	}while(go != '0');
    

       这一步是为了后面程序复位后方便调整PID参数,即便于PID参数整定。
    3. 循环体

    	while(1)
    	{
    			detPID_PWM_out();//调用PID函数,计算控制增量
    			if(sendFlag) //每刷新一次控制输出,往上位机发一次数据
    			{
    					send_intData(mts.detPWM_out); 
    					sendFlag = 0;
    			}
    			TIM_SetCompare1(TIM5,BASE_SPEED - mts.detPWM_out);	//注意电机的正反转,这里的4个通道可以控制两个电机正反转
    			TIM_SetCompare2(TIM5,BASE_SPEED + mts.detPWM_out);		
    			TIM_SetCompare3(TIM5,0); //通道3、4为0,此时假设两个电机刚好往同一个方向转,如果转向不一致,请对调硬件或再修改代码,这里只举例说明
    			TIM_SetCompare4(TIM5,0);
    	}
    }
    

       循环体里面计算控制输出,并根据控制输出调整PWM矩形波的占空比。
    4. 中断

    /*下面是中断服务函数,定时器中断的优先级高于串口中断*/
    
    void USART1_IRQHandler(void)                	//串口1中断服务程序
    	{
    		
    		if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d(回车) 0x0a(换行)结尾)
    			{
    				if(sendFlag%2)
    				{
    						val = USART_ReceiveData(USART1);	//读取接收到的数据
    				}
    				else
    				{
    						go = USART_ReceiveData(USART1);	//读取接收到的数据		
    				}
    				sendFlag = ++sendFlag >= 255?1:sendFlag;						 
    			} 
    } 
    	
    void TIM6_IRQHandler(void)   //TIM6中断
    {
    	if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
    		{
    			TIM_ClearITPendingBit(TIM6, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
    //			(u_16) = TIM_GetCounter(TIM4);
    //			(U_16) = TIM_GetCounter(TIM3);
    			mts.Ek_2 = mts.Ek_1;
    			mts.Ek_1 = mts.Ek;
    			mts.Ek = TIM_GetCounter(TIM3) - TIM_GetCounter(TIM4); //计算偏差
    			sendFlag = 1;
    		}
    			
    }
    

       程序中只用了两个中断,一个是串口接收中断,用于接收上位机的命令和数据,以便调试或者监控程序里面一些变量的变化;另一个是定时器中断,为了以50Hz的频率采集编码器反馈的速度信号,同时计算偏差。

    总结

       本文只介绍了最简单的PID控制算法C语言实现,上面提到的那几种常用的PID改进算法每一个都可以单独拿出来讲一下如何实现,但限于篇幅且本文重点不是这个所以大家感兴趣的话可以先查查相关的文章,后面有机会我会再单独讲一下我个人对这些算法的理解和实际应用中的实现。本文的基于uKeil的C源码工程共享在公众号“24K纯学渣”上面,回复“PID电机控制”即可获取。另外,限于作者水平,如有描述错误或不妥之处,欢迎大家在下面评论指出。如果希望进一步的交流学习,可以在公众号上联系作者,任何学习上的交流本人都非常欢迎!

    展开全文
  • PWM控制直流电机(单片机实验)

    万次阅读 多人点赞 2020-07-21 14:48:26
    PWM控制直流电机(单片机实验) 有问题欢迎私信哦 一.题目 设计电路,使用定时器实现PWM对直流电机的转速控制,并且实现按键切换转动方向。并进行软件仿真,做出实物。 二.基本要求 1.设置按键控制直流电机的开关 2....

    PWM控制直流电机(单片机实验)

    有问题欢迎私信哦

    一.题目
    设计电路,使用定时器实现PWM对直流电机的转速控制,并且实现按键切换转动方向。并进行软件仿真,做出实物。
    二.基本要求
    1.设置按键控制直流电机的开关
    2.设置按键控制直流电机的加速、减速。
    3.设置按键控制直流电机的正反转。
    4.设置显示模块可以直观的了解到直流电机的工作状态。
    5.使用PROTUES软件进行电路设计并仿真。
    6.按照仿真设计实物。

    目录

    1. 项目分析 6
      1.1 设计思路 6
      1.2 系统框架构建 6
    2. 硬件设计 7
      2.1 硬件模块组成 7
      2.2 单片机控制模块 7
      2.2.1 单片机控制模块简介 7
      2.2.2 AT89C52简介 7
      2.2.3 AT89C52主要功能列举 7
      2.2.4 AT89C52引脚功能介绍 7
      2.3 电机驱动模块 8
      2.3.1 L298电机驱动简介 8
      2.3.2 L298N原理图 8
      2.3.3 L298N的逻辑功能 9
      2.4 数码管显示模块 9
      2.4.1 LED数码管简介 9
      2.4.2 LED七段数码管的结构 9
      2.5 键盘控制模块 10
      2.5.1 键盘控制模块介绍 10
      2.5.2 独立按键介绍 10
      2.5.3 独立按键与单片机的链接 10
    3. 软件设计 11
      3.1 代码设计 11
      3.2 仿真实现 14
    4. 系统调试总结分析 14

    1. 项目分析

    1.1 设计思路
    PWM控制直流电机的主要功能要求有:能够实现对直流电机的加速、减速、正反转和暂停,能够直观的了解到直流电机的工作状态,且可以很方便的实现对直流电机的智能控制。

    为此我们设计了以下几个部分来构成我们的直流电机PWM控制系统:
    主体电路:即直流电机PWM控制模块。这部分电路主要由AT89C52单片机的I/O端口、定时计数器、外部中断扩展等控制直流电机的加速、减速以及电机的正转和反转,能够很方便的实现电机的智能控制。其间是通过AT89C52单片机产生脉宽可调的脉冲信号并输入到L298N驱动芯片来控制直流电机工作的。
    该直流电机PWM控制系统由以下电路模块组成:
    设计输入部分:这一模块主要是利用带中断的独立式键盘来实现对直流电机的加速、减速以及电机的正反转和暂停控制。
    设计控制部分:主要由AT89C52单片机的外部中断扩展电路组成。直流电机PWM控制实现部分主要由一些二极管、电机和L298N直流电机驱动模块组成。
    设计显示部分:LED数码显示部分,实现对PWM脉宽调制占空比的实时显示。
    1.2 系统框架构建
    方案说明:直流电机PWM调速系统以AT89C52单片机为控制核心,由命令输入模块、LED显示模块及电机驱动模块组成。采用带中断的独立式键盘作为命令的输入,单片机在程序控制下,定时不断给L298直流电机驱动芯片发送PWM波形,H型驱动电路完成电机正,反转和急停控制;同时单片机不停的将PWM脉宽调制占空比送到LED数码管完成实时显示。如图1-2-1为预设框架图。
    在这里插入图片描述
    2. 硬件设计

    2.1 硬件模块组成
    (1) 单片机控制模块
    (2) 电机驱动模块
    (3) 数码管显示模块
    (4) 键盘控制模块

    2.2 单片机控制模块

    2.2.1 单片机控制模块简介
    在该模块,经过我们讨论比较之后我们选择了AT89C52构成我们的单片机控制模块。

    2.2.2 AT89C52简介
    AT89C52是一个低电压,高性能CMOS 8位单片机,片内含8k bytes的可反复擦写的Flash只读程序存储器和256 bytes的随机存取数据存储器,器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,AT89C52单片机在电子行业中有着广泛的应用。

    2.2.3 AT89C52主要功能列举
    (1) 拥有灵巧的8位CPU和在系统可编程Flash
    (2) 晶片内部具时钟振荡器(传统最高工作频率可至 12MHz)
    (3) 内部程序存储器(ROM)为 8KB
    (4) 内部数据存储器(RAM)为 256字节
    (5) 32 个可编程I/O 口线
    (6) 8 个中断向量源
    (7) 三个 16 位定时器/计数器
    (8) 三级加密程序存储器
    (9) 全双工UART串行通道

    2.2.4 AT89C52引脚功能介绍

    VCC:AT89S52电源正端输入,接+5V。
    VSS:电源地端。
    XTAL1:单芯片系统时钟的反相放大器输入端。
    XTAL2:系统时钟的反相放大器输出端,一般在设计上只要在 XTAL1 和 XTAL2 上接上一只石英振荡晶体系统就可以动作了,此外可以在两引脚与地之间加入一 20PF 的小电容,可以使系统更稳定,避免噪声干扰而死机。
    RESET:AT89C52的重置引脚,高电平动作,当要对晶片重置时,只要对此引脚电平提升至高电平并保持两个机器周期以上的时间,AT89C52便能完成系统重置的各项动作,使得内部特殊功能寄存器之内容均被设成已知状态,并且至地址0000H处开始读入程序代码而执行程序。
    EA/Vpp:"EA"为英文"External Access"的缩写,表示存取外部程序代码之意,低电平动作,也就是说当此引脚接低电平后,系统会取用外部的程序代码(存于外部EPROM中)来执行程序。因此在8031及8032中,EA引脚必须接低电平,因为其内部无程序存储器空间。如果是使用 8751 内部程序空间时,此引脚要接成高电平。此外,在将程序代码烧录至8751内部EPROM时,可以利用此引脚来输入21V的烧录高压(Vpp)。
    ALE/PROG:ALE是英文"Address Latch Enable"的缩写,表示地址锁存器启用信号。AT89C52可以利用这支引脚来触发外部的8位锁存器(如74LS373),将端口0的地址总线(A0~A7)锁进锁存器中,因为AT89C52是以多工的方式送出地址及数据。平时在程序执行时ALE引脚的输出频率约是系统工作频率的1/6,因此可以用来驱动其他周边晶片的时基输入。此外在烧录8751程序代码时,此引脚会被当成程序规划的特殊功能来使用。
    PSEN:此为"Program Store Enable"的缩写,其意为程序储存启用,当8051被设成为读取外部程序代码工作模式时(EA=0),会送出此信号以便取得程序代码,通常这支脚是接到EPROM的OE脚。AT89C52可以利用PSEN及RD引脚分别启用存在外部的RAM与EPROM,使得数据存储器与程序存储器可以合并在一起而共用64K的定址范围。
    PORT0(P0.0~P0.7):端口0是一个8位宽的开路汲极(Open Drain)双向输出入端口,共有8个位,P0.0表示位0,P0.1表示位1,依此类推。其他三个I/O端口(P1、P2、P3)则不具有此电路组态,而是内部有一提升电路,P0在当做I/O用时可以推动8个LS的TTL负载。如果当EA引脚为低电平时(即取用外部程序代码或数据存储器),P0就以多工方式提供地址总线(A0~A7)及数据总线(D0~D7)。设计者必须外加一锁存器将端口0送出的地址栓锁住成为A0~A7,再配合端口2所送出的A8~A15合成一完整的16位地址总线,而定址到64K的外部存储器空间。
    PORT2(P2.0~P2.7):端口2是具有内部提升电路的双向I/O端口,每一个引脚可以推动4个LS的TTL负载,若将端口2的输出设为高电平时,此端口便能当成输入端口来使用。P2除了当做一般I/O端口使用外,若是在AT89C52扩充外接程序存储器或数据存储器时,也提供地址总线的高字节A8~A15,这个时候P2便不能当做I/O来使用了。
    PORT1(P1.0~P1.7):端口1也是具有内部提升电路的双向I/O端口,其输出缓冲器可以推动4个LS TTL负载,同样地若将端口1的输出设为高电平,便是由此端口来输入数据。如果是使用8052或是8032的话,P1.0又当做定时器2的外部脉冲输入脚,而P1.1可以有T2EX功能,可以做外部中断输入的触发脚位。
    PORT3(P3.0~P3.7):端口3也具有内部提升电路的双向I/O端口,其输出缓冲器可以推动4个TTL负载,同时还多工具有其他的额外特殊功能,包括串行通信、外部中断控制、计时计数控制及外部数据存储器内容的读取或写入控制等功能。
    其引脚分配如下:
    P3.0:RXD,串行通信输入。
    P3.1:TXD,串行通信输出。
    P3.2:INT0,外部中断0输入。
    P3.3:INT1,外部中断1输入。
    P3.4:T0,计时计数器0输入。
    P3.5:T1,计时计数器1输入。
    P3.6:WR:外部数据存储器的写入信号。
    P3.7:RD,外部数据存储器的读取信号。
    RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
    ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。
    /PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
    /EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
    XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。
    XTAL2:来自反向振荡器的输出。

    2.3 电机驱动模块

    2.3.1 L298电机驱动简介
    L298是SGS公司的产品,L298N为15个管角的单块集成电路,高电压,高电流,四通道驱动,设计用L298N来接收DTL或者TTL逻辑电平,驱动感性负载(比如继电器,直流和步进马达)和开关电源晶体管。内部包含4通道逻辑驱动电路,其额定工作电流为 1 A,最大可达 1.5 A,Vss 电压最小 4.5 V,最大可达 36 V;Vs 电压最大值也是 36 V。L298N可直接对电机进行控制,无须隔离电路,可以驱动双电机。

    2.3.2 L298N原理图
    L298原理图如图2-3-1所示
    在这里插入图片描述
    图2-3-1 L298原理图

    2.3.3 L298N的逻辑功能
    当使能端为高电平时,输入端IN1为PWM信号,IN2为低电平信号时,电机正转;输入端IN1为低电平信号,IN2为PWM信号时,电机反转;IN1与IN2相同时,电机快速停止。当使能端为低电平时,电动机停止转动。
    在对直流电动机电压的控制和驱动中,半导体功率器件(L298)在使用上可以分为两种方式:线性放大驱动方式和开关驱动方式在线性放大驱动方式。
    半导体功率器件工作在线性区优点是控制原理简单,输出波动小,线性好,对邻近电路干扰小,缺点为功率器件工作在线性区,功率低和散热问题严重。开关驱动方式是使半导体功率器件工作在开关状态,通过脉调制(PWM)来控制电动机的电压,从而实现电动机转速的控制。如表2-3-1所示。

    2.4 数码管显示模块
    2.4.1 LED数码管简介
    LED(Light Emitting Diode),发光二极管,是一种固态的半导体器件,它可以直接把电转化为光。LED的心脏是一个半导体的晶片,晶片的一端附在一个支架上,一端是负极,另一端连接电源的正极,使整个晶片被环氧树脂封装起来。半导体晶片由两部分组成,一部分是P型半导体,在它里面空穴占主导地位,另一端是N型半导体,在这边主要是电子。但这两种半导体连接起来的时候,它们之间就形成一个“P-N结”。
    当电流通过导线作用于这个晶片的时候,电子就会被推向P区,在P区里电子跟空穴复合,然后就会以光子的形式发出能量,这就是LED发光的原理。而光的波长也就是光的颜色,是由形成P-N结的材料决定的。除半导体激光器外,当电流激励时能发射光学辐射的半导体二极管。严格地讲,术语LED应该仅应用于发射可见光的二极管;发射近红外辐射的二极管叫红外发光二极管(IRED,Infrared Emitting Diode);发射峰值波长在可见光短波限附近,由部份紫外辐射的二极管称为紫外发光二极管;但是习惯上把上述三种半导体二极管统称为发光二极管。
    2.4.2 LED七段数码管的结构
    LED七段数码管,如图2-4-2所示,是由多个发光二极管封装在一起组成“8”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。LED数码管常用的段数一般为7段,有的另加一个小数点 。LED数码管根据LED的接法不同,分为共阴和共阳两类 。
    共阴极结构,是8段发光二极管的阴极端连接在一起,阳极端分开控制,使用时公共端接地,要使哪根发光二极管,则对应的阳极端接高电平。共阳极结构,是8段发光二极管的阳极端连接在一起,阴极端分开控制,使用时公共端接电源。要使哪根发光二极管,则对应的阴极端接地。
    在这里插入图片描述
    图2-4-2 LED数码管结构图
    其中7段发光二极管构成7笔的字形“8”,1根发光二极管构成小数点。从a-g引脚输入不同的8位二进制编码,可显示不同的数字或字符。通常把控制发光二极管的7(或8)位二极管编制称为字段码。不同数字或字符其字段码不一样,对于同一个数字或字符,共阴极连接和共阳极连接的字段码也不一样,共阴极和共阳极的字段码互为反码。

    2.5 键盘控制模块

    2.5.1 键盘控制模块介绍
    键盘控制模块主要是用于操作设备运行的一种指令和数据输入装置。
    键盘按照接口原理可分为编码键盘与非编码键盘两类。这两类键盘的主要区别是识别键符及给出相应键码的方法。编码键盘主要是用硬件来实现对键的识别;非编码键盘主要是由软件来实现键盘的定义与识别。键盘按照其结构可分为独立式键盘与矩阵式键盘两类。独立式键盘主要用于按键较少的场合,矩阵式键盘主要用于按键较多的场合,也称行列式键盘。综合需求比较我们选择了独立式键盘用于我们的键盘控制模块。

    2.5.2 独立按键介绍
    独立按键主要是指轻触式按键开关,也称之为轻触开关。独立按键是一种电子开关,属于电子元器件类,使用时以满足操作力的条件向开关操作方向施压开关功能闭合接通,当撤销压力时开关即断开,其内部结构是靠金属弹片受力变化来实现通断的。
    独立键盘的按键相互独立,每个按键接一根I/O口线,一根I/O口线上的按键工作状态不会影响其它I/O口线的工作状态(引脚图如图2-5-1所示)。因此,通过检测I/O口线的电平状态,即可判断键盘上哪个键被按下。
    在这里插入图片描述
    图2-5-1 独立按键引脚图
    2.5.3 独立按键与单片机的链接
    如图2-5-2所示为单片机和独立按键链接的示意图
    在这里插入图片描述
    图2-5-2 独立键盘与单片机的链接
    3. 软件设计

    3.1 代码设计

    #include<reg52.h> 
    #define uchar unsigned char	
    #define uint unsigned int 
    #define value P0
    #define wei P2
    uchar sdkey;
    uchar zfkey;
    uchar zkgkey;	
    sbit motor_A_1=P3^5;
    sbit motor_A_2=P3^6;
    sbit zkg=P3^7;
    sbit k1=P1^0;  	// k1加速按键
    sbit k2=P1^1;   // K2减速按键
    sbit k3=P1^2;   // K3方向取反
    sbit k4=P1^3;   // k4电机开关
    uchar T=0;	     
    uchar W=0;	   
    uchar k=0;	    
    uint i=0;      
    uint l=0;
    uchar code smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x00};
    uchar code smgwei[]={0x01,0x02,0x04,0x08};
    void time0Init(void)
    {
    	TH0=0xff;
    	TL0=0xf6;			
    	TMOD=0x01;	
    	EA=1;						
    	ET0=1;
    	TR0=1;
    }
    void Delay(uint m)
    {
    	while(m--);	
    }
    void displaysmg(uint a,uint b)
    {
    	wei=~smgwei[a];
    	value=smgduan[b];
    	Delay(100);
    }
    void display()
    {
    	if(W>0)
    	{
      displaysmg(0,W/20);		
    	}
     if(zkg==1)
    	{
    		displaysmg(3,1);	
    	}	
    	else 
    	{
    		wei=0xff;
    	}
    	if(zfkey==1)
    				{
    						displaysmg(2,1);	
    				}
    				else
    				{
    				 displaysmg(2,6);			
    				}
    
    }
    void timer0() interrupt 1
    {		  		   
    	TH0=0xff;
    	TL0=0xf6;
    	T++;	 				
    	if(T==100)      
    	T=0; 
    	if(k==0)
    	 {
    		 
    		if(T>W)
    			motor_A_1 =0;
    		else
    			motor_A_1 =1;
         }
    	else
    	 {
    		if(T>W)
    			motor_A_2 =0;
    		else
    			motor_A_2 =1;
    	 }
    }	 
    void key(void)           
    {
    	if(k1==0)								 //加速
    	{	
    		Delay(100);						
    		{
    			while(k1==0);
    			if(W==100)
    			W=0;				
    			else
    				W+=20;	
    		}
    	}
    	else if(k2==0)					    //减速
    	{	
    		Delay(100);					    
    		{				 
    			while(k2==0);			   	
    			if(W==0)				    
    				W=100;				
    			else
    				W-=20;
    		}
    	}
    	else if(k3==0)					    //转向
    	{
    		Delay(100);									
    		{	
    			if(k3==0)
    			{		   
    			while(!k3);
    			k=!k;	
    			zfkey=~zfkey;
    			}
    		} 
    	}
    	else if(k4==0)						//总开关
    	{	
    		Delay(100);			            	
    		{	
    		  if(k4==0)
    			{	
    				zkg=~zkg;
    				zkgkey=~zkgkey;
    			}
    			while(!k4);
    			W=0;													
    		}
    	}
    }
    void main(void)
    {
    	zkg=0;
       zfkey=1;
    	   time0Init();			              		 
    	while(1)	 
    	   {
    	      if(k==0)
    	      motor_A_2=0;
    	      else
    	      motor_A_1=0;	 		
    key();						
    	   display();
    	}
    }
    

    3.2 仿真实现

    图3-2-1 电机顺时针-关闭状态仿真图
    图3-2-2 电机顺时针-开启状态仿真图
    图3-2-3 电机逆时针-关闭状态仿真图
    图3-2-3 电机顺时针-5档状态仿真图
    图3-2-4 电机逆时针-2档状态仿真图
    在这里插入图片描述
    图3-2-5 电机顺时针-2档状态仿真图

    图3-2-6 电机逆时针-2档状态实物图

    4. 系统调试总结分析

    4.1 仿真调试
    通过仿真我们能够直观的看到实验现象。其中数码管左边第一位为档位显示,右边第二位为顺时针/逆时针状态显示,右边第一位为电机开启/关闭状态显示。K1按键为加速按键,K2按键为减速按键,k3按键为电机转向选择按键,K4为电机的开关按键。
    1、加速按键K1
    按下加速按键K1的时候,数码管的档位显示会更改并显示当前档位,每次按下K1会将档位从当前显示数字加1。档位共分为6档,0~5,从1档到5档使得电机不断加速,5档时电机处于最高速度。0档时数码管并不显示任何,此时电机停止转动并且当目前为5档时,如果再次按下K1,电机速度会置0(数码管档位不显示),如再次按下K1,又会重新加1。同时电机会根据数码管显示的档位相应的转速转动。
    2、减速按键k2
    按下减速按键K2的时候,数码管的档位显示会更改并显示当前档位,每次按下k2的时候与加速相反,减速按键每次会让数码管显示数字减1,从5档到0档,数码管随着每次K2的按下都会随之减1,当数码管从5减到0,显示的数字不断减小,标示着电机转速不断下降。当前档位为0时,数码管不显示任何并且电机停止转动,如果当前档位为0,按下K2时,数码管会显示5,即为最高档位,同时电机也会位于最高速度。之后每次按下K2,又会重新减1。同时电机会根据数码管显示的档位相应的转速转动。
    3、方向按键K3
    方向按键K3按下的时候,数码管的右边第二位会显示1或者不显示,其中1表示电机转向为顺时针方向,数码管不显示表示电机逆时针转动。电机的转向不受电机开关K4的影响。电机转向可通过数码管显示1或者不显示直观的看到。
    4、电机开关按键K4
    电机默认状态为关机状态,此时数码管不显示。在这个状态下,可以人为的去选择电机的转向。同时也可以去调节电机的转速。但是当K4按下,数码管显示1,此时电机为开启状态,此时处于安全考虑档位会自动置0,即电机开启后,如不手动去调节档位,电机也不会工作。电机转向的选择并不受电机是否开启的影响。

    4.2 实物测试
    通过自己动手,我们完成了实验所需仪器的组装。整个装置由最小系统、数码管,4个独立按键以及L298N和直流电机组成。根据各个元器件的原理图以及仿真图,组装完成好实物之后。由直流电源提供12V的直流电给L298N模块供电,再通过L298N的模块给整个系统提供5V的供电用以完成实验。最后我们得到的实验结果和预期一致,可以通过按键用来控制电机的转速调节和电机的转向控制并通过数码管显示相关的信息。

    展开全文
  • STM32通过PWM控制ESC30C电调

    千次阅读 2020-07-27 20:54:18
    最近在搞一个水下推进器,这东西的控制其实跟四旋翼的螺旋桨控制差不多。但我也是第一次用STM32板子来控制电调驱动桨叶旋转,因此踩了很多坑。网上找了很多资料,但是很多都写的不是很清楚,这边稍微记录一下怎么...
  • ROS机器人DIY教程之,STM32电机PWM控制

    千次阅读 2020-08-23 14:48:37
    电机调速需要使用到STM32的PWM输出控制电机驱动器从而完成电机调速功能。 1、实现的工具 starrobot底层开发板、12V 5200ma锂电池、GB37-520减速电机、USB数据线、Keil5 starrobot底层开发板板载了A4950电机驱动...
  • 利用单片机PWM信号进行舵机控制

    千次阅读 2019-06-14 13:53:04
    在机器人机电控制系统中,舵机控制效果是性能的...其工作原理是:控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压...
  • 常用芯片大全

    千次阅读 多人点赞 2019-03-29 09:13:29
    AD 系列芯片 1. 模数转换器⋯⋯ AD1380JD 16 位20us 高性能模数转换器( 民用级) AD1380KD 16 位20us 高性能模数转换器( 民用级) AD1671JQ 12 位1.25MHz 采样速率带宽2MHz 模数转换器( 民用级) AD1672AP 12 位3...
  • 4 、Esp8266之 了解PWM,更为深入地用PWM控制一盏LED的亮度变化。 5 、Esp8266之 原生乐鑫SDK高级使用之封装Post与Get请求云端,拿到“天气预报信息”。 6 、Esp8266之 了解 SmartConfig与Airkiss一键配网,给...
  • 推挽电路的应用非常广泛,比如单片机的推挽模式输出,PWM控制器输出,桥式驱动电路等。推挽的英文单词:Push-Pull,顾名思义就是推-拉的意思。所以推挽电路又叫推拉式电路。 推挽电路有很多种,根据用法的不同有所...
  • 1.0电机的分类及永磁同步电机的控制技术介绍 基础的电磁感应产生力的作用,这类似的初中物理知识不再讨论; 与直流无刷及永磁同步电机知识太发散的就不再讨论; 本文介绍的几点内容 电机的分类及日常生活...
  • 常用开关电源芯片大全

    万次阅读 多人点赞 2016-09-27 14:04:59
     116.PWM控制升压式DC-DC电源转换器XC6371   117.白光LED驱动专用DC-DC电源转换器XC9116   118.500mA同步整流降压式DC-DC电源转换器XC9215/XC9216/XC9217   119.稳压输出电荷泵XC9801/XC9802...
  • IC1中含有PWM控制器,功率MOSFET和各种保护电路。这种5V/5W开关电源的成本比常用的线性电源成本低。 该电源交流输入电压范围为85~265V,当负载从额定负载的10%变化到100%,电源电压调整率和负载电流调整率可达...
  • 一、 PWM输出原理 二、STM32 PWM工作过程 三、定时器PWM功能常用函数 四、PWM输出配置步骤
  • DCDC Buck电源芯片选型

    千次阅读 2020-07-22 15:10:20
    只列举常用的,芯片均出自TI,MPS,SY。国产小厂只考虑XL,但并不首推。 个人整理,tb均能买到,如有纰漏欢迎纠错。
  • 如果是我的话,直接用一个常用的单片机(AVR,8051)来控制TLC5940,然后用串口通信,上位机软件也写成串口通信的形式,估计简单不少,而且如果电脑没有串口,可以用串口转USB芯片解决,这样的话可能硬件上面麻烦...
  • PWM实现仪表步进电机的微步细分驱动

    千次阅读 热门讨论 2019-11-10 09:45:16
    目前,国内外常用的几种仪表步进电机电气参数、驱动原理基本相同:MCU发脉冲给驱动芯片,电机会根据脉冲数转动相应的步数。也有将步进电机驱动模块集成在MCU中的,如飞思卡尔的HY64系列。这种应用中,软件编程较为...
  • 基于单片机的直流电机控制与仿真 (PWM)脉冲宽度调制 脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的...
  • 本文以单片机控制两个带编码器的直流电机使二者转速保持一致为例讲PID算法与直流电机的PWM技术控制。本文围绕下面几个问题展开: 什么是PID控制算法?  PID控制算法即比例、积分、微分控制算法。PID控制分为...
  • 常用DC-DC;AC-DC电源芯片

    千次阅读 2017-07-09 18:45:00
    求推荐几个常用的开关电源芯片http://bbs.21ic.com/icview-1245974-1-1.html(出处: 21ic电子技术论坛)   1.1 DC-DC电源转换器  1.低噪声电荷泵DC-DC电源转换器AAT3113/AAT3114   2.低功耗开关型DC-DC电源转换器...
  • 直流电机驱动芯片

    万次阅读 多人点赞 2019-02-17 22:55:34
    由于单片机属于信息类电路,带负载能力极差,不可能直接用来控制电机的运动。因此电机的驱动就显得尤为重要。本文汇总了自己用过的几个电机驱动芯片及其注意事项等等,以后有机会还会继续修正增加等。大家有其他的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,507
精华内容 1,002
关键字:

常用pwm控制芯片