基于单片机AT89c51的数字PID控制直流电机PWM调速系统C语言程序

Python018

基于单片机AT89c51的数字PID控制直流电机PWM调速系统C语言程序,第1张

首先弄清楚PID是一种控制算法!!!

1,“如果用单片机恒温可以使温度到达预定值就停止加热,低了就加热,用一个

温度传感器

反馈,这样算是一个自动控制吗”你这是

控制系统

,但是效果会非常差,尤其是对于

温度控制

这种大

惯性系统

,达到预定值就停止加热,但是由于惯性,温度肯定会继续上升,

电炉

烧水的时候,水开了,断电之后水还要沸腾一定时间的(沸腾是很消耗能量的,由此可见如果是加热的话温度上升更严重,你也可以自己用温度计试试看);“低了就加热”是同样的道理。如果系统对

控制精度

有要求,你这样做肯定达不到要求。PID是一种控制算法,相对于其他控制算法来说算是最简单的了。PID能够做到在温度快要达到设定值的时候降低加热

功率

,让温度上升速度变慢,最终稳定在

设定值

。如果用你的直接控制,温度会在设定值上下振荡,永远不会停在设定值。

2,一般的控制系统都需要加反馈,以构成

闭环控制系统

,相对的还有

开环控制系统

开环控制系统,举个例子,就是你加热的时候事先计算好大约需要多少热量,然后考虑一下环境影响,计算出

加热时间

,然后控制加热系统按照你这个时间加热。你觉得这样的系统能够稳定工作吗?环境稍稍有变动就挂了!开环控制系统的特点就是很容易受到环境的影响;闭环控制系统就稳定很多,你用1L水可用,2L水也行,500W电能用,1000W电炉也能用,这就是闭环的优点。

因此,大多数的控制系统都是闭环的,开环很少单独使用,即使用到了也是有闭环的。开环其实也是有优点的,开环在控制系统里面叫做前馈(跟反馈对应的),比如你的系统里面电源电压上升了,加热速度肯定会变快,如果你对电源电压采样,将采样的结果输入到闭环里面,对闭环做一个轻微的修正,控制的

精度

会更好,这就是开环的优势,它是超前的,能够预知结果(根据地源电压提高就能知道需要降低输出功率了)。

说完这些,你应该明白了,反馈是必需的(前馈也可以要,但是不是必需的),PID不能被取代(除非你用其它更复杂的控制算法)。

给你推荐一本书,<计算机图形学基础>唐泽圣,周嘉玉,李新友写的,我们以前上课用的,上面有常用的直线和圆弧算法,比如数值微分法生成直线,逐点比较法插补圆弧,角度DDA法产生圆弧,基本都有C语言的源程序.你可以搜搜这本书,本来都有源程序的,后来给删掉了~~

贴一个别人的

/*************************************************************************

Function: int ArcXY(double dfx0,double dfy0,double dfrx,

double dfry,int angle)

Description: 在X-Y轴所构成的平面上,以圆弧运动的方式从目前位置经过指

定的参考点到目的点。调用此函数成功将增加运动命令的库存数目。

Parameters:dfx0, dfy0 参考点的X-Y轴座标值

dfrx, dfry 圆心的X-Y轴座标值

angle 插补角度

Calls: 无

Return Value: 大於或等於0 给予此运动命令的编码

小於0失败,传回值的意义可参考错误信息代码

**************************************************************************/

#include <stdio.h>

#include <math.h>

int ArcXY(double dfx0,double dfy0,double dfrx, double dfry,int angle)

int symbol(double number)

main()

{

ArcXY(0,0,-3,5,360)

getch()

}

int ArcXY(double dfx0,double dfy0,double dfrx, double dfry,int angle)

{

FILE *f1

double i,j,dx,dy,dfr,x,y,ang,step,f = 0.01

int flag,tempx,tempy,statex,statey,direction = 1

dfr = sqrt((dfrx - dfx0) * (dfrx - dfx0) + (dfry - dfy0) * (dfry - dfy0))

if(dfx0 == 0)

{

dfx0 = 1

dfrx = dfrx + 1

statex =1

}

if(dfy0 == 0)

{

dfy0 = 1

dfry = dfry + 1

statey =1

}

dfrx = 2 * dfx0 - dfrx

i = dfx0 - dfrx

j = dfy0 - dfry

x = dfx0

y = dfy0

step = ang = 180 * 2 * asin(f/(2*dfr))/3.1415926

if(((dfx0 >0) &&(dfy0 >0)) || ((dfx0 <0) &&(dfy0 <0)))

{

flag = direction

}

if(((dfx0 <0) &&(dfy0 >0)) || ((dfx0 >0) &&(dfy0 <0)))

{

flag = -direction

}

f1=fopen("c:\\c.txt","w+")

if(statex ==1)

{

x = x - 1

}

if(statey ==1)

{

y = y - 1

}

fprintf(f1,"%f,",x)

fprintf(f1,"%f\n",y)

while(ang <angle)

{

dx = f * (j + flag*(f * i)/(2 * dfr))/dfr

dy = f * (i - flag*(f * j)/(2 * dfr))/dfr

tempx = symbol(x)

tempy = symbol(y)

x = x + dx

y = y + dy

fprintf(f1,"%f,",x)

fprintf(f1,"%f\n",y)

if( (tempx !=symbol(x)) || (tempy != symbol(y)) )

{

flag = -flag

}

i = i - dx

j = j + dy

ang = ang + step

}

return 0

}

int symbol(double number)

{

if(number >0)

{

return 1

}

else

{

return -1

}

}

int ArcXY(double dfx0,double dfy0,double dfrx, double dfry,int angle)这个就是子函数,你放到你需要的地方注意参数,按自己需要修改,要么添加返回值返回感兴趣的部分,要么添加参数按照传引用的方法取得,直线的有简单DDA算法的,需要的话明天打上,今天有点晚了.