You are on page 1of 10

Source: http://asicsoc.blogspot.com/2007/12/temperature-controllerusing-microchip.

html
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 30C to 40C.

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

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

If temperature is in between 30C to 40C 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 30C set low_temp_flag else if temperature is more than 40C then set
high_temp_flag else clear both the flags to indicate that temperature is in between 30C and 40C.
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 30C LED switches OFF //above 40C LED switches ON //
//between 30C and 40C 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 dont 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.6S )
//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
//dont 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 > 40C 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 30C and 40C 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)); //dont 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.

You might also like