Temperature controller using Microchip PIC16F877A Microcontroller


In continuously monitoring the surrounding temperature of industrial applications ‘Temperature Monitoring Control System’ play vital role. A simple prototype of such system has been designed. The system uses the temperature sensor LM35, PIC16F877A microcontroller and level converter IC MAX232. The controller reads the temperature sensor data and after calibration the temperature is displayed in the HyperTerminal.

Specification for temperature controller using PIC16F877A

Sample specification for the prototype development:

  • The prototype should maintain the temperature within 30ºC to 40ºC.

  • If temperature exceeds 40ºC then the system should switch ON LED.

  • If temperature falls bellow 30ºC then the system should switch OFF LED.

  • If temperature is in between 30ºC to 40ºC then the LED should BLINK. Blinking rate can be chosen appropriately.

  • The sensor data as well as the temperature should be displayed on HyperTerminal of the computer for every 0.5seconds.


Hardware design for temperature controller using PIC16F877A


The schematic diagram of the hardware required to implement this prototype is given in Figure (1.The temperature sensor used is LM35. It has a resolution of 10mV/ºC when used without any external circuitry or components. PIC 16F877A is used to implement the controller software. Temperature sensor has been connected to the channel zero of ADC. Microcontroller processes the data and sends to its serial port. Configuration of ADC and serial port features of microcontroller are explained in software section. To make serial data of controller compatible to the RS232 protocol level converter IC MAX232 is used. Reset button provides reset option for microcontroller.




Figure (1)Schematic of Temperature Monitoring and Control System


Algorithm for temperature controller using PIC16F877A

Algorithm of the software is as follows:

S.1) Intialize controller:I/O ports, A/D pins, serial port, interrupts

S.2) Initialize timer counter, load timer, enable timer; wait till timer delay is over.

S.3) Enable A/D conversion.

S.4) Read A/D value; calibrate the obtained digital value to the temperature.

S.5) If temperature is less than 30ºC set low_temp_flag else if temperature is more than 40ºC then set high_temp_flag else clear both the flags to indicate that temperature is in between 30ºC and 40ºC.

S.6) If low_temp_flag is set switch off LED else if high_temp_flag is set then switch on LED else if both flags are clear then toggle LED.

S.7) Goto the step S.1

Flag technique used in this software algorithm helps to upgrade the software and also to change the temperature range easily.


Software for temperature controller using PIC16F877A

Software is written in C language and compiled using MikroC compiler. Software is given bellow. ‘If’ loop is generally used in the software. Less number of ASM code is generated with this compared to the ‘switch’ or ‘while’ or ‘for’. In embedded applications ‘if’ loop is considered to be more efficient than any other loop. The program utilizes 343(4%) bytes of program memory and 44(11%) data RAM. (Built in functions are considered). If floating-point number (0.49) is used for calibration then the program memory location increases to around 700bytes (11%).

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//program for temperature monitoring system written for PIC16F877A //

//author: keshava murali //

//version1 //

//bellow 30ºC LED switches OFF //above 40ºC LED switches ON //

//between 30ºC and 40ºC LED toggles //

//timer delay~0.5sec //

//9/11/07 //

// Compiler: MikroC for PIC - V. 5.0.0.3 //

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define LED PORTB.F1 //LED port pin

#define max_count 15

#define low_temp 30 //define lower temperature range

#define high_temp 40 //define higher temperature range

//Function declarations

void send_data(unsigned char *p,unsigned char no_of_bytes);

unsigned char hex_to_ascii(unsigned char number);

//global variable declarations

unsigned short int timer_counter=0;

unsigned char mes_temp[]={"temp:"},mes_sensor[]={"sdata: "};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//timer 0 ISR; increments timer_counter ; reinitializes TMR0 //

//input: none output: none affected: timer_counter, TMR0,INTCON //

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void interrupt() //timer0 interrupt

{

timer_counter++; //increment counter

TMR0 = 96; //reinitialize TMR0 register

INTCON.TMR0IF=0; //clear timer0 overflow interrupt flag bit

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////main program starts here; reads ADC channel 0; calibrates the sensor data; //

////sends to serial port //

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void main(void)

{

unsigned char sensor_data,sensor_data1,sensor_data2,high_temp_flag,low_temp_flag,med_temp_flag,i;

TRISA=0xFF; //configure PORTA as input

TRISB=0; //configure PORTB as output

PORTA=0; //clear PORTA

PORTB=0; //clear PORTB

Usart_Init(9600); //initialize serial port using built in function

//if built in function is not used then use bellow commented //codes to initialize serial port

//SPBRG=103; //for 9600 baud rate (with 4MHz)

//TXSTA=0x22; //8 bit transmission, asynchronous, low baud rate, no parity

//RCSTA=0x90; //8 bit receive, enable serial port, no parity

//PIE1.RCIE=1; //enable receive interrupt

//PIE1.TXIE=1; //enable transmission interrupt

//Configure A/D

ADCON0=0x80; //Fosc/32, AN0, A/D disabled

ADCON1=0x80; //right justified, Fosc/32, analog inputs

ADCON0.ADON=1; //enable ADC module

OPTION_REG=0b00000111; //disable portb pullup, -ve edge, internal clock, increment

//on +ve edge, prescalar-0:256

INTCON.TMR0IE=1; //enable timer0 interrupt

INTCON.PEIE=1; //enable peripheral interrupts

INTCON.GIE=1; //enable global interrupt

for(;;) //infinite loop

{

INTCON.TMR0IE=1; //enable timer 0 interrupt

while(timer_counter!=max_count) //timer0 delay; wait till delay elapsed

{asm nop;}

timer_counter=0; //delay over; reinitialize counter

//Delay_ms(450); //without timer delay we can use built in delay function

sensor_data=Adc_Read(0); // read A/D using built in function

// if you don’t want to use built in function then use //bellow commented code

//ADCON0.GO=1; //start A/D conversion

//while(ADCON0.GO){} //wait till A/D conversion is over (1.6µS )

//sensor_data=ADRESL; //get ADC data; lower byte is sufficient

for(i=0;i<=5;i++) //send message to serial port

{Usart_Write(mes_sensor[i]);}

//send_data(&mes_sensor,sizeof(mes_temp)); //no built in function-use this function

sensor_data1=sensor_data/2; //calibrate sensor data

sensor_data2=sensor_data1; //temporarily store calibrated temperature

sensor_data1=hex_to_ascii((sensor_data/10)); //do hex to ascii conversion of MSB digit

Usart_Write(sensor_data1); //send to serial port

//don’t want built in function-use bellow two codes

//while(!TXIF){} //if transmit buffer is empty put data else wait

//TXREG=sensor_data1; //send to serial port

sensor_data1=hex_to_ascii((sensor_data%10));//hex to ascii conversion of LSB digit

Usart_Write(sensor_data1); // send to serial port

//while(!TXIF){} //if transmit buffer is empty put data else wait

//TXREG=sensor_data1; //send to serial port

if(sensor_data2>high_temp) //check for temperature range

{high_temp_flag=0xFF; //if temperature > 40ºC set high_temp_flag

low_temp_flag=0;} //clear low_temp_flag

else if(sensor_data2

{low_temp_flag=0xFF; //if temperature <>

high_temp_flag=0;} //clear high_temp_flag

else

{low_temp_flag=0;

high_temp_flag=0;} //to avoid false triggering of LED clear both temp flags

if(high_temp_flag==0xFF) //check flag conditions;

LED=1; //if high_temp_flag is set switch ON LED

//PORTB.F1=1;

else if(low_temp_flag==0xFF) //if low_temp_flag is set switch OFF LED

LED=0;

//PORTB.F1=0;

else //if temperature is in between 30ºC and 40ºC blink LED

LED=~LED; //toggle LED

//PORTB.F1= ~PORTB.F1;

for(i=0;i<=4;i++) //send temperature to serial port

{Usart_Write(mes_temp[i]);} //send message to serial port

//send_data(&mes_temp,sizeof(mes_temp)); //don’t want built in?-use this function

sensor_data1=hex_to_ascii((sensor_data2/10)); //hex to ASCII convesion of MSB digit

Usart_Write(sensor_data1); //send to serial port;

//while(!TXIF){} //if transmit buffer is empty put data else wait

//TXREG=sensor_data1; //send to serial port

sensor_data1=hex_to_ascii((sensor_data2%10));//hex to ASCII convesion of LSB digit

Usart_Write(sensor_data1); //send to serial port

//while(!TXIF){} //if transmit buffer is empty put data else wait

//TXREG=sensor_data1; //send to serial port

}

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//function to convert hex number to ASCII format //

//input: unsigned char hex number return: unsigned char ASCII equivalent //

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

unsigned char hex_to_ascii(unsigned char number)

{ //if hex number is 0 to 9 add 0x30

if(number<10)

number=number+0x30;

else //if hex number is A to F add 0x37

number=number+0x37;

return(number); //return ASCII equivalent

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//function to send a character to serial port //

//use this function if USART built in function is not used //

//input: starting address of the string, length of the string return: none //

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*

void send_data(unsigned char *p,unsigned char no_of_bytes)

{ unsigned char i;

for(i=0;i

{

while(!TXIF) {} //if transmission buffer is full wait

TXREG=*(p+i); //send character to serial port

}

}

*/

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Calibration

We know PIC16F877A ADC has 10-bit resolution. Thus for 0V we get count zero and for 5V we get count 1024. Hence for our application each bit represents 5/1024=4.9x10-3 mV/ºC. But LM35 has a resolution of 10mV/ºC. Therefore each bit of ADC represents (4.9x10-3)/10x10-3 =0.49V/ºC. Thus to get the exact value of temperature the ADC value has to be multiplied by 0.49. Since multiplication of this floating-point number consumes enormous memory area and also adds overhead of inefficient calculation we can approximate it to 0.5=1/2. Hence 2 in the program divide ADC value. This makes program more efficient, simpler with less program memory area.


Software Improvements

Improvements are possible to the prototype software given here. These improvements are necessary to convert the prototype into commercial product.

Accuracy

To get more accurate results we have to average the ADC value that has been not done in given program. A ‘jump’ in ADC and hence in temperature value may be seen due to this. But this requires more program memory, RAM and also little more complex logic.

User settable Temperature Range

Option should be provided to change the temperature range as per user requirement. The user should enter a command in HyperTerminal. After microcontroller receives this command it asks the user to enter the lower range. Then user has to enter the lower range. Similarly higher range is also entered. These new ranges are stored in the internal EEPROM of microcontroller. Whenever microcontroller resets, it reads the lower range and higher range from the EEPROM and compares instantaneous temperature value with this value.

Data logging Facility

Temperature related events and data could be stored in an external EEPROM interfaced to microcontroller using I2C bus protocol. Whenever the temperature crosses range on both lower and higher side, the temperature can be logged to EEPROM. The logging can be performed for particular interval of time. In later time this logged data can be read by a data logger and transferred to computer for analysis through RS232 interface.

10 comments:

  1. i want to design digital thermometer. i think i can use this concept.

    ReplyDelete
  2. Whatever i have given here is educational kind of project.....code has to be robust to make it real time...all the best !

    ReplyDelete
  3. How About PIC16f877A with Ultra Sonic Sensor?
    Please give me a Circuit and code about that. Thank U

    ReplyDelete
  4. can you detailed about the components...please...

    ReplyDelete
  5. congratulations, pic 16f87A is the most usefull mc of microchip family.... but where is the headear of progam?

    ReplyDelete
  6. Please send me the code
    my mail id is: mail2vicky.7@gmail.com

    ReplyDelete
  7. can i use this code for a project that uses lm 35 for sensing temperature.if not,can u please send me the code that is compatible for 877 pic and lm 35.my mail id is ashiquemat2000@gmail.com

    ReplyDelete
  8. good blog visit
    http://search4electronics2013.blogspot.com/

    ReplyDelete
  9. i want to measure the temperature for 24/7,can i use this..???

    ReplyDelete
  10. hi thank you ,i have some problem my project how to control abut green glass (control the temperature the temperature input by using keypad 3*4 with using pic 16f877a and lcd 2*16 my mail arian_dlm@yahoo.com

    ReplyDelete

Your Comments... (comments are moderated)

Search This Blog

Loading...