Program of water tank temperature PID control system designed by C51 microcontroller, PID control program

Publisher:幸福的人生Latest update time:2023-02-08 Source: elecfans Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

This system is a microcontroller temperature control system based on PID. I found a complete program on the Internet and made the corresponding proteus hardware simulation according to his program, but

It did not achieve the expected effect. It needs to be improved.


The procedure is as follows:


#include<reg51.h> 

#include<intrins.h> 

#include<math.h> 

#include<string.h> 

struct PID { 

unsigned int SetPoint; // Set the target Desired Value 

unsigned int Proportion; // Proportional Const 

unsigned int Integral; // Integral constant Integral Const 

unsigned int Derivative; // Derivative constant Derivative Const 

unsigned int LastError; // Error[-1] 

unsigned int PrevError; // Error[-2] 

unsigned int SumError; // Sums of Errors 

}; 

struct PID spid; // PID Control Structure 

unsigned int rout; // PID Response (Output) 

unsigned int rin; // PID Feedback (Input) 

sbit data1=P1^0; 

sbit clk=P1^1; 

sbit plus=P2^0; 

sbit subs=P2^1; 

sbit stop=P2^2; 

sbit output=P3^4; 

sbit DQ=P3^3; 

unsigned char flag,flag_1=0; 

unsigned char high_time,low_time,count=0; //Duty cycle adjustment parameters 

unsigned char set_temper=35; 

unsigned char temper; 

unsigned char i; 

unsigned char j=0; 

unsigned int s; 

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

Delay subroutine, the delay time is based on the 12M crystal oscillator, the delay time is 30us×time 

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

void delay(unsigned char time) 

unsigned char m,n; 

for(n=0;n<time;n++) 

for(m=0;m<2;m++){} 

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

Write a one-bit data subroutine 

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

void write_bit(unsigned char bitval) 

EA=0; 

DQ=0; /*Pull DQ low to start a write sequence*/ 

if(bitval==1) 

  _nop_(); 

  DQ=1; /*If you want to write 1, set the bus high*/ 

delay(5); /*Delay 90us for DA18B20 sampling*/ 

DQ=1; /*Release DQ bus*/ 

_nop_(); 

_nop_(); 

EA=1; 

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

Write one byte data subroutine 

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

void write_byte(unsigned char val) 

unsigned char i; 

unsigned char temp; 

EA=0; 

TR0=0; 

for(i=0;i<8;i++) /*Write one byte of data, one bit at a time*/ 

  temp=val>>i; /*Shift operation, move the bit to be written this time to the lowest bit*/ 

  temp=temp&1; 

  write_bit(temp); /*Write this bit to the bus*/ 

delay(7); /*After delaying 120us*/ 

// TR0=1; 

EA=1; 

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

Read one bit of data subroutine 

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

unsigned char read_bit() 

unsigned char i,value_bit; 

EA=0; 

DQ=0; /*Pull DQ low to start reading timing*/ 

_nop_(); 

_nop_(); 

DQ=1; /*Release the bus*/ 

for(i=0;i<2;i++){} 

value_bit=DQ; 

EA=1; 

return(value_bit); 

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

Read one byte data subroutine 

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

unsigned char read_byte() 

unsigned char i,value=0; 

EA=0; 

for(i=0;i<8;i++) 

  if(read_bit()) /*Read one byte of data, read once in one sequence, and perform shifting processing*/ 

  value|=0x01<<i; 

  delay(4); /*Delay 80us to complete this timing, and then read the next data*/ 

EA=1; 

return(value); 

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

reset subroutine 

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

unsigned char reset() 

unsigned char presence; 

EA=0; 

DQ=0; /*Pull the DQ bus low to start reset*/ 

delay(30); /*Keep low level for 480us*/ 

DQ=1; /*Release the bus*/ 

delay(3); 

presence=DQ; /*Get response signal*/ 

delay(28); /*Delay to complete the entire sequence*/ 

EA=1; 

return(presence); /*Return the response signal, if there is a chip, it returns 0, if there is no chip, it returns 1*/ 

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

Get temperature subroutine 

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

void get_temper() 

unsigned char i,j; 

do 

  i=reset(); /*reset*/ 

}while(i!=0); /*1 is no feedback signal*/ 

i=0xcc; /*Send device positioning command*/ 

write_byte(i); 

i=0x44; /*Send conversion command*/ 

write_byte(i); 

delay(180); /*delay*/ 

do 

  i=reset(); /*reset*/ 

}while(i!=0); 

i=0xcc; /*Device positioning*/ 

write_byte(i); 

i=0xbe; /*Read buffer contents*/ 

write_byte(i); 

j=read_byte(); 

i=read_byte(); 

i=(i<<4)&0x7f; 

s=(unsigned int)(j&0x0f); 

s=(s*100)/16; 

j=j>>4; 

temper=i|j; /*The obtained temperature is placed in temperature*/ 

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

Initialize PID Structure 

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

void PIDInit (struct PID *pp) 

memset ( pp,0,sizeof(struct PID)); 

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

PID calculation part 

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

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

unsigned int dError,Error; 

Error = pp->SetPoint - NextPoint; // Deviation 

pp->SumError += Error; // Points 

dError = pp->LastError - pp->PrevError; // Current differential 

pp->PrevError = pp->LastError; 

pp->LastError = Error; 

return (pp->Proportion * Error // Proportion term 

+ pp->Integral * pp->SumError // Integral term 

+ pp->Derivative * dError); // Differential term 

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

Temperature comparison processing subroutine 

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

compare_temper() 

unsigned char i; 

if(set_temper>temper) 

  if(set_temper-temper>1) 

  { 

   high_time=100; 

   low_time=0; 

  } 

  else 

  { 

   for(i=0;i<10;i++) 

   { 

    get_temper(); 

    rin = s; // Read Input 

    rout = PIDCalc ( &spid,rin ); // Perform PID Interation 

   } 

   if (high_time<=100) 

   {

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

   }

   else 

   {

    high_time=100;

      }

   low_time= (100-high_time); 

  } 

else if(set_temper<=temper) 

  if(temper-set_temper>0) 

  { 

   high_time=0; 

   low_time=100; 

  } 

  else 

  { 

   for(i=0;i<10;i++) 

   { 

    get_temper(); 

    rin = s; // Read Input 

    rout = PIDCalc ( &spid,rin ); // Perform PID Interation 

   } 

   if (high_time<100) 

   {

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

   }

   else 

   {

    high_time=0; 

   }

   low_time= (100-high_time); 

  } 

// else 

// {} 

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

T0 interrupt service subroutine, used to control level flipping, 40us*100=4ms cycle 

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

void serve_T0() interrupt 1 using 1 

if(++count<=(high_time)) 

output=1; 

else if(count<=100) 

  output=0; 

else 

count=0; 

TH0=0x2f; 

TL0=0xe0; 

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

Serial port interrupt service routine, used for host computer communication 

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

void serve_sio() interrupt 4 using 2 

/* EA=0; 

RI=0; 

i=SBUF; 

if(i==2) 

while(RI==0){} 

RI=0; 

set_temper=SBUF; 

SBUF=0x02; 

while(TI==0){} 

TI = 0; 

else if(i==3) 

TI = 0; 

SBUF=temper; 

while(TI==0){} 

TI = 0; 

EA=1; */ 

void disp_1(unsigned char disp_num1[6]) 

unsigned char n,a,m; 

for(n=0;n<6;n++) 

// k=disp_num1[n]; 

  for(a=0;a<8;a++) 

  { 

   clk=0; 

   m=(disp_num1[n]&1); 

   disp_num1[n]=disp_num1[n]>>1; 

   if(m==1) 

   data1=1; 

   else 

   data1=0; 

   _nop_(); 

   clk=1; 

   _nop_(); 

  } 

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

display subroutine 

Function: Convert duty cycle temperature into a single character, display duty cycle and measured temperature 

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

void display() 

unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; 

unsigned char disp_num[6]; 

unsigned int k,k1; 

k=high_time; 

k=k%1000; 

k1=k/100; 

if(k1==0) 

disp_num[0]=0; 

else 

disp_num[0]=0x60; 

k=k%100; 

disp_num[1]=number[k/10]; 

disp_num[2]=number[k%10]; 

k=temper; 

k=k%100; 

disp_num[3]=number[k/10]; 

disp_num[4]=number[k%10]+1; 

disp_num[5]=number[s/10]; 

disp_1(disp_num); 

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

main program 

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

main() 

unsigned char z; 

unsigned char a,b,flag_2=1,count1=0; 

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

TMOD=0x21; 

TH0=0x2f; 

TL0=0x40; 

SCON=0x50; 

PCON=0x00; 

TH1=0xfd; 

TL1=0xfd; 

PS=1; 

EA=1; 

EX1=0; 

ET0=1; 

ES=1; 

TR0=1; 

TR1=1; 

high_time=50; 

low_time=50; 

PIDInit ( &spid ); // Initialize Structure 

spid.Proportion = 10; // Set PID Coefficients 

spid.Integral = 8; 

spid.Derivative =6; 

spid.SetPoint = 100; // Set PID Setpoint 

while(1) 

  if(plus==0) 

  { 

   EA=0; 

   for(a=0;a<5;a++) 

    for(b=0;b<102;b++){} 

   if(plus==0) 

   { 

    set_temper++; 

    flag=0; 

   } 

  } 

  else if(subs==0) 

  { 

   for(a=0;a<5;a++) 

    for(b=0;a<102;b++){} 

   if(subs==0) 

   { 

    set_temper--; 

    flag=0; 

   } 

  } 

  else if(stop==0) 

  { 

   for(a=0;a<5;a++) 

    for(b=0;b<102;b++){} 

   if(stop==0) 

   { 

    flag=0; 

    break; 

   } 

   EA=1; 

  } 

  get_temper(); 

  b=temper; 

  if(flag_2==1) 

  {

   a=b;

  } 

  if((abs(a-b))>5) 

  {

   temper=a;

  } 

  else 

  {  

   temper=b;

  } 

  a=temper; 

  flag_2=0; 

  if(++count1>30) 

  { 

   display(); 

   count1=0; 

  } 

  compare_temper(); 

TR0=0; 

z=1; 

while(1) 

  EA=0; 

  if(stop==0) 

  { 

   for(a=0;a<5;a++) 

    for(b=0;b<102;b++){} 

   if(stop==0) 

   disp_1(phil); 

   // break; 

  } 

  EA=1; 

}


Reference address:Program of water tank temperature PID control system designed by C51 microcontroller, PID control program

Previous article:51 microcontroller learning: light up the first LED
Next article:The design of 51 microcontroller to display 0-7 in sequence on 8-bit digital tube

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号