久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4963|回復: 1
收起左側

基于51單片機pid調節的直流電機pwm控制

[復制鏈接]
ID:738241 發表于 2020-4-26 09:56 | 顯示全部樓層 |閱讀模式
#include <REGX51.H>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define THC0 0xf8
#define TLC0 0x50   //2ms,0x30,含中斷處理時間時,0x50

#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1

sbit RS = P2^0;   //定義端口
sbit RW = P2^1;
sbit EN = P2^2;

unsigned char aa[]={'T','a','r','g','e','t',' ',' ',' ',' ',' ','r','/','m','i','n'};  //目標轉速。Target            r/min
unsigned char cc[]={'A','c','t','u','a','l',' ',' ',' ',' ',' ','r','/','m','i','n'};           //實測轉速: Actual      r/min
                                                                                                                                                                                                                                 
uchar i=0;
sbit k1=P3^3;
sbit k2=P3^4;
sbit k3=P3^5;
sbit k4=P3^6;
sbit k5=P3^7;
sbit PWM_FC=P1^0;
sbit IN1=P1^1;
sbit IN2=P1^2;
int out=0;
uint SpeedSet=3000;
uint cnt=0;
uint Inpluse=0,num=0,zs;//脈沖計數
uint PWMTime=100;//脈沖寬度
int e ,e1 ,e2 ;//pid 偏差
float uk ,uk1 ,duk ;//pid輸出值
float Kp=0.36,Ki=0.05,Kd=0.016;//pid控制系數        0.1 0.05 0.016

/*
PID的參數設置可以參照以下來進行:  
     參數整定找最佳,從小到大順序查;  
         先是比例后積分,最后再把微分加;  
         曲線振蕩很頻繁,比例度盤要放大;  
         曲線漂浮繞大灣,比例度盤往小扳;  
         曲線偏離回復慢,積分時間往下降;  
         曲線波動周期長,積分時間再加長;  
         曲線振蕩頻率快,先把微分降下來;  
         動差大來波動慢。微分時間應加長;  
         理想曲線兩個波,前高后低4比1 ; 
         一看二調多分析,調節質量不會低;
*/

void PIDControl();
void SystemInit();
void delay(uchar x);
void PWMOUT();
void SetSpeed();
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);
void init();
void write_com(unsigned char com);
void write_data(unsigned char date);
/*------------------------------------------------
uS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
長度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t);
/*------------------------------------------------
mS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t);


void DelayUs2x(unsigned char t)
{   
        while(--t);
}

void DelayMs(unsigned char t)
{
          while(t--)                 //大致延時1mS
        {
             DelayUs2x(245);
        }
}


void write_com(unsigned char com) //寫命令
{
        RS_CLR;
        RW_CLR;
        P0=com;
        DelayMs(3);
        EN_SET;
        DelayMs(3);
        EN_CLR;
}

void write_data(unsigned char date)         //寫一個字符
{
        RS_SET;
        RW_CLR;
        P0=date;
        DelayMs(3);
        EN_SET;
        DelayMs(3);
        EN_CLR;
}

void init()                        //初始化
{
        write_com(0x38);
        write_com(0x0c);
        write_com(0x06);
        write_com(0x01);
}

/*------------------------------------------------
              寫入字符串函數
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{     
        if (y == 0)
        {     
                 write_com(0x80 + x);     
        }
        else
        {     
                write_com(0xC0 + x);     
        }        
        while (*s)
        {     
                write_data( *s);     
                s ++;     
        }
}
/**************主函數************/
void main()
{
        SystemInit();
        init();
        LCD_Write_String(0,0,aa);
        zs=1;
        while(1)
        {
                SetSpeed();
                if(zs==1)
                {
                    zs=0;
                        cc[7]=num/1000+'0';
                        cc[8]=num/100%10+'0';
                        cc[9]=num/10%10+'0';
                        cc[10]=num%10+'0';
                        LCD_Write_String(0,1,cc);
                }
        }
}

void PIDControl()        //pid偏差計算
{
        e=SpeedSet-num;
        duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2));  
        uk=uk1+duk;
        out=(int)uk;
        if(out>1000)
        {
                out=1000;
        }
        else if(out<0)
        {
                out=0;
        }
        uk1=uk;
        e2=e1;
        e1=e;
        PWMTime=out;
}

void delay(uchar x)
{
        uint i,j;
        for(i=x;i>0;i--)
                for(j=50;j>0;j--);
}

void PWMOUT()
{
        if(cnt<PWMTime)
        {
                PWM_FC=1;
        }
        else
        {
                PWM_FC=0;
        }
        if(cnt>1000) cnt=0;
}
void SystemInit()
{
        TMOD=0X21;    //t1用來串口t2定時
        TH0=THC0;
        TL0=TLC0;
        TH1=0xC0;
        TL1=0XC0;
        ET1=1;
        ET0=1;
        TR0=1;
        TR1=1;
        EX0=1;     //中斷0用來測量轉速
        IT0=1;
        EA=1;
        e =0;
        e1=0;
        e2=0;
        IN1=1;
        IN2=1;
}
void SetSpeed()
{
        if(k1==0)
        {
                delay(100);
                if(k1==0)
                {
                   IN1=0;
                   IN2=1;
                }
        }
        if(k2==0)
        {
                delay(100);
                if(k2==0)
                {
                   IN1=1;
                   IN2=1;
                }
        }
        if(k3==0)
        {
                delay(100);
                if(k3==0)
                {
                   IN1=~IN1;
                   IN2=~IN2;
                }
                while(k3==0);
        }
        if(k4==0)
        {
                delay(100);
                if(k4==0)
                {
                        SpeedSet+=10;
                        if(SpeedSet>3500)
                        {
                                SpeedSet=3500;
                        }
                }
        }
        if(k5==0)
        {
                delay(100);
                if(k5==0)
                {
                        SpeedSet-=10;
                        if(SpeedSet<0) SpeedSet=0;
                }
        }       
        aa[7]=SpeedSet/1000+'0';
        aa[8]=SpeedSet/100%10+'0';
        aa[9]=SpeedSet/10%10+'0';
        aa[10]=SpeedSet%10+'0';
        LCD_Write_String(0,0,aa);
}


void int0() interrupt 0
{
        Inpluse++;
}
void t0() interrupt 1
{
        static unsigned int time=0;

        TH0=THC0;
        TL0=TLC0;
        time++;  //轉速測量周期
        if(time>500)
        {
                zs=1;
                time=0;
                num=Inpluse;         //計算式中是仿真時,碼盤數60時的情況,如果碼盤數n=10時,num=Inpluse*60/n=Inpluse*6;
                Inpluse=0;
                PIDControl();
        }
        PWMOUT();
}
void timer_1()  interrupt 3
{
           cnt++;        //cnt越大占空比越高2.5Khz
}

回復

使用道具 舉報

ID:1 發表于 2020-4-26 16:05 | 顯示全部樓層
本帖需要重新編輯補全電路原理圖,源碼,詳細說明與圖片即可獲得100+黑幣(帖子下方有編輯按鈕)
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产一区二区三区久久久久久久久 | 国产美女在线观看 | 完全免费在线视频 | 久久精品一级 | 天天爽夜夜爽精品视频婷婷 | 欧美涩 | 黄色毛片黄色毛片 | 国产yw851.c免费观看网站 | 日韩中文一区二区三区 | 久久久91精品国产一区二区三区 | 久久精品成人一区 | 中文字幕av一区 | 欧美大片在线观看 | 国产成人精品免费 | 国产视频久久久久 | 欧美日韩国产高清 | 亚洲福利一区 | 精品一区二区三区在线观看 | 欧美日韩中文在线 | 国产精品久久久久久久7电影 | 91爱爱·com | 欧美国产91 | 欧美视频精品 | 人人色视频| 国产成人亚洲精品自产在线 | 日韩欧美一区二区在线播放 | 国产精品区二区三区日本 | 免费一级黄色录像 | 亚洲视频欧美视频 | 天天干狠狠干 | 一区二区av| 成人免费淫片aa视频免费 | av一区二区三区四区 | 中文字幕一区二区三区精彩视频 | 亚洲成人午夜电影 | 亚洲在线 | 欧美久| 日韩男人天堂 | 亚洲欧美日韩在线 | 伊人无码高清 | аⅴ资源新版在线天堂 |