標題:
大佬們能幫忙看看這個電機調速單片機程序有啥問題嗎?
[打印本頁]
作者:
titanium鈦
時間:
2022-3-26 22:29
標題:
大佬們能幫忙看看這個電機調速單片機程序有啥問題嗎?
在另一位大佬貼出來的程序的基礎上改的,各部分程序的作用也都理解了但是燒錄到單片機后電機就是不會調速
自己一直看不出有啥問題,請大佬們幫忙看看
單片機源程序如下:
#include<reg51.h>
#include "intrins.h"
#include <LCD1602.H>
#define uchar unsigned char
#define uint unsigned int
#define GPIO_KEY P2
sbit PWM=P1^3;
uchar speed1[4]={"000"};//設定轉速
uchar speed2[3]={"000"};//占空比
uchar speed[]={"000"}; //當前轉速
uchar KeyValue=0; //鍵值
uint AA,count=0,flag;
float pid_p=0.003,pid_i=0.003,pid_d=0.002; //PID三個參數(shù)初值
uint SpeedSet=50,CurrentSpeed; //設定轉速 當前轉速
unsigned char pid_val_mid; //pid_val_mid脈沖寬度
unsigned int lastError=0; //之前誤差初始為0
long int sumError=0; //偏差積累初始為0
void delay1(unsigned int i)
{
unsigned int j;
for(;i>0;i--)
for(j=0;j<333;j++)
{;}
}
/********************* 鍵盤掃描*************/
void KeyDown(void)
{
GPIO_KEY=0x0f; //設置按鍵觸點初始值為0;0000 1111
delay1(10);
if(GPIO_KEY!=0x0f) //判斷按鍵是否按下
{
delay1(10); //延時消抖
if(GPIO_KEY!=0x0f) //再次判斷按鍵是否按下,低電平有效
{
GPIO_KEY=0X0F;
delay1(10);
//測試列
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;//0000 0111
case(0X0b): KeyValue=1;break;//0000 1011
case(0X0d): KeyValue=2;break;//0000 1101
case(0X0e): KeyValue=3;break;//0000 1110
}
//測試行
GPIO_KEY=0XF0;//設置按鍵觸點初始值為1;1111 0000
delay1(10);
switch(GPIO_KEY)
{ //鍵盤表:
case(0X70): KeyValue=KeyValue+0;break;//0111 0000 0 1 2 3
case(0Xb0): KeyValue=KeyValue+4;break;//1011 0000 4 5 6 7
case(0Xd0): KeyValue=KeyValue+8;break;//1101 0000 8 9 a b
case(0Xe0): KeyValue=KeyValue+12;break;//1110 0000 c d e f
}
}
}
}
void timer()
{
TMOD=0x11;//定時器0工作方式1.16位定時,定時器1工作方式1,16位定時;
TH0=0x4c;//11.0592mhz下的50ms初值 (65535-50000)/256 12mhz是0x3c
TL0=0x00;// (65535-50000)%256 0xb0
TH1=0xfc;//11.0592mhz下的1msPWM控制
TL1=0x66;
TR1=1; //定時器1啟動位,該位由軟件清零
ET1=1; //定時器T1溢出中斷允許
IT0=1; //外部中斷下降沿觸發(fā)
TR0=1; //定時器0啟動位,該位由軟件清零
ET0=1; //定時器T0溢出中斷允許
EX0=1; //外部中斷0中斷允許
EA=1; //CPU全局中斷開放
}
/***********************lcd顯示*************/
void display()
{
speed[0]=CurrentSpeed/100+0x30; //當前轉速
speed[1]=CurrentSpeed/10%10+0x30;//0x30對應ASCII的數(shù)值0
speed[2]=CurrentSpeed%10+0x30;
speed1[0]=SpeedSet/100+0x30;//設定轉速
speed1[1]=SpeedSet/10%10+0x30;
speed1[2]=SpeedSet%10+0x30;
speed2[0]=pid_val_mid/100+0x30;//占空比
speed2[1]=pid_val_mid/10%10+0x30;
speed2[2]=pid_val_mid%10+0x30;
LCD_ShowString(1,1,"SET:"); //設定速度
LCD_ShowNum(1,5,speed1,3);
LCD_ShowString(1,8,"R/MIN");
LCD_ShowString(2,1,"NOW:"); //當前速度
LCD_ShowNum(2,5,speed,3);
LCD_ShowString(2,8,"R/MIN");
}
/************************電機控制*************/
void keyKZ()
{
if(KeyValue==7)//c設定速度加10
SpeedSet+=10;
if(KeyValue==15)//d設定速度減10
SpeedSet-=10;
if(KeyValue==3)//e設定速度加1
SpeedSet+=1;
if(KeyValue==11)//f設定速度減1
SpeedSet-=1;
KeyValue=0;
}
/************************PID控制算法*************/
unsigned int PID()
{
int dError=0,Error=0,B;
Error=SpeedSet-CurrentSpeed;//當前誤差
sumError=Error+sumError;//誤差積累
dError=Error-lastError;//誤差偏差
lastError=Error;
B=pid_p*Error+pid_i*sumError+pid_d*dError;//三個參數(shù)計算
if(B>100) pid_val_mid=100;
if(B<0) pid_val_mid=0;
if(B>=0&&B<=100)
pid_val_mid=B;
return(0);
}
void Timer0_isr() interrupt 1 //定時器0中斷
{
AA++;
TH0=0x4b; //重裝50ms
TL0=0xfe;
if(AA==20) //1s
{
CurrentSpeed=count/96*60;//一分鐘的轉速:count/96(96線編碼器)得出1s內圈數(shù)也就是r/s,圈數(shù)*60得到r/min
count=0;
AA=0;
PID();
}
}
void key_int() interrupt 0 //外部中斷0 P3.2口接a相
{
count++; //a相脈沖計數(shù)
}
void Timer1() interrupt 3 //定時器1中斷
{
static int c=0; //static靜態(tài)變量,只有第一次會賦值
TH1=0xfc; //重新賦值1mspwm,也就是每間隔1ms中斷一次
TL1=0x66;
c++; //每次定時器溢出加1
if(c<=pid_val_mid) PWM=1; //當中斷次數(shù)小于設定的脈寬給高電平,
if(c>pid_val_mid) PWM=0; //等到了設定脈寬值就變?yōu)榈碗娖?br />
if(c>=100) c=0; //一個周期分為100段高低電平,大于100就是下一個周期
}
void main()
{
timer(); //定時器初始化
LCD_Init();//LCD初始化
while(1)
{
KeyDown(); //鍵盤掃描
keyKZ(); //鍵盤控制
display();//顯示LCD
}
}
復制代碼
作者:
Wprogrammer
時間:
2022-3-27 09:56
調試是一步步來才能找到問題的 比如先讓電機動起來 然后可快可慢 這樣才能知道問題點
作者:
lkc8210
時間:
2022-3-27 11:43
你PID三個參數(shù)的初值設得太小
float pid_p=0.003,pid_i=0.003,pid_d=0.002;
Error=SpeedSet-CurrentSpeed;//當前誤差
sumError=Error+sumError;//誤差積累
dError=Error-lastError;//誤差偏差
lastError=Error;
B=pid_p*Error+pid_i*sumError+pid_d*dError;//三個參數(shù)計算假設CurrentSpeed=40;SpeedSet=50;Error=10;
Error小于333, pid_p等于沒用
sumError要34秒后才大于333
dError要Error有改變才有用
研究一下PID三個參數(shù)值的正確設置吧
作者:
titanium鈦
時間:
2022-3-27 11:53
Wprogrammer 發(fā)表于 2022-3-27 09:56
調試是一步步來才能找到問題的 比如先讓電機動起來 然后可快可慢 這樣才能知道問題點
現(xiàn)在的情況就是LCD會顯示但是顯示的速度值不對,電機通電就能轉但是按按鍵啥速度不會改變
只能慢慢調試了
作者:
ankangyu
時間:
2022-3-27 16:56
不可以光改設速度。對應的PID參數(shù)也要改的,每一套PID參數(shù)都是對應當前設定速度的。
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1