久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
51單片機PID算法控制直流電機轉速
[打印本頁]
作者:
教教我把
時間:
2024-12-18 16:12
標題:
51單片機PID算法控制直流電機轉速
這是一個論壇老哥(
ID:171036
)20年寫的有一部分我不會調了,我想讓電機的實際轉速與目標轉速一致
新建文件夾.zip
(41.75 KB, 下載次數: 0)
2024-12-18 16:10 上傳
點擊文件名下載附件
程序與原理圖
111.png
(105.64 KB, 下載次數: 0)
下載附件
2024-12-18 16:09 上傳
/*PID的參數設置可以參照以下來進行:
參數整定找最佳,從小到大順序查;
先是比例后積分,最后再把微分加;
曲線振蕩很頻繁,比例度盤要放大;
曲線漂浮繞大灣,比例度盤往小扳;
曲線偏離回復慢,積分時間往下降;
曲線波動周期長,積分時間再加長;
曲線振蕩頻率快,先把微分降下來;
動差大來波動慢。微分時間應加長;
理想曲線兩個波,前高后低4比1 ;
一看二調多分析,調節質量不會低;
*/
#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;//轉向鍵
sbit AddSpeed=P1^6;//加速鍵
sbit SubSpeed=P1^7;//減速鍵
sbit RS = P2^5;//LCD1602數據命令選擇端口
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'};//目標轉速:Target r/sec
uchar cc[]={'A','c','t','u','a','l',' ',' ',' ',' ',' ','r','/','s','e','c'};//實測轉速: Actual r/sec
uchar displayflag;//顯示標志位變量
uint SetSpeed=3000;//聲明設定速度變量
uint ActualSpeed=0;//聲明實際速度變量
int e ,e1 ,e2 ;//聲明當前偏差值變量、之后偏差值變量、再后偏差值變量
int out=0;//PID調節后輸出偏差值變量
uint cnt=0;//定時器1中斷次數變量
uint Inpluse=0;//聲明脈沖計數變量、
uint PWMTime=100;//聲明脈沖寬度時間變量
float uk ,uk1 ,duk ;//聲明目前總偏差值變量、之后偏差值總變量、偏差值總變量
float Kp=0.36,Ki=0.05,Kd=0.016;//pid控制系數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連續系統離散化增量型PID算法,算出總偏差值變量。
uk=duk+uk1;//計算偏差值總變量加上之后偏差值總變量之和賦給目前總偏差值變量
out=(int)uk;//強制類型轉化為整數型的目前總偏差值變量賦給PID調節后輸出偏差值變量
if(out>1000)//判斷PID調節后輸出偏差值變量是否大于100
{
out=1000;//PID調節后輸出偏差值變量為100
}
else if(out<0)//判斷PID調節后輸出偏差值變量是否小于0
{
out=0;//PID調節后輸出偏差值變量為0
}
uk1=uk;//目前總偏差值變量賦給之后偏差值總變量
e2=e1;//之前偏差值變量賦給之后偏差值變量
e1=e;//當前偏差值變量賦給之前偏差值變量
PWMTime=out;//PID調節后輸出偏差值變量賦給脈沖寬度時間變量
}
void PWMOUT()
{
if(cnt<PWMTime)//判斷定時器1中斷次數變量是否小于脈沖寬度時間變量
{
PWM_FC=1;//脈沖寬度輸入端口輸出高電平
}
else
{
PWM_FC=0;//脈沖寬度輸入端口輸出低電平
}
if(cnt>1000)//判斷定時器1中斷次數變量是否大于100
cnt=0;//定時器1中斷次數變量歸0
}
void SystemInit()//定時器0定時器1外部中斷0初始化函數
{
TMOD=0X21;//定時器0方式1,定時器1方式2。
TH0=0xf8;//初裝定時器0高八位寄存器定時數值
TL0=0x50 ;//初裝定時器0低八位寄存器定時數值,即2毫秒。
TH1=0xC0;//初裝定時器1高八位寄存器定時數值
TL1=0XC0;//初裝定時器1低八位寄存器定時數值,即16毫秒。
EA=1;//開總中斷
EX0=1;//開外部中斷0
IT0=1;//外部中斷0下降沿觸發
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()//設定速度函數
{
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;//設定速度變量每次加100
if(SetSpeed>3500)//判斷設定速度變量是否大于3500
{
SetSpeed=3500;//設定速度變量歸為3500
}
}
}
if(SubSpeed==0)//判斷減速鍵是否按下
{
delay(5);//延時
if(SubSpeed==0)//再次判斷減速鍵是否按下
{
SetSpeed-=100;//設定速度變量每次減100
if(SetSpeed<0)//判斷設定速度變量是否小于0
SetSpeed=0;//設定速度變量歸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);
}
/**************主函數************/
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函數
{
Inpluse++;//脈沖計數變量加加
}
void Timer0() interrupt 1//定時器0中斷服務函數
{
static uint time=0;//轉速測量周期變量
TH0=0xf8;//重裝定時器0高八位寄存器計數值
TL0=0x50 ;//重裝定時器0低八位寄存器計數值,即2毫秒。
time++;//轉速測量周期變量加加
if(time>500)//判斷轉速測量周期變量是否大于500,等于500就是500x2毫秒=1000毫秒,也就是1s。
{
time=0;//轉速測量周期變量歸0
displayflag=1;//顯示標志位變量置1
ActualSpeed=Inpluse;//脈沖計數變量表示實際速度變量
Inpluse=0;//脈沖計數變量歸0
PIDControl();//PID控制函數
}
PWMOUT();
}
void Timer1() interrupt 3//定時器1中斷服務函數
{
cnt++;//定時器1中斷次數變量
}
作者:
人工置頂員
時間:
2024-12-22 17:02
頂一下
作者:
xiaobendan001
時間:
2024-12-22 18:38
我測試了一些,是單管控制,過沖比較嚴重,搞很久,最后就是把e限制了值,我編碼器60脈沖,只有一個信號,0.1秒一個測量周期,輸出鎖定在+—10轉,除了因為限制e的值后使提速變的比較緩慢以外,倒是可以實現空載時鎖定速度,200-3000之間都可以,目前沒有測試加載情況。因為電流還要控制,目前沒有好的限流方案用啊。
作者:
jovew
時間:
2024-12-22 19:14
怎么可以調節 步進電機的步數?
作者:
TTQ001
時間:
2024-12-23 01:16
PID 速度控制的目的不是使實際輸出速度等于目標速度嗎? 如果程序正確,則可能是由于比例,積分和微分系數缺乏調整。
作者:
Y_G_G
時間:
2024-12-23 09:17
1,你這個電機控制并不需要D項,PI控制就足夠了
2,I項需要限幅
3,過流控制不過是程序流程上的需要而已,在這個電路中意義不大
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
黄色在线播放
|
欧美激情综合网
|
日韩免费视频一区二区
|
成人深夜福利
|
久久精品美女
|
成人午夜av
|
91片黄在线观看
|
黄色av观看
|
亚洲免费精品视频
|
男女免费视频
|
久久久蜜桃
|
日韩国产在线播放
|
日韩在线视频一区
|
欧美激情xxxx
|
www.四虎在线
|
国产精品一区在线播放
|
国产福利在线播放
|
日日操日日射
|
一级黄色片免费看
|
黄色大片在线播放
|
日韩欧美自拍
|
一级真人毛片
|
五月在线视频
|
手机av在线
|
超碰人人人人
|
久久精品一区二区三区四区五区
|
视频一二区
|
欧美视频免费在线观看
|
欧美一二
|
色爱综合网
|
成人三级视频
|
亚洲二级片
|
久在线视频
|
欧美激情国产精品
|
九九热这里
|
一区二区三区视频在线观看
|
性大毛片视频
|
亚洲精品成人
|
欧美黄色片
|
九九影视理伦片
|
国产精品美女毛片真酒店
|