a6b18a13632762d0d7ad660ba7ec08fa503dc654.jpg (44.81 KB, 下載次數(shù): 80)
下載附件
2016-3-31 17:35 上傳
要求平衡桿能在正負30°的范圍內平衡。現(xiàn)在我只能讓其在水平位置以下平衡,到了水平位置以上就不能平衡,會飛到上面去了。 求大神指導,不勝感激!
附上程序:
#include <reg52.h>
#include <intrins.h>
#include <math.h>
#define _Nop() _nop_()
#define nop() _nop_()
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
#define LCD_data P0
sbit LCD_RS=P2^3;
sbit LCD_RW=P2^4;
sbit LCD_EN=P2^5;
sbit LCD_PSB=P3^3;
unsigned int c,d,e,f,m,n,p;
uchar code dis1[]={"單軸螺旋槳懸浮系"};
uchar code dis2[]={"角度:"};
uchar code dis3[]={"調整時間:"};
uchar code dis4[]={"°"};
uchar code dis5[]={"秒"};
sbit lowspeed=P3^6; //K3
sbit autospeed=P3^4; //K1 !!!之前的K4與LCD12864端口沖突了!!!
sbit pmw=P3^5;
sbit ADC0832_CLK = P1^4;
sbit ADC0832_DIO = P1^5;
sbit ADC0832_CS = P2^0;
unsigned int chuzhi0=0xb9b0,chuzhi1=0xf830,time,time1;
unsigned char ADC_flag,balance=0x9f;
unsigned char kaiguan=1;
unsigned char jiaodu[20];
unsigned char jiaodu1,jiaodu2,jiaodu3;
unsigned int angle; /*實測角度值*/
float setjiaodu=0;
float Pro=0.01,
I=0.0001,
De=0,
lasterror=0,
pre_error=0,
sumerror=0;
unsigned char ADC0832_Read(unsigned char ch){
unsigned char i,ADC_buff=0,temp=0;
ADC0832_CS = 1;
ADC0832_DIO = 1;
ADC0832_CLK = 0;
ADC0832_CS = 0;
nop();
ADC0832_CLK = 1;
nop();
ADC0832_CLK = 0;
ADC0832_DIO = 1;
nop();
ADC0832_CLK = 1;
nop();
ADC0832_CLK = 0;
if(ch==0)
ADC0832_DIO = 0;
else
ADC0832_DIO = 1;
ADC0832_CLK = 1;
nop();
ADC0832_CLK = 0;
nop();
ADC0832_DIO = 1;
nop();
ADC0832_CLK = 1;
nop();
for(i=0;i<8;i++){
nop();
ADC0832_CLK = 0;
nop();
nop();
ADC_buff=ADC_buff<<1;
if(ADC0832_DIO==1)
ADC_buff=ADC_buff+1;
ADC0832_CLK = 1;
}
for(i=0;i<8;i++){
temp = temp>>1;
if(ADC0832_DIO==1)
temp = temp | 0x80;
ADC0832_CLK = 1;
nop();
ADC0832_CLK = 0;
nop();
}
ADC0832_CS = 1;
ADC0832_CLK = 1;
if(temp == ADC_buff)
ADC_flag = 1;
else
ADC_flag = 0;
return ADC_buff;
}
//1MS為單位的延時程序
void xianshi2();
unsigned int set_to_dat(float a)
{
float b;
if(a>0)
{b=256/5*(2*sqrt(1-((3.1415*a/180)*(3.1415*a/180)))+2.5);}
else
{b=256/5*(2.5-2*sqrt(1-((3.1415*a/180)*(3.1415*a/180))));}
return b;
}
unsigned int ADC0832da_to_Angle(unsigned char da)
{
/*將輸入的數(shù)據(jù)轉換成角度值*/
float Volage;
float Angle;
int zhuan;
Volage =da*5.0/256;
if(0.5*Volage-1.25>=0){
Angle = (float)(asin(0.5*Volage-1.25))*180/3.1415;
zhuan=(float)((asin(0.5*Volage-0.25*5)*180/3.1415)*100);
}
else{
Angle = (float)(asin(1.25-0.5*Volage))*180/3.1415;
zhuan=(float)((asin(1.25-0.5*Volage)*180/3.1415)*100);
}
return zhuan;
}
void delay_1ms(uchar x)
{
uchar j;
while(x--){
for(j=0;j<125;j++)
{;}
}
}
void delay(unsigned int a);
///////////////////以下是LCD12864驅動程序//////////////////////////////
bit lcd_busy() //檢查LCD忙狀態(tài)
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
void lcd_wcmd(uchar cmd)//寫指令數(shù)據(jù)到LCD
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
void lcd_wdat(uchar dat) //寫顯示數(shù)據(jù)到LCD
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
void lcd_init() //LCD初始化設定
{
delay(15);
LCD_PSB = 1; //并口方式
delay(5);
lcd_wcmd(0x34); //擴充指令操作
delay(5);
lcd_wcmd(0x30); //基本指令操作
delay(5);
lcd_wcmd(0x0C); //顯示開,關光標
delay(5);
lcd_wcmd(0x01); //清除LCD的顯示內容
delay(5);
}
////////////////以上是LCD12864驅動程序////////////////////////////
void xianshi()
{
if(jiaodu2<128){
lcd_wcmd(0X93);
delay_1ms(15);
lcd_wcmd(0X93);
delay_1ms(15);
lcd_wcmd(0X93);
delay_1ms(15);
lcd_wdat(0x2B);
delay_1ms(5);
}else{
lcd_wcmd(0X93);
delay_1ms(5);
lcd_wdat(0x2D);
delay_1ms(5);}
lcd_wcmd(0x94);
lcd_wdat(c+0x30);
delay_1ms(20);
lcd_wdat(d+0x30);
delay_1ms(20);
lcd_wdat(0x2E);
delay_1ms(5);
lcd_wdat(e+0x30);
delay_1ms(20);
lcd_wdat(f+0x30);
delay_1ms(20);
}
void xianshi2()
{
lcd_wcmd(0X8D);
lcd_wdat(m+0x30);
delay_1ms(5);
lcd_wdat(n+0x30);
delay_1ms(5);
lcd_wdat(0x2E);
delay_1ms(5);
lcd_wdat(p+0x30);
delay_1ms(5);
}
void pid();
void main(){
uchar i;
lcd_init(); /*LCD初始化*/
lcd_wcmd(0X80); //設置顯示位置為第一行的第1個字符
for(i=0;i<16;i++){lcd_wdat(dis1);} //顯示字符
lcd_wcmd(0X90); //設置顯示位置為第二行的第2個字符
for(i=0;i<6;i++){lcd_wdat(dis2);}
lcd_wcmd(0X88); //設置顯示位置為第三行的第3個字符
for(i=0;i<10;i++){lcd_wdat(dis3);}
lcd_wcmd(0X97); //設置顯示位置為第四行的第3個字符
for(i=0;i<2;i++){lcd_wdat(dis4);}
lcd_wcmd(0X8F); //設置顯示位置為第五行的第3個字符
for(i=0;i<2;i++){lcd_wdat(dis5);}
IT0=0;
EX0=1;
IT1=0;
EX1=1;
TMOD=0x11;
TH0=chuzhi1>>8;
TL0=chuzhi1;
ET0=1;
EA=1;
TR0=1;
while(1){
if(lowspeed==0){ //初始化
delay(20);
if(lowspeed==0){
chuzhi0=0xb5c8;
chuzhi1=0xfc18;
}
}
if(autospeed==0){
delay(20);
if(autospeed==0){
kaiguan=1;
balance=0x90;
//balance=(char)set_to_dat(setjiaodu);
pid();
}
}
}
}
void shezhi() interrupt 1{ //調節(jié)占空比
if(pmw==1){
TH0=chuzhi0>>8;
TL0=chuzhi0;
pmw=0;
}
else{
TH0=chuzhi1>>8;
TL0=chuzhi1;
pmw=1;
}
TF0=0;
}
void shezhi1() interrupt 0{
chuzhi0=0xb5c8;
chuzhi1=0xfc18;
kaiguan=0;
}
void shezhi2() interrupt 3{
time++;
TH1=0X3C;
TL1=0XB0;
TF1=0;
}
/*void shezhi3() interrupt 2{
//balance=0x9c;
} */
void delay(unsigned int a){
unsigned b=50,c=130;
for(;a>0;a--){
for(;b>0;b--)
for(;c>0;c--);
}
}
void pid2();
void pid(){
unsigned char chazhi,chazhi1,chazhi2,button,change,j=3,i;
while(kaiguan==1){
for(i=0;i<20;i++){
jiaodu=ADC0832_Read(0);
delay(200);
}
jiaodu3=jiaodu[0];
jiaodu1=(jiaodu[0]+jiaodu[1]+jiaodu[2]+jiaodu[3]+jiaodu[4]+jiaodu[5]+jiaodu[6]+jiaodu[7]+jiaodu[8]+jiaodu[9])/10;
jiaodu2=(jiaodu[10]+jiaodu[11]+jiaodu[12]+jiaodu[13]+jiaodu[14]+jiaodu[15]+jiaodu[16]+jiaodu[17]+jiaodu[18]+jiaodu[19])/10;
angle=ADC0832da_to_Angle(jiaodu2); //將采集值轉換為角度值
chazhi=abs(jiaodu2-balance);
chazhi1=abs(jiaodu1-balance);
chazhi2=abs(jiaodu3-balance);
change=chazhi/8+1;
if((chazhi>=20)&&(button==0)){
button=1;
TH1=0x3c;
TL1=0xb0;
ET1=1;
TR1=1;
}
if((chazhi<=3)&&(button==1)&&(chazhi1<=3)&&(chazhi2<=3)){
button=0;
ET1=0;
TR1=0;
time1=(time*10)/20;
/*此處添加顯示平衡時間的子函數(shù),平衡時間為已經(jīng)設好的變量“time”*/
m=time1/100;
n=time1%100/10;
p=time1%10;
xianshi2();
// time=0;
pid2();
}
c=angle/1000;
d=angle%1000/100;
e=angle%1000%100/10;
f=angle%10;
j--;
if(j==0){
xianshi();
j=3;
} /*此處添加顯示當前角度的子程序,角度值為已經(jīng)設好的變量“jiaodu2”*/
if(jiaodu2=jiaodu1){
if((jiaodu2>balance)&&(chuzhi0<0xb9b0)&&(chazhi>=2)){
chuzhi0=chuzhi0+change; //改變占空比
chuzhi1=chuzhi1-change;
}
if((jiaodu2<balance)&&(chuzhi0>0xb5c8)&&(chazhi>=2)){
chuzhi0=chuzhi0-change;
chuzhi1=chuzhi1+change;
}
}
if(jiaodu2>jiaodu1){
if((jiaodu2>=balance)&&(chuzhi0<0xb9b0)&&(chazhi>=2)){
chuzhi0=chuzhi0+change;
chuzhi1=chuzhi1-change;
}
}
if(jiaodu2<jiaodu1){
if((jiaodu2<=balance)&&(chuzhi0>0xb5c8)&&(chazhi>=2)){
chuzhi0=chuzhi0-change;
chuzhi1=chuzhi1+change;
}
}
}
return;
}
void pid2(){
float derror,error,change;
unsigned char jiaodu0,button,j;
while(1)
{
jiaodu0=ADC0832_Read(0);
c=angle/1000;
d=angle%1000/100;
e=angle%1000%100/10;
f=angle%10;
j--;
xianshi();
error=(float)abs(balance-jiaodu0);
sumerror+=error;
derror=lasterror-pre_error;
pre_error=lasterror;
lasterror=error;
change=Pro*error+I*sumerror+De*derror;
// change=error/10+1;
if(change>500)
{
change=500;
}
if((error>=20)&&(button==0)){
button=1;
TH1=0x3c;
TL1=0xb0;
ET1=1;
TR1=1;
}
if((jiaodu>balance)&&(chuzhi0<0xb9b0)&&(error>=2)){
chuzhi0=chuzhi0-(int)change;
chuzhi1=chuzhi1+(int)change;
}
if((jiaodu<balance)&&(chuzhi0>0xb5c8)&&(error>=2)){
chuzhi0=chuzhi0+(int)change;
chuzhi1=chuzhi1-(int)change;
}
if(error<2){
button=0;
ET1=0;
TR1=0;
time1=(time*10)/20;
/*此處添加顯示平衡時間的子函數(shù),平衡時間為已經(jīng)設好的變量“time”*/
m=time1/100;
n=time1%100/10;
p=time1%10;
xianshi2();
time=0;
}
}
return;
}
|