精华内容
下载资源
问答
  • 2021-07-11 01:53:21

    PID控制电机实验报告

    发布时间:2020-04-06

    摘要

    以电机控制平台为对象,利用51单片机和变频器,控制电机精确的定位和正反转运动,克服了常见的因高速而丢步和堵转的现象。电机实现闭环控制的基本方法是将电机工作于启动停止区,通过改变参考脉冲的频率来调节电机的运行速度和电机的闭环控制系统由速度环和位置环构成。通过PID调节实现稳态精度和动态性能较好的闭环系统。

    关键词:变频器PID调节 闭环控制

    一、实验目的和任务

    通过这次课程设计,目的在于掌握如何用DSP控制变频器,再通

    过变频器控制异步电动机实现速度的闭环控制。为实现闭环控制,我们需完成相应的任务:

    1、通过变频器控制电机的五段调速。

    2、通过示波器输出电机速度变化的梯形运行图与s形运行图。

    3、通过单片机实现电机转速的开环控制。

    4、通过单片机实现电机的闭环控制。

    二、实验设备介绍

    装有ccs4.2软件的个人计算机,含有ADC模块的51单片机开发板一套,变频器一个,导线若干条。

    三、硬件电路

    1.变频器的简介

    变频器(Variable-frequency Drive,VFD)是应用变频技术与微电子技术,通过改变电机工作电源频率方式来控制交流电动机的电力控制设备。变频器主要由整流(交流变直流)、滤波、逆变(直流变交流)、制动单元、驱动单元、等组成。变频器靠内部IGBT的开断来调整输出电源的电压和频率,变频器还有很多的保护功能。随着工业自动化程度的不断提高,变频器也得到了非常广泛的应用。

    2.变频器的使用

    变频器事物图 变频器原理图

    PID控制电机实验报告 相关内容:

    工实训钳工有哪些实验报告的呢?下面是小编为大家收集的资料,欢迎阅读,谢谢。工实训钳工实验报告为期二周的钳工实训结束了,在实训期间虽然很累,但我们很快乐,因为我们在学到了很多很有用的东西的同时还锻炼了自己的动手能力,钳工实...

    实验流程:一、账套管理我在金蝶“账套管理”中建立了一个账套号为002,账套名为湮的帐套,并启用之。之后我在“用户管理”中新建了一个名叫陈熑ㄏ尬管理员的新用户。...

    一、 选课要求实验选课前需确认在教务选课系统中选择该课程。电工学实验实行网上选课,=二、 预习要求课前认真阅读实验教程,复习相关理论知识,学习本节实验预备知识,回答相关问题。...

    化学实验报告的范例【1】化学实验报告格式例一定量分析实验报告格式(以草酸中h2c2o4含量的测定为例)实验题目:草酸中h2c2o4含量的测定实验目的:学习naoh标准溶液的配制、标定及有关仪器的使用;学习碱式滴定管的使用,练习滴定操作。...

    光学中研究光的本性以及光在媒质中传播时各种性质的学科。物理光学过去也称“波动光学”,从光是一种波动出发,能说明光的干涉、衍射和偏振等现象。...

    篇一:电极电位的测量实验报告一. 实验目的1. 理解电极电位的意义及主要影响因素2. 熟悉甘汞参比电极的性能以及工作原理3. 知道电化学工作站与计算机的搭配使用方法二. 实验原理电极和溶液界面双电层的电位称为绝对电极电位,它直接反应...

    (一)实验项目:家兔动脉血压调节(二)实验目的:1、掌握神经体液因素及受体阻断或兴奋药物对家兔心血管活动的影响机制。2、掌握动脉血压作为心血管功能活动的综合指标及其相对恒定的调节原理和重要意义。...

    课程名称:实验名称: 惠斯通电桥学院: 眼视光学院专业班级: 眼视光 151 班学生姓名: 许春芸学号: 6303615024实验地点: 210 座位号: 30 座实验时间: 第8周星期 6 上午10点10开始一、实验目的:1.掌握电桥测电阻的原理和方法。...

    查看更多>>

    更多相关内容
  • 基于stmf103系列单片机控制电机位置,包含增量型和位置型,已经实现功能
  • 本代码是基于STM32F103ZET6和编码器直流电机编写的,模糊自整定增量式PID控制电机转动速度的程序。并且是基于正点原子代码格式编写的,相对于普通增量式PID来说控制效果更好,是很好的算法优化。对于初学者有重要的...
  • 本代码是基于STM32F103ZET6和编码器直流电机编写的,模糊自整定位置PID控制电机转动速度的程序。并且是基于正点原子代码格式编写的,相对于普通位置式PID来说控制效果更好,是很好的算法优化。对于初学者有重要的...
  • 励磁系统是同步发电的重要组成部分,也是一个典型的反馈控制系统,单纯按端电压偏差进行的PID控制其阻尼特性较差,易产生低频振荡。本设计引入辅助控制环节—电力系统稳定器(PSS)增加正阻尼转矩,通过建立基于...
  • 该程序可以用来根据超声波测距而利用PID控制算法调节电机的转速
  • 本程序基于STM32 F103RCT6,使用TB6612FNG驱动模块来实现对电机的速度控制,使用了3个定时器分别执行3种功能。具体内容请见代码注释。 本资源中各个参数都很大的原因是因为我的ARR值达到了7200,同时存在启动时直接...
  • PID控制电机知识概述

    千次阅读 多人点赞 2020-08-10 13:07:44
    我们所要控制的是带有编码器的电机,编码器的工作原理下文会讲到,这里将他理解为可以读出当前电机速的一个模块就好。 接下来我们对上图电机的接线简单的说明一下:由上至下依次标号1 ~ 6 1,6号线:电机电源输入。 ...

    ​在很多学科竞赛中,我们时常会使用到电机。那么本篇文章我们就来说说如何基于STM32F4xx来驱动电机。
    首先本篇文章的内容主要有以下几点:

    一.我们需要控制什么样的电机。
    二.控制这个电机所需要学习的知识。
    三.如何对电机的速度进行控制。

    一. 我们需要控制什么样的电机

    在这里插入图片描述
    我们所要控制的是带有编码器的电机,编码器的工作原理下文会讲到,这里将他理解为可以读出当前电机速的一个模块就好。

    接下来我们对上图电机的接线简单的说明一下:由上至下依次标号1 ~ 6
    1,6号线:电机电源输入。

    2,5号线:电机编码器供电。

    3,4号线双向编码器读值线路。

    二、控制这个电机所需要学习的知识。

    1.初始化相关GPIO口。

    示例:

     GPIO_InitTypeDef  GPIO_InitStructure;
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   //使能PB,PE端口时钟
    ​
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;         //LED0-->PB.5 端口配置
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //IO口速度为50MHz
     GPIO_Init(GPIOB, &GPIO_InitStructure);           //根据设定参数初始化GPIOB.5
     GPIO_SetBits(GPIOB,GPIO_Pin_5);             //PB.5 输出高电平
    

    初始化GPIO口几点注意事项:

    1.开启时钟的总线需要准确。(查找总线翻阅参考手册即可)

    2.配置的输出模式需要根据使用的用途进行调整。

    ​2. TIM定时器使用。

    TIM定时器使用之定时器:顾名思义就是将TIM定时器作为定时器然后使其产生中断,然后我们对中断服务函数进行操作。
    这部分最重要的就是了解定时器定时时间的计算:

    例:寄存器配置如下:

    	TIM_TimeBaseInitStruct.TIM_Period        = (10000 - 1);   //重装载值
        TIM_TimeBaseInitStruct.TIM_Prescaler     = (7200 - 1);    //预分频系数
    

    在默认时钟为72M时计算如下:
    预分频系数为7199,那么定时器时钟频率为72M / 7200 = 10kHz

    周期为0.1ms,定时器计数达到重装值时候,产生定时器中断

    则定时器中断时间为10000 * 0.1ms = 1s

    TIM定时器使用之PWM输出:即使用TIM的PWM模式使对应IO口输出PWM方波。部分配置主要代码:

    
      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1      设置为模式一即小于CCRX为有效
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
      TIM_OCInitStructure.TIM_Pulse =250;        //CCRx
      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出的有效极性  低
      TIM_OC3Init(TIM8, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM8 通道3
     
      TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable);  //使能TIM8在CCR1上的预装载寄存器
      TIM_ARRPreloadConfig(TIM8,ENABLE);//ARPE使能 //这个周期生效或下个周起生效
      TIM_Cmd(TIM8, ENABLE);  //使能TIM8
      
      TIM_CtrlPWMOutputs(TIM8, ENABLE);     //高级定时器需要这句才能输出PWM
    

    TIM定时器使用之编码器读值:即使用定时器的编码器模式,对电机速度进行读值。部分配置主要代码:

    // 定时器编码器模式初始化
      //配置时基单元
      TIM_DeInit(TIM3);                //复位TIM3相关寄存器
      TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);      //初始化
      TIM_TimeBaseStructure.TIM_Prescaler = 0;            //分频值
      TIM_TimeBaseStructure.TIM_Period = 65535;            //自动重装载
      TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;      //
      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down; // 这里可以自己设置,或使用默认值
      TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
      //此处:TIM_ICPolarity_Rising 意思是不反相
      TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising); // 这里配置了编码器模式
      //配置编码器
      TIM_ICStructInit(&TIM_ICInitStructure);  //该结构中按缺省值(默认)填入
      TIM_ICInitStructure.TIM_Channel=TIM_Channel_1 |TIM_Channel_2;    //通道
      TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
      TIM_ICInitStructure.TIM_ICSelection =TIM_ICSelection_DirectTI;  //设置
      TIM_ICInitStructure.TIM_ICFilter = 0;  //配置滤波器值
      TIM_ICInit(TIM3, &TIM_ICInitStructure);  //设置通道
      TIM_SetCounter(TIM3, 0);
      TIM_Cmd(TIM3, ENABLE);            //定时器总开关
    

    这里使用的是TIM3定时器的通道1和2。

    3.PID算法相关知识:

    这部分学习可参考:https://www.bilibili.com/video/BV1Ds411t7x4?from=search&seid=17723158423363342532

    三.如何对电机的速度进行控制

    学习完上面这部分,我们对于控制电机所需要用到的部分已经清楚了。

    接下来我们在只要将上面的配置结合起来就能做到对电机的控制。

    结合思路如下:

    1. 初始化GPIO口。
    2. 设定一个定时器为编码器模式,并初始化它。
    3. 设置一个定时器,负责每隔一段时间将编码器的计数值读出来。
    4. 设置PWM输出,相关寄存器配置。
    5. 结合编码器读出的数值编写PID算法。
    6. 根据PID算法所返回的值,改变PWM占空比。
    展开全文
  • PID控制电动机

    2015-08-13 22:37:40
    PID 51 单片机 电动机,适用刚接触PID算法/单片机的驱动电动机的学生,同事,努力吧很简单入门。一定学会的,都是网上分享的
  • pid 控制用于带反馈系统的直流电机速度控制
  • PID算法控制电机转速

    2018-11-29 15:08:58
    PID算法控制电机转速 ,STM32开发例程,适合初学者学习,
  • 本文主要为51单片机电机pid控制系统程序,下面一起来学习一下
  • 运用Keil软件基于stm32f103系列嵌入式芯片编写的程序,用于对直流电机进行PID可调控制
  • PID,编码器控制步进电机的 STM32完整代码,利用Timer3产生的80KHz PWM驱动步进电机,使用编码器精准控制步进电机到指定位置。
  • 直流电机是将直流电能转换成机械能或将机械能转换成直流电能的旋转电机。...对直流电动机模型进行仿真分析,并对PID控制的仿真结果进行对比分析,通过仿真结果发现PID控制系统具有良好的静、动态性能和鲁棒性。
  • 本设计采用STC12C5A60S2单片机作为主控芯片实现了PID电机调速控制器。传感器采用欧姆龙的200线编码器。电机驱动模块采用L298N,使用LM2596来对电机供电。设计中的重点是电机转速的获取和基于PID电机控制算法的实现...
  • 本文为51单片机PWM直流电机PID控制转速源程序,一起来学习下
  • 电机PID速度控制,采样时间为200ms
  • PID-增量式PID和位置式PID算法实现和PID库(51单片机+STM32+arduino完成)
  • 带编码器的直流电机PID速度、位置、速度位置闭环控制代码及教程,包含PID速度控制PID位置控制PID速度位置双环控制STM32源代码
  • 基于FPGA直流电机的速度闭环PID控制,采用硬件描述语言实现直流电机速度控制系统的设计,主要完成以下功能:电机加速、电机减速、电机定速及速度检测等功能的实现。
  • PID控制,可以用于电机矢量控制的系统中,改进PID时可以参考
  • pid控制电机C语言版

    2018-08-06 18:11:05
    用C语言实现的,通过PID控制电机,具体详细代码为C语言
  • 本文章将利用最简单的软件和硬件--51单片机和Proteus仿真软件,由简及深地介绍PID控制电机调速的相关技术。 1.认识PWM脉宽调制技术 在介绍PWM脉宽调制技术之前,我们先在proteus上搭建如下模型,观察小灯的亮灭变化...

            本文章将利用最简单的软件和硬件--51单片机和Proteus仿真软件,由简及深地介绍PID控制电机调速的相关技术。

    1.认识PWM脉宽调制技术

          在介绍PWM脉宽调制技术之前,我们先在proteus上搭建如下模型,观察小灯的亮灭变化。

             在这个模型中,我省去了单片机的复位电路和灯的上拉电阻。这不影响我们观察仿真结果,但实际使用时要加上。接着用keil软件,用以下程序生成hex文件,添加到上面的模型中。

    #include<reg51.h>
    
    #define MAX 0x50
    #define MIN 0x00
    #define TIMELINE 11
    #define TRUE 1
    #define FALSE 0
    
    unsigned int TimeCounter;
    int ArrowFlg=0;
    unsigned char upCounter,downCounter;
    
    sbit LED=P2^0;//PWM输出口
    
    
    void T0Deal() interrupt 1 using 0//控制PWM的高低电平,upCount代表高电平的时间单位量,downCount代表低电平时间单位量
    {
    
    	TH0=0xf1;
    	TL0=0xf1;
    	TR0=1;
    	TimeCounter++;
    	if(TimeCounter==TIMELINE)
    	{
    		if((upCounter==MAX)&&(downCounter==MIN))
    		{
    			ArrowFlg=FALSE;
    		}
    		if((upCounter==MIN)&&(downCounter==MAX))
    		{
    			ArrowFlg=TRUE;
    		}
    		if(ArrowFlg==TRUE)
    		{
    			 upCounter++;
    			 downCounter--;
    		}
    		else
    		{
    			 upCounter--;
    			 downCounter++;
    		}
    		TimeCounter=0; 
    	}
    }
    
    void Delay(unsigned int i)//延时函数
    {
    	unsigned int j;
    	while(i--)
    	{
    		for(j=0;j<32;j++);
    	}
    }
    
    void main()
    {
    	upCounter=MIN;
    	downCounter=MAX;
    	TMOD=0x01;
    	TH0=0xF0;
    	TL0=0xf0;
    	EA=1;
    	ET0=1;
    	TR0=1;
    	while(1)
    	{
    		LED=0;
    		Delay(downCounter);//延时产生高电平
    		LED=1;
    		Delay(upCounter);//延时产生低电平
    	}
    }
    

            添加hex文件并运行仿真以后,我们可以发现,灯的亮度变化是从灭慢慢变亮,然后再从亮慢慢熄灭。灯的亮度是在不停变化的。实际上,我们想要使灯的亮度发生变化,本质上是要改变灯的电压,但是在这里,我们是通过PWM来控制灯的亮度的。接下来我们来介绍具体是如何实现的。

            假如我们驱动一种小灯,让它保持最高亮度需要10V。如果想让它保持最高亮度,我们只要在整个PWM周期里都保持10V即可,即让整个PWM周期都是高电平。如下图所示。

           现在,我不想让灯那么亮,我想让它暗一点,使输入其的电压变成2V。理论上我要加更大的电阻才能实现,现在利用PWM技术,我只要让其占空比变成原来的1/5就可以实现。

            上图就是占空比为原来1/5时的样子,它的作用效果和将输入小灯泡的电压调成2V的作用效果是一样的。

           回到上面我给的程序中,我们是通过改变upCount和downCount的值,借助这两个值代入延时函数进而产生PWM脉冲的。我们观察到灯的亮度一直在变化,这是因为upCount和downCount的值一直在改变。upCount就是高电平维持的时间长度,downCount就是低电平维持的时间长度。两个加起来就是一个PWM周期。upCount大一点,灯的亮度就大一点,upCount小一点灯就暗一点。

           实际上,PWM控制灯的亮度和黑白激光打印机打印不同的灰色是一样的。黑白激光打印机只能打出黑色,而我们看到它打出灰色是因为在灰色部分它打出的黑色像素点没那么密集。在这个模型中,灯的亮度没那么亮其本质原因是因为在这一段PWM的占空比没那么大,灯亮的时间比较短而已。

    2.认识直流电机和电机双H桥结构

           直流电机和我们上面所说的LED灯特性上基本上是一样的。比如只要让其两端有电压差,它就会转,就像LED灯两端有电压差就会亮一样。如果给直流电机的电压比较小,那么它的转速也越慢(这是在负载不变的情况下),就像上面所介绍的LED灯在电压不足的情况下变暗一样。唯一不同的是如果改变直流电机的电压差方向,只会改变电机的转动方向,而如果改变LED灯的正负极方向,LED灯会直接烧毁。

           接下来我们介绍电机的双H桥结构,其电路结构如下图所示。

            双H桥结构是指上图中的1、2、3、4号三极管组成的外H桥结构,和5、6、7、8号三极管组成的内H桥结构。其中外H桥的四个三极管作用是放大电流以驱动电机。而内H桥的作用是利用三极管的饱和截止特性作为开关控制电流流经电机的方向进而控制电机的转向,因此在一些场合中会用四个同样具有开关特性的晶体管来代替这四个三极管。我倾向于把这种结构称作内外双H桥结构。

    3.位置式PID与增量式PID

           首先来谈谈为什么控制电机调速要用到PID控制。假设我们想把 电机的转速从此时的V1提到V2,在这过程中,我们不能直接输出一个速度V2的PWM信号,这样电机是无法正常运行的。而是应该缓慢地提高PWM的占空比,进而使电机的速度缓慢地提升上去。在这过程中就会出现一个问题,就是电机的速度不可能马上很好的停留在V2,而是会在V2附近波动震荡一段时间。如果我们能调试好合适的PID参数,就会使这个过程变得更短,震荡次数越少,震荡幅度越小,电机运行更平稳。

    位置式PID

           首先我们先给出位置式PID控制的表达式

    式中,e(k)为设定值与当前值的差,即误差;e(i)为从开始到当前时刻误差的累加(在数学里所谓的积分也就是每一时刻值的累加);e(k-1)表示上一时刻的误差。Kp、Ki、Kd就是我们需要根据实际情况调节的比例、积分、微分系数。在程序中如何实现在下面我们给出的PID控制电机转速实例中会有涉及。

            接下来我们通过一个小例子来看看位置式PID存在的一些问题。

            如上图所示,0处是电机所要拉动的一个负载,我们想让电机把这个负载拉倒5处。

            在这个系统中假设使用位置式PID进行电机调速,如果在一开始的时候负载的重量特别大,以至于电机拉不动,那么此时电机会输出力矩但不会输出转数。负载依旧在原位置0处,和我们想要的理想位置5处一直有大小为5的误差,如果这个负载依旧很大,那么在位置式PID的积分环节中,这个误差就会不断累加。

            这个时候我们适当减小负载的重量,使电机可以拉得动。当电机把负载拽到5附近的时候,由于之前的积分环节中积累的误差太多了,电机会一直输出转矩而不会停下来。哪怕电机拉着负载使它的位置超过了5,这时候误差变成了负值,也需要在5附近震荡一段时间才会停下来。在这过程中系统会有极大的超调和震荡。其负载位置与时间的关系大致可如下图所示。

           在上述情况中,系统有很大的超调和震荡显然是不理想的。因此在一些场合中,我们可以在位置式PID控制中把积分环节去掉,使系统性能更好。

    增量式PID

          首先给出增量式PID的核心表达式

    式中,e(k)同样是误差;e(k-1)是上一时刻的误差;e(k-2)表示上上时刻的误差。

            从表达式中我们可以看出,增量式PID仅与此时刻的误差,上一时刻的误差,上上时刻的误差这三个误差有关,输出的△u(k)是这三次误差的增量,顾名思义叫做增量式PID。

    4.PID控制电机调速实例

          首先先展示实例模型电路图。

          在右侧的电机部分,我们可以很清晰地看到内外双H桥结构。左侧的四个按键分别调节比例系数P的大小及转速。通过判断P2.3的电平状态来判断应该正转还是反转。两个与非门的作用分别控制正转和反转时PWM对电机的控制,比如反转时,26、27角分别输出高电平和低电平,由于27角输出的是低电平,不管PWM信号如何变化,下面那个与非门输出的一定是高电平,而上面那个与非门由于是26脚的高电平同PWM信号与非产生结果,因此事实上上面那个与非门输出的信号就是对PWM信号进行取反。P3.4引脚用来读取电机的实时转速。下面通过代码来进一步阐述这个实例。

    #include<reg52.h>
    #include"lcd1602.h"
    
    sfr T2MOD = 0x0c9;
    #define uchar unsigned char
    #define uint unsigned int
    
    sbit Q0 = P2^4;
    sbit Q1 = P2^5;
    sbit Q2 = P2^6;
    sbit Q3 = P2^7;
    
    sbit PWM	 	= P1^7;
    sbit UP		 	= P1^0;
    sbit DOWM	 	= P1^1;
    sbit GORB		= P2^3; //换相
    sbit ADDSPEED 	= P1^2;
    sbit SUBSPEED	= P1^3;
    
    uint tuint = 65535;
    uint tpwm = 1;	//pwm周期为10000us tpwm变量表示pwm高电平时间,也相当于占空比 (仿真时,频率高时,电机反应慢。在实物上要加大频率)
    uchar t1_flag = 0;
    
    uint pulse = 0;
    uint t0_flag = 0;
    uchar t2_flag = 0;
    bit t2_over = 0;
    bit Just_Get = 1;
    
    
    #define 	ZZ 		{ Q0 = 0;Q1 = 0;Q2 = 1;Q3 = 1;}	//正转
    #define 	FZ 		{ Q0 = 1;Q1 = 1;Q2 = 0;Q3 = 0;}	//反转
    #define 	STOP	{ Q0 = 1;Q1 = 0;Q2 = 1;Q3 = 0;}	//停止
    //禁止出现 Q0 = 0;Q1 = 1;Q2 = 0;Q3 = 1; 不然会烧掉mos管
    
    //************************ PID *************************************
    float now = 0,bef = 0,bbef = 0; 	//本次采样值,上次采样值,上上次采样值
    float err_now,err_bef,err_bbef;		//当前偏差,上次偏差,上上次偏差
    float error_add = 0;				//所有偏差之和
    float set = 25;						//设定值
    
    float kp = 25;
    float ki = 25;
    float kd = 0;
    
    //*****************************************************************
    
    void delayms(uint ms)//延时?个 ms
    {
        uchar a,b,c;
    	while(ms--)
    	{ 
    	  for(c=1;c>0;c--)
            for(b=142;b>0;b--)
                for(a=2;a>0;a--);
    	}
    }
    
    void timer_init()
    {
    	EA = 1;
    	ET0 = 1;
    	ET1 = 1;
    	ET2 = 1;
    	
    	TMOD = 0x15; //定时器0 计数模式 定时器1模式1
    	T2MOD = 0x01;
    	
    	TH0 = TL0 = 255;
    	TH2 = 0x3C;
    	TL2 = 0xB0;		//50MS
    	
    }
    void timer1() interrupt 3
    {
    	if(t1_flag == 0)
    	{
    		t1_flag = 1;
    		PWM = 1;
    		TH1 = (tuint - tpwm + 1)/256;
    		TL1 = (tuint - tpwm + 1)%256;
    		
    	}
    	else
    	{
    		t1_flag = 0;
    		PWM = 0;
    		TH1 = (tuint - 10000 + tpwm + 1)/256;
    		TL1 = (tuint - 10000 + tpwm + 1)%256;
    	}
    }
    
    void timer0() interrupt 1
    {
    	TH0 = TL0 = 255;
    	t0_flag++;
    }
    void timer2() interrupt 5
    {
    	TF2 = 0;
    	TH2 = 0x3C;
    	TL2 = 0xB0;		//50MS
    	
    	t2_flag++;
    	
    	if(t2_flag == 2)
    	{
    		TR0 = 0;
    		TR2 = 0;
    		t2_flag = 0;
    		t2_over = 1;	//表示100ms时间到
    	}
    }
    void GetPulse()
    {
    	t0_flag = 0;
    	t2_flag = 0;
    	
    	TH0 = TL0 = 255;
    	TH2 = 0x3C;
    	TL2 = 0xB0;		//50MS
    	
    	TR0 = 1;
    	TR2 = 1;
    }
    
    int PID()	//增量式PID
    {
    	int change;
    
    	err_now = set - now;
    	err_bef = set - bef;
    	err_bbef = set - bbef;
    	
    	change = kp*(err_now - err_bef) + ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
    	
    /*	
    	if(set >= now)
    	{	
    		if(set - now > 1)
    			change = kp*(err_now - err_bef) + ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
    		else
    			change = 0.2*kp*(err_now - err_bef) + 0.5*ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
    	}
    	else if(now > set)
    	{
    		if(now - set > 1)
    			change = kp*(err_now - err_bef) + ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
    		else
    			change = 0.2*kp*(err_now - err_bef) + 0.5*ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
    			
    	}
    */
    	
    	//change = (kp + ki + kd)*(set - now) + (-kp - 2*kd)*(set - bef) + kd*(set - bbef);
    	//change = kp*(set - now) + ki*(set - bef) + kd*(set - bbef);
    	if(change > 0)
    	{
    		printchar(1,10,'+');	
    		printuint(1,11,4,change);
    		
    	}
    	else if(change < 0)
    	{	
    		printchar(1,10,'-');
    		printuint(1,11,4,-change);
    	}
    	else if(change == 0)
    	{	
    		printchar(1,10,' ');
    		printword(1,11," 0  ");
    
    	}
    	
    	return(change);
    }
    
    int PID2()		//位置式PID
    {
    	
    	int num = 0;
    	static num_bef = 0;
    	
    	err_now = set - now;
    	err_bef = set - bef;
    	
    	error_add = error_add + err_now;  //误差累加。一旦误差为0则error_add的值不变,PID输出值不变
    
    	num = kp*err_now + ki*error_add + kd*(err_now - err_bef);
    	
    /*	
    	if(set - now >= 0)
    	{	
    		if(set - now > 1)
    			num = kp*err_now + ki*error_add + kd*(err_now - err_bef);
    		else
    			num = 0.1*kp*err_now + ki*error_add + kd*(err_now - err_bef);
    	}
    	else
    	{
    		if(now - set > 1)
    			num = kp*err_now + ki*error_add + kd*(err_now - err_bef);
    		else
    			num = 0.1*kp*err_now + ki*error_add + kd*(err_now - err_bef);
    			
    	}
    	*/
    	
    	if(num > num_bef)
    	{
    		printchar(1,10,'+');	
    		printuint(1,11,4,num - num_bef);
    	}
    	else if(num < num_bef)
    	{
    		printchar(1,10,'-');	
    		printuint(1,11,4,num_bef - num);
    	}
    	else
    	{	
    		printchar(1,10,' ');
    		printuint(1,11,4,0);
    	}
    	
    	num_bef = num;
    	
    	return((uint)num);
    }
    
    void main()
    {	
    	
    	lcd_init();
    	timer_init();
    	TH1 = TL1 = 255;
    	
    	printword(0,0,"P:");		//比例系数
    	printword(0,5,"S:");		//设定值 
    	printword(1,0,"TPWM:");		//当前占空比
    	printword(0,10,"PS:");		//当前电机反馈的每秒脉冲数
    	
    	while(1)
    	{
    		if(GORB == 1)
    		{	ZZ;		}
    		else
    		{	FZ;		}
    		
    		if(ADDSPEED == 0)
    			set++;
    		if(SUBSPEED == 0)
    			set--;
    		
    		if(Just_Get == 1)
    		{	
    			Just_Get = 0;
    			GetPulse();
    		}
    		else if(t2_over == 1)
    		{	
    			t2_over = 0;
    			Just_Get = 1;
    			pulse = t0_flag;
    			bbef = bef;
    			bef = now;
    			now = t0_flag;
    			
    			if(set != 0)
    			{
    				TR1 = 1;
    			}
    			else
    			{
    				TR1 = 0;
    				PWM = 0;
    			}
    			
    		//	tpwm = tpwm + PID();		//增量式PID
    			tpwm = PID2();				//位置式PID
    					
    		}
    		
    		if(UP == 0)
    			kp = kp + 1;
    		if(DOWM == 0)
    			kp = kp - 1;
    		
    		printuint(0,2,3,kp);
    		printuint(0,7,3,set);
    		printuint(1,5,4,tpwm);
    		printuint(0,13,5,pulse);
    
    	}
    	
    }

            PWM脉冲实质上是通过定时器1来负责产生的。函数GetPulse()借助定时器的延时定时采集电机的脉冲信号。PID和PID2分别是增量式PID和位置式PID的程序代码。希望读者能通过注释读懂程序的工作流程,也可以自行注释掉相关代码来看看不同PID控制方式下的效果。

    展开全文
  • 基于激光对微型无人机实时远程充电的实际需求,以装载激光束发射系统的转动伺服电机为研究对象,在Matlab环境下,建立转台伺服电机的Simulink数学模型,采用PID控制与模糊逻辑控制相结合的方法,对伺服电机跟踪系统...
  • 基于pid控制编码器在直流电机控制转速和转角,。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  • 模糊pid控制,可以用于电机控制系统中,参考改进的pid控制
  • 但是常规的无刷直流电机控制系统通过霍尔传感器来检测转子的位置常规的BLDCM电机控制是PID控制,但是传统PID控制在无刷直流电机控制上的存在动静稳定性不足等问题,于是使用MATLAB软件对无刷直流电机控制系统进行仿真...
  • 本项目采用的是PID控制算法来修正小车行走时两轮的速度偏差,实现小车可以走直线。小车是使用一个安卓App来控制小车的行走路径,App通过App Inventor2来进行编写。 完成作品图: 需要用到的材料: 1. Arduino Uno 2. ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,892
精华内容 3,156
关键字:

pid控制电机