×
单片机 > 单片机程序设计 > 详情

51单片机PID控制垂直风力摆设置角度

发布时间:2023-09-01 发布时间:
|

#include

#include "i2c.h"

#include "delay.h"

#include "display.h"

#include "math.h"

#define uchar unsigned char

#define uint unsigned int

#define AddWr 0x90 //写数据地址

#define AddRd 0x91 //读数据地址

void timer0_init(); //定时器0初始化

void motor_run();

void control();

uchar time;

uint motor_pwm;

double count=0; //定义占空比,并初始占空比为26%

sbit PWM=P2^3;

sbit Motor_CW=P2^4;

sbit Motor_CCW=P2^5;

float angleset=50;

float angel;

uint nowerror;

long sumerror;

uint lasterror;

float output;


float kp=0.56,ki=0.008,kd=1;

extern bit ack;

bit flag;

//bit WriteDAC(unsigned char dat);

/*------------------------------------------------

主程序

------------------------------------------------*/

uchar ReadADC(uchar Chl)

{

uchar val;

Start_I2c();

SendByte(AddWr);

if(ack==0)return (0);

SendByte(Chl);

if(ack==0)return (0);

Start_I2c();

SendByte(AddRd);

if(ack==0)return (0);

val=RcvByte();

NoAck_I2c();

Stop_I2c();

return(val);

}

void motor_run(uint pwm)

{

if(time

{

PWM=1;

}else

{

PWM=0;

}

if(time>100)

{

time=0;

flag=1;

}


}

/****************************pid*****************************/

void timer0_init()

{

TMOD=0x01; //定时器0工作于方式1

TH0=(65536-100)/256;

TL0=(65536-100)%256;

TR0=1;

ET0=1;

EA=1;

}


/**************定时0中断处理******************/

void timer0_int() interrupt 1

{


TR0=0; //设置定时器初值期间,关闭定时器

TH0=(65536-100)/256;

TL0=(65536-100)%256;

TR0=1;

time++;

motor_run(motor_pwm);


}


uint XIANFU_Pwm(uint pwm)

{

if ( pwm <0) pwm = 0;

if (pwm>=100) pwm= 100;

return pwm;


}

float PID_Control(float angleset,float angel)

{

angel=ReadADC(0x40);

nowerror=angleset-angel;//当前误差

sumerror+=nowerror; //误差求和

if(sumerror>2500)

sumerror=2500;//限幅

output = kp*nowerror+ki*sumerror+kd*(lasterror-nowerror);

lasterror=nowerror;

return output;//增量输出

}

void control()

{

motor_pwm=(uint) PID_Control(angleset,angel);

motor_pwm= XIANFU_Pwm(motor_pwm);

//motor_run(motor_pwm);

}

main()

{

float angleAD;

Motor_CW=0; //电机正反转

Motor_CCW=1;

timer0_init();

while(1)

{

if(flag==1)

{

flag=0;

control();

}

angleAD = ReadADC(0x40); //绝对角度数字值AD值

display(angleAD);

//WriteDAC(angleAD);

}

}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机与232串口通讯