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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1794|回復(fù): 5
收起左側(cè)

51單片機PID算法控制直流電機轉(zhuǎn)速

[復(fù)制鏈接]
ID:1140214 發(fā)表于 2024-12-18 16:12 | 顯示全部樓層 |閱讀模式
這是一個論壇老哥( ID:171036)20年寫的有一部分我不會調(diào)了,我想讓電機的實際轉(zhuǎn)速與目標轉(zhuǎn)速一致 新建文件夾.zip (41.75 KB, 下載次數(shù): 0)

111.png

  • /*PID的參數(shù)設(shè)置可以參照以下來進行:
  •   參數(shù)整定找最佳,從小到大順序查;
  •   先是比例后積分,最后再把微分加;
  •   曲線振蕩很頻繁,比例度盤要放大;
  •   曲線漂浮繞大灣,比例度盤往小扳;
  •   曲線偏離回復(fù)慢,積分時間往下降;
  •   曲線波動周期長,積分時間再加長;
  •   曲線振蕩頻率快,先把微分降下來;
  •   動差大來波動慢。微分時間應(yīng)加長;
  •   理想曲線兩個波,前高后低4比1 ;
  •   一看二調(diào)多分析,調(diào)節(jié)質(zhì)量不會低;
  • */
  • #include <reg51.h>
  • #include<stdio.h>
  • #define uchar unsigned char
  • #define uint unsigned int
  • sbit qidong=P1^3;//啟動鍵
  • sbit tingzhi=P1^4;//停止鍵
  • sbit fangxiang=P1^5;//轉(zhuǎn)向鍵
  • sbit AddSpeed=P1^6;//加速鍵
  • sbit SubSpeed=P1^7;//減速鍵
  • sbit RS = P2^5;//LCD1602數(shù)據(jù)命令選擇端口
  • sbit RW = P2^6;//LCD1602讀寫選擇端口
  • sbit EN = P2^7;//LCD1602使能端口
  • sbit IN2=P3^3;//L298輸入端2
  • sbit IN1=P3^4;//L298輸入端1
  • sbit PWM_FC=P3^5;//L298使能端口
  • uchar aa[]={'T','a','r','g','e','t',' ',' ',' ',' ',' ','r','/','s','e','c'};//目標轉(zhuǎn)速:Target  r/sec
  • uchar cc[]={'A','c','t','u','a','l',' ',' ',' ',' ',' ','r','/','s','e','c'};//實測轉(zhuǎn)速: Actual  r/sec
  • uchar displayflag;//顯示標志位變量
  • uint SetSpeed=3000;//聲明設(shè)定速度變量
  • uint ActualSpeed=0;//聲明實際速度變量
  • int e ,e1 ,e2 ;//聲明當前偏差值變量、之后偏差值變量、再后偏差值變量
  • int out=0;//PID調(diào)節(jié)后輸出偏差值變量
  • uint cnt=0;//定時器1中斷次數(shù)變量
  • uint Inpluse=0;//聲明脈沖計數(shù)變量、
  • uint PWMTime=100;//聲明脈沖寬度時間變量
  • float uk ,uk1 ,duk ;//聲明目前總偏差值變量、之后偏差值總變量、偏差值總變量
  • float Kp=0.36,Ki=0.05,Kd=0.016;//pid控制系數(shù)p=0.1,i=0.05,d=0.016。
  •   void delay(uchar x)
  • {
  •    uint i,j;
  •    for(i=x;i>0;i--)
  •     for(j=50;j>0;j--);
  •    }
  •   void DelayUs2x(unsigned char t)
  • {
  •    while(--t);
  •   }
  •   void DelayMs(unsigned char t)
  • {
  •    while(t--)
  • {
  •     DelayUs2x(245);
  •     DelayUs2x(245);
  •    }
  • }
  •   void write_com(uchar com)//寫命令
  • {
  •    RS=0;
  •    RW=0;
  •    P0=com;
  •    DelayMs(5);
  •    EN=1;
  •    DelayMs(5);
  •    EN=0;
  •   }
  •   void write_data(uchar date)//寫一個字符
  • {
  •    RS=1;
  •    RW=0;
  •    P0=date;
  •    DelayMs(5);
  •    EN=1;
  •    DelayMs(5);
  •    EN=0;
  •   }
  •   void init()//初始化
  • {
  •    write_com(0x38);
  •    write_com(0x0c);
  •    write_com(0x06);
  •    write_com(0x01);
  •   }
  •   void LCD_Write_String(uchar x,uchar y,uchar *s)//寫字符串
  • {
  •    if (y == 0)
  • {
  •     write_com(0x80 + x);
  •    }
  •    else
  • {
  •     write_com(0xC0 + x);
  •    }
  •    while (*s)
  • {
  •      write_data( *s);
  •      s++;
  •    }
  • }
  •   void PIDControl()//pid偏差計算
  • {
  •    e=SetSpeed-ActualSpeed;//計算當前偏差值變量
  •    duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2));//PID連續(xù)系統(tǒng)離散化增量型PID算法,算出總偏差值變量。
  •    uk=duk+uk1;//計算偏差值總變量加上之后偏差值總變量之和賦給目前總偏差值變量
  •    out=(int)uk;//強制類型轉(zhuǎn)化為整數(shù)型的目前總偏差值變量賦給PID調(diào)節(jié)后輸出偏差值變量
  •    if(out>1000)//判斷PID調(diào)節(jié)后輸出偏差值變量是否大于100
  • {
  •     out=1000;//PID調(diào)節(jié)后輸出偏差值變量為100
  •    }
  •    else if(out<0)//判斷PID調(diào)節(jié)后輸出偏差值變量是否小于0
  • {
  •     out=0;//PID調(diào)節(jié)后輸出偏差值變量為0
  •   }
  •    uk1=uk;//目前總偏差值變量賦給之后偏差值總變量
  •    e2=e1;//之前偏差值變量賦給之后偏差值變量
  •    e1=e;//當前偏差值變量賦給之前偏差值變量
  •    PWMTime=out;//PID調(diào)節(jié)后輸出偏差值變量賦給脈沖寬度時間變量
  • }
  •   void PWMOUT()
  • {
  •    if(cnt<PWMTime)//判斷定時器1中斷次數(shù)變量是否小于脈沖寬度時間變量
  • {
  •     PWM_FC=1;//脈沖寬度輸入端口輸出高電平
  •    }
  •    else
  • {
  •     PWM_FC=0;//脈沖寬度輸入端口輸出低電平
  •    }
  •    if(cnt>1000)//判斷定時器1中斷次數(shù)變量是否大于100
  •    cnt=0;//定時器1中斷次數(shù)變量歸0
  • }
  •   void SystemInit()//定時器0定時器1外部中斷0初始化函數(shù)
  • {
  •    TMOD=0X21;//定時器0方式1,定時器1方式2。
  •    TH0=0xf8;//初裝定時器0高八位寄存器定時數(shù)值
  •    TL0=0x50 ;//初裝定時器0低八位寄存器定時數(shù)值,即2毫秒。
  •    TH1=0xC0;//初裝定時器1高八位寄存器定時數(shù)值
  •    TL1=0XC0;//初裝定時器1低八位寄存器定時數(shù)值,即16毫秒。
  •    EA=1;//開總中斷
  •    EX0=1;//開外部中斷0
  •    IT0=1;//外部中斷0下降沿觸發(fā)
  •    ET0=1;//開定時器0中斷允許
  •    ET1=1;//開定時器1中斷允許
  •    TR0=1;//開定時器0中斷
  •    TR1=1;//開定時器1中斷
  •    e =0;//偏差值變量為0
  •    e1=0;//之后偏差值變量為0
  •    e2=0;//再后偏差值變量為0
  •    IN1=1;
  •    IN2=1;
  •   }
  •   void SpeedSet()//設(shè)定速度函數(shù)
  • {
  •    if(qidong==0)
  • {
  •     delay(5);
  •     if(qidong==0)
  •   {
  •      IN1=0;
  •      IN2=1;
  •      while(qidong==1);
  •     }
  •    }
  •    if(tingzhi==0)
  • {
  •     delay(5);
  •     if(tingzhi==0)
  •   {
  •      IN1=1;
  •      IN2=1;
  •      EN=1;
  •      while(tingzhi==1);
  •     }
  •    }
  •    if(fangxiang==0)
  • {
  •     delay(5);
  •     if(fangxiang==0)
  •   {
  •      IN1=~IN1;
  •      IN2=~IN2;
  •      while(fangxiang==1);
  •     }
  •    }
  •    if(AddSpeed==0)//判斷加速鍵是否按下
  • {
  •     delay(5);//延時
  •     if(AddSpeed==0)//再次判斷加速鍵是否按下
  •   {
  •      SetSpeed+=100;//設(shè)定速度變量每次加100
  •      if(SetSpeed>3500)//判斷設(shè)定速度變量是否大于3500
  •    {
  •       SetSpeed=3500;//設(shè)定速度變量歸為3500
  •      }
  •     }
  •    }
  •    if(SubSpeed==0)//判斷減速鍵是否按下
  • {
  •     delay(5);//延時
  •     if(SubSpeed==0)//再次判斷減速鍵是否按下
  •   {
  •      SetSpeed-=100;//設(shè)定速度變量每次減100
  •      if(SetSpeed<0)//判斷設(shè)定速度變量是否小于0
  •      SetSpeed=0;//設(shè)定速度變量歸0
  •     }
  •    }
  •     aa[7]=SetSpeed/1000+'0';
  •     aa[8]=SetSpeed/100%10+'0';
  •     aa[9]=SetSpeed/10%10+'0';
  •     aa[10]=SetSpeed%10+'0';
  •     LCD_Write_String(0,0,aa);
  •   }
  •   /**************主函數(shù)************/
  •   void main()
  • {
  •    SystemInit();
  •    init();
  •    LCD_Write_String(0,0,aa);
  •    displayflag=1;
  •    while(1)
  • {
  •     SpeedSet();
  •     if(displayflag==1)
  •   {
  •      displayflag=0;
  •      cc[7]=ActualSpeed/1000+'0';
  •      cc[8]=ActualSpeed/100%10+'0';
  •      cc[9]=ActualSpeed/10%10+'0';
  •      cc[10]=ActualSpeed%10+'0';
  •      LCD_Write_String(0,1,cc);
  •     }
  •    }
  •   }
  •   void int0() interrupt 0//外部中斷0函數(shù)
  • {
  •    Inpluse++;//脈沖計數(shù)變量加加
  •   }
  •   void Timer0() interrupt 1//定時器0中斷服務(wù)函數(shù)
  • {
  •    static uint time=0;//轉(zhuǎn)速測量周期變量
  •    TH0=0xf8;//重裝定時器0高八位寄存器計數(shù)值
  •    TL0=0x50 ;//重裝定時器0低八位寄存器計數(shù)值,即2毫秒。
  •    time++;//轉(zhuǎn)速測量周期變量加加
  •    if(time>500)//判斷轉(zhuǎn)速測量周期變量是否大于500,等于500就是500x2毫秒=1000毫秒,也就是1s。
  • {
  •     time=0;//轉(zhuǎn)速測量周期變量歸0
  •     displayflag=1;//顯示標志位變量置1
  •     ActualSpeed=Inpluse;//脈沖計數(shù)變量表示實際速度變量
  •     Inpluse=0;//脈沖計數(shù)變量歸0
  •     PIDControl();//PID控制函數(shù)
  •    }
  •    PWMOUT();
  • }
  •   void Timer1() interrupt 3//定時器1中斷服務(wù)函數(shù)
  • {
  •    cnt++;//定時器1中斷次數(shù)變量
  •   }

回復(fù)

使用道具 舉報

ID:301191 發(fā)表于 2024-12-22 17:02 | 顯示全部樓層
頂一下
回復(fù)

使用道具 舉報

ID:1109793 發(fā)表于 2024-12-22 18:38 | 顯示全部樓層
我測試了一些,是單管控制,過沖比較嚴重,搞很久,最后就是把e限制了值,我編碼器60脈沖,只有一個信號,0.1秒一個測量周期,輸出鎖定在+—10轉(zhuǎn),除了因為限制e的值后使提速變的比較緩慢以外,倒是可以實現(xiàn)空載時鎖定速度,200-3000之間都可以,目前沒有測試加載情況。因為電流還要控制,目前沒有好的限流方案用啊。
回復(fù)

使用道具 舉報

ID:97678 發(fā)表于 2024-12-22 19:14 | 顯示全部樓層
怎么可以調(diào)節(jié) 步進電機的步數(shù)?
回復(fù)

使用道具 舉報

ID:420836 發(fā)表于 2024-12-23 01:16 | 顯示全部樓層
PID 速度控制的目的不是使實際輸出速度等于目標速度嗎? 如果程序正確,則可能是由于比例,積分和微分系數(shù)缺乏調(diào)整。
回復(fù)

使用道具 舉報

ID:401564 發(fā)表于 2024-12-23 09:17 | 顯示全部樓層
1,你這個電機控制并不需要D項,PI控制就足夠了
2,I項需要限幅
3,過流控制不過是程序流程上的需要而已,在這個電路中意義不大
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 国产视频中文字幕在线观看 | 欧美一区免费 | 久草视频观看 | 老司机67194精品线观看 | 亚洲日日夜夜 | 福利视频三区 | 成人欧美一区二区三区 | 国产精品美女在线观看 | 国产成人精品一区二区三区在线 | 国产精品美女久久久久aⅴ国产馆 | 欧美不卡一区二区三区 | www国产成人 | 午夜精品视频一区 | 五月婷亚洲 | 国产精品高潮呻吟久久av黑人 | 国产探花在线观看视频 | 嫩草视频在线免费观看 | 一区二区三区四区在线免费观看 | 国产美女永久免费无遮挡 | 美女高潮网站 | 日日摸夜夜添夜夜添精品视频 | 亚洲精品乱码久久久久久久久 | 欧美一区二区三区在线观看视频 | 欧美一区二区另类 | 欧美精品一级 | 国产精品国产成人国产三级 | 337p日本欧洲亚洲大胆精蜜臀 | 国产三区精品 | 热久久久久 | 天堂一区二区三区 | www.久久.com | 999久久久久久久久6666 | 国产黄色网址在线观看 | 国产玖玖 | 你懂的在线视频播放 | 新91视频网 | 国产免费一级片 | 日韩精品视频一区二区三区 | 在线视频一区二区三区 | 狠狠骚 | 91精品国产一区二区三区 |