Red de conocimiento informático - Conocimiento sistemático - Programa en lenguaje C de algoritmo PID para control de temperatura

Programa en lenguaje C de algoritmo PID para control de temperatura

//Algoritmo PID control de temperatura lenguaje C 2008-08-17 18:58

#includelt;reg51.hgt

#includelt;intrins.hgt;

#includelt;math.hgt;

#includelt;string.hgt;

struct PID {

unsigned int SetPoint; // Establece el valor deseado objetivo

unsigned int Proportion; // Const proporcional

unsigned int Integral; // Constante integral Const integral

unsigned int Derivative; // Constante diferencial Const derivada

unsigned int LastError; // Error[-1]

unsigned int PrevError; // Error[-2]

unsigned int SumError; // Sumas de errores

};

struct PID spid; // Estructura de control PID

unsigned int rout; )

unsigned int rin; // Retroalimentación PID (entrada)

sbit data1=P1^0

sbit clk=P1^1; >

sbit plus=P2^0;

sbit subs=P2^1;

sbit parada=P2^2

sbit salida =P3; ^4;

sbit DQ=P3^3;

indicador de caracteres sin firmar, flag_1=0;

tiempo_alto, tiempo_bajo, recuento = 0; /Parámetro de ajuste del ciclo de trabajo

unsigned char set_temper=35;

unsigned char temperament

unsigned char i

unsigned char j; =0;

int sin signo

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

Subrutina de retardo, el tiempo de retardo es Prevalecerá el oscilador de cristal de 12M, el tiempo de retardo es 30us×time

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

retraso nulo (tiempo de carácter sin firmar)

{

carácter sin firmar m, n;

for(n=0;nlt;time;n)

for(m= 0;mlt;

2;m ){}

}

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

Escribe una subrutina de datos de un bit

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

void write_bit(unsigned char bitval)

{

EA=0;

DQ=0; /*Baja DQ para iniciar una secuencia de escritura*/

if(bitval==1)

{

_nop_();

DQ=1; /*Si quieres escribir 1, configura el bus en alto*/

}

delay(5

DQ=1 /*Liberar bus DQ*/

_nop_()

_nop_(); ;

EA=1

}

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

Escribir subrutina de datos de un byte

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

void write_byte(unsigned char val)

{

unsigned char i

p>

temperatura de carácter sin firmar;

EA=0; /*Desactivar interrupción*/

TR0=0; ; ilt; 8 ;i) /*Escribe un byte de datos, un bit a la vez*/

{

temp=valgt;gt;i; cambiar esta vez Mueve el bit escrito al bit más bajo*/

temp=tempamp 1

write_bit(temp /*Escribe el bit en el bus*/

p>

}

delay(7); /*Después del retraso 120us*/

// TR0=1

EA=1; *Habilitar interrupción*/

}

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

Lectura de subrutina de datos de un bit

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

carácter sin firmar read_bit()

{

carácter sin firmar i, valor_bit

EA=0;

DQ=0; /*Baja DQ y comienza a leer el tiempo*/

_nop_();

_nop_(); p>

DQ=1; /*Liberar el bus*/

for(i=0;ilt;2;i){}

value_bit=DQ; p>

EA =1;

ret

urna(valor_bit);

}

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

Subrutina de lectura de datos de un byte

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

carácter sin firmar read_byte()

{

carácter sin firmar i, valor=0

EA=0;

for(i=0;ilt;8;i)

{

if(read_bit()) / *leer Un byte de datos se lee una vez en una secuencia y se desplaza*/

value|=0x01lt;lt;i;

delay(4); este momento y luego lea los siguientes datos*/

}

EA=1

return(value);

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

Restablecer subrutina

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

restablecimiento de caracteres sin firmar()

{

presencia de caracteres sin firmar

EA=0

DQ; = 0; /*Baja el bus DQ para comenzar a restablecer*/

delay(30); /*Mantiene el nivel bajo durante 480us*/

DQ=1; Liberar el bus*/

delay(3);

presence=DQ /*Obtener la señal de respuesta*/

delay(28); Retraso para completar toda la secuencia */

EA=1;

return(presence); /*Devuelve la señal de respuesta, si hay un chip, devuelve 0, si lo hay. no es chip, devuelve 1*/

}

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

Obtener subrutina de temperatura

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

void get_temper()

{

unsigned char i, j;

hacer

{

i=reset() /*Reset*/

} while(i!=0); /*1 no hay señal de retroalimentación*/

i=0xcc; / *Enviar comando de posicionamiento del dispositivo*/

write_byte(i); ; /*Enviar comando de inicio de conversión*/

write_byte(i

delay(180);

{

i=reiniciar(); /*reiniciar */

} while(i!=0);

i=0xcc /*Ubicación del dispositivo*/

write_byte(i); p>i=0xbe; /*Leer contenido del buffer*/

write_byte(i

j=read_byte()

i=read_byte ()

i=(ilt;lt;4)amp;0x7f;

s=(unsigned int)(jamp;0x0f); s*100)/16;

j=jgt;gt;4;

temper=i|j; /*La temperatura obtenida se coloca en temperatura*/

p>

}

/*==================================== = =================================================== = ===============

Inicializar estructura PID

================== = =================================================== = =================================*/

void PIDInit (struct PID *pp )

{

memset (pp, 0, sizeof(struct PID)

}

/*==== = =================================================== = ==============================================

Parte de cálculo de PID

====================================== === ================================================= === =============*/

unsigned int PIDCalc( estructura PID *pp, unsigned int NextPoint )

{

unsigned int dError, Error

Error = pp-gt; SetPoint - NextPoint; // Desviación

SumError = Error; >

dError = pp-gt; LastError - pp-gt; PrevError; // Diferencial actual

pp-gt; gt; LastError = Error;

return (pp-gt;Proporción * Error//Proporción

pp-gt;Integral * pp-gt;SumError //Término integral

pp-gt;Derivada * dError); // Término diferencial

}

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

**********************************************

Subrutina de procesamiento de comparación de temperaturas

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

compare_temper()

{

carácter sin firmar i;

if(set_tempergt;temper)

{

if(set_temper-tempergt; 1)

{

tiempo_alto=100;

tiempo_bajo=0;

}

else

{

for (i=0;ilt;10;i)

{ get_temper();

rin = s; p>rout = PIDCalc ( amp ; spid, rin ); // Realizar interacción PID

}

if (high_timelt;=100)

high_time=( char sin firmar)(rout/800 );

else

high_time=100;

low_time= (100-high_time

); }

}

else if(set_temperlt;=temper)

{

if(temper-set_tempergt;0)

{

p>

high_time=0

low_time=100

}

else

{

for(i=0; ilt; 10; i )

{ get_temper();

rin = s; Leer entrada

rout = PIDCalc (amp; spid, rin); // Realizar interacción PID

}

if (high_timelt; 100)

high_time=(unsigned char)(rout/ 10000);

else

high_time=0

low_time= (100-high_time); /p>

}

}

// más

// {}

}

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

Subrutina de servicio de interrupción T0, utilizada para controlar el cambio de nivel, período de 40us*100=4ms

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

void save_T0() interrumpe 1 usando 1

{

if( count

lt;=(high_time))

salida=1

else if(countlt;=100)

{

salida= 0;

}

de lo contrario

cuenta=0

TH0=0x2f

TL0=0xe0; ;

}

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

Rutina de servicio de interrupción del puerto serie, utilizada para la comunicación con la computadora host

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

void save_sio() interrumpe 4 usando 2

{

/* EA=0

RI; =0;

p>

i=SBUF;

if(i==2)

{

mientras( RI==0){}

RI=0;

set_temper=SBUF;

SBUF=0x02; ==0){}

TI=0;

}

si no(i==3)

{

TI=0;

SBUF=temperamento;

mientras(TI==0){}

TI=0; >

}

EA=1; */

}

void disp_1(unsigned char disp_num1[6])

{

carácter sin firmar n, a, m

for(n=0;nlt;6;n)

{

// k=disp_num1[n];

for(a=0; alt; 8; a )

{

clk=0; >

m=(disp_num1[n ]amp;1);

disp_num1[n]=disp_num1[n]gt;gt;1

if(m== 1)

datos1 =1

de lo contrario

datos1=0

_nop_(); clk=1;

_nop_();

}

}

}

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

Mostrar subrutina

Función: convierte la temperatura del ciclo de trabajo en un solo carácter, muestra el ciclo de trabajo y la temperatura medida

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

visualización nula ( )

{

número de código de carácter sin firmar[]={0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6 , 0xbe, 0xe0, 0xfe, 0xf6};

d char disp_num[6];

unsigned int k, k1

k=high_time

k=k1000; =k/100;

if(k1==0)

disp_num[0]=0

si no

disp_num[; 0]=0x60;

k=k100;

num_disp[1]=número[k/10]; ];

k=temperamento;

k=k100;

disp_num[3]=número[k/10]; disp_num[4]=número[k10] 1

disp_num[5]=número[s/10];

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

Programa principal

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

main()

{

carácter sin firmar z;

carácter sin firmar a, b, flag_2=1, count1=0;

char phil sin firmar[]={2, 0xce, 0x6e, 0x60, 0x1c, 2};

TMOD=0x21;

TH0=0x2f; /p>

TL0 =0x40;

SCON=0x50;

PCON=0x00;

TH1=0xfd; TL1=0xfd;

PS=1;

EA=1;

EX1=0; p>

ES= 1;

TR0=1;

TR1=1;

tiempo_alto=50; =50;

PIDInit (amp; spid); // Inicializar estructura

spid.Proportion = 10; // Establecer coeficientes PID

spid.Integral = 8;

spid.Derivative =6;

spid.SetPoint = 100; // Establecer punto de ajuste PID

mientras(1)

{

if(plus==0) ​​​​

{

EA=0

for(a=0; alt;5;a)

for(b=0;blt;102;b){}

if(plus==0) ​​​​

{

set_temper;

flag=0;

}

}

si no

bs==0) ​​​​

{

for(a=0;alt;5;a)

for(b=0;alt;102 ;b ){}

if(subs==0) ​​​​

{

set_temper--

flag=0; ;

}

}

si(parada==0)

{

para(a =0; alt ;5;a)

for(b=0;blt;102;b){}

if(stop==0)

{

bandera=0;

romper;

}

EA=1; /p>

get_temper();

b=temperamento;

if(flag_2==1)

a=b;

if ((abs(a-b))gt; 5)

temperamento=a

else

temperamento=b; p>a= temperamento;

flag_2=0;

if( count1gt; 30)

{

display(); /p>

count1=0;

}

compare_temper();

}

TR0=0; p>

z=1;

mientras(1)

{

EA=0; =0)

{

para(a=0; alt; 5; a )

para(b=0; blt; 102; b ){ }

if(stop==0)

disp_1(phil);

// descanso;

EA =1;

}

}

//subrutina DS18b20

#include lt; /p>

sbit DQ=P2^1; //Definir puerto

typedef unsigned char byte;

typedef unsigned int word;

// Retraso

retraso nulo(palabra usegundos)

{

for(;usegundosgt;0;usegundos--);

}

//Restablecer

byte ow_reset(void)

{

presencia de bytes;

DQ=0; // nivel bajo DQ

retraso(29); //480us

DQ=1; //nivel alto DQ

retraso(3);

//Espera

presencia=DQ; //señal de presencia

retraso(25);

retorno(presencia

} //0 permite, 1 prohíbe

//Leer un byte del bus de 1 cable

byte read_byte(viod)

{

byte i;

valor de byte=0;

para (i=8; igt; 0; i--)

{

valorgt;gt;=1;

DQ=0;

DQ=1;

retraso(1);

if(DQ)valor|=0x80;

retraso(6);

}

retorno(valor);

}

//Escribe un byte en el bus de 1 cable

void write_byte(char val)

{

byte i; /p>

for (i=8; igt; 0; i--) //Escribe un byte a la vez

{

DQ=0;

DQ=valamp;0x01;

retraso(5);

DQ=1;

val=val/2;

p>

}

retraso(5);

}

//Leer temperatura

char Read_Temperature( vacío)

{

unión{

byte c[2]

int x

} temp;

ow_reset();

write_byte(0xcc);

write_byte(0xBE); =read_byte();

temp.c[0]=read_byte();

ow_reset()

write_byte(0xCC);

escribir_byte(0x44);

devolver temp.x/2;

}