Temperature Monitoring System using PIC16F877A and LM35
Temperature Monitoring System using PIC16F877A and LM35 file WTAF4etWcqUZMXh1ZvS3Gp

Temperature Monitoring System using PIC16F877A and LM35

1. Introduction

This project uses a PIC16F877A microcontroller and an LM35 temperature sensor to measure ambient temperature and display it on a 16×2 LCD. It can be used in home automation, weather stations, or industrial monitoring.

2. Learning Objectives

  • Learn ADC (Analog-to-Digital Conversion) in PIC microcontrollers.
  • Interface LM35 temperature sensor with a PIC MCU.
  • Display sensor values on a 16×2 LCD using 4-bit mode.
  • Understand troubleshooting techniques for embedded systems.

3. Tools and Components Required

Hardware:

  • PIC16F877A microcontroller
  • LM35 temperature sensor
  • 16×2 LCD display
  • Crystal oscillator (20MHz)
  • Capacitors (22pF x 2)
  • Resistors (1kΩ, 10kΩ for pull-up and contrast adjustment)
  • Potentiometer (10kΩ) – For LCD contrast
  • Power supply (5V DC)
  • Breadboard & jumper wires

Software:

  • MPLAB X IDE
  • XC8 Compiler
  • Proteus (optional for simulation)

4. Background & Key Concepts

LM35 Temperature Sensor

  • The LM35 is a precision temperature sensor with an output proportional to temperature (°C).
  • Output formula: Vout=10mV/°C×TemperatureV_{out} = 10mV/°C \times TemperatureVout​=10mV/°C×Temperature
  • Example: If Vout = 250mV, the temperature = 25°C.

Analog-to-Digital Conversion (ADC) in PIC16F877A

  • PIC16F877A has a 10-bit ADC, meaning the digital output range is 0-1023.
  • Conversion formula: Temperature=(ADC_value1023)×500Temperature = \left( \frac{ADC\_value}{1023} \right) \times 500Temperature=(1023ADC_value​)×500

5. Circuit Diagram Explanation

  • LM35 (Temperature Sensor) Connections:
    • VCC → 5V
    • GND → Ground
    • Vout → AN0 (RA0) of PIC (Analog Input)
  • 16×2 LCD Connections (4-bit mode):
    • RS → RD0, E → RD1, D4-D7 → RD2 to RD5
    • VSS → GND, VDD → 5V, RW → GND
    • Contrast (V0) → 10kΩ Potentiometer (middle pin)
  • Oscillator (20MHz) with Capacitors (22pF each) connected to OSC1 & OSC2 pins

6. Source Code (MPLAB X, XC8)

cCopyEdit#include <xc.h>
#define _XTAL_FREQ 20000000  // 20MHz Crystal Frequency

// LCD Pins
#define RS RD0
#define EN RD1
#define D4 RD2
#define D5 RD3
#define D6 RD4
#define D7 RD5

// Configuration Bits
#pragma config FOSC = HS    // High-speed Oscillator
#pragma config WDTE = OFF   // Watchdog Timer Off
#pragma config PWRTE = OFF  // Power-up Timer Off
#pragma config BOREN = ON   // Brown-out Reset On
#pragma config LVP = OFF    // Low Voltage Programming Off

// Function Prototypes
void LCD_Command(char);
void LCD_Char(char);
void LCD_Init();
void LCD_String(const char*);
void ADC_Init();
unsigned int ADC_Read(unsigned char);
void Display_Temperature();

void main() {
    TRISA = 0xFF;   // Set PORTA as input (for ADC)
    TRISD = 0x00;   // Set PORTD as output (for LCD)
    ADC_Init();     // Initialize ADC
    LCD_Init();     // Initialize LCD

    while (1) {
        Display_Temperature();
        __delay_ms(1000);  // Update every second
    }
}

// LCD Initialization
void LCD_Init() {
    LCD_Command(0x02); // 4-bit mode
    LCD_Command(0x28); // 2-line, 5x8 font
    LCD_Command(0x0C); // Display ON, Cursor OFF
    LCD_Command(0x06); // Auto Increment cursor
    LCD_Command(0x01); // Clear Display
    __delay_ms(2);
}

// Send Command to LCD
void LCD_Command(char cmd) {
    RS = 0;
    D4 = (cmd >> 4) & 1;
    D5 = (cmd >> 3) & 1;
    D6 = (cmd >> 2) & 1;
    D7 = (cmd >> 1) & 1;
    EN = 1; __delay_ms(1); EN = 0;

    D4 = cmd & 1;
    D5 = (cmd >> 1) & 1;
    D6 = (cmd >> 2) & 1;
    D7 = (cmd >> 3) & 1;
    EN = 1; __delay_ms(1); EN = 0;
}

// Send Character to LCD
void LCD_Char(char data) {
    RS = 1;
    LCD_Command(data);
}

// Display String on LCD
void LCD_String(const char* str) {
    while (*str) LCD_Char(*str++);
}

// Initialize ADC
void ADC_Init() {
    ADCON0 = 0x41;  // Enable ADC, Select Channel 0
    ADCON1 = 0xC0;  // Right Justified, Vref = VDD
}

// Read ADC Value
unsigned int ADC_Read(unsigned char channel) {
    ADCON0 &= 0xC5;  // Clear channel bits
    ADCON0 |= (channel << 3); // Select channel
    __delay_ms(2);
    GO_nDONE = 1;  // Start Conversion
    while (GO_nDONE);
    return ((ADRESH << 8) + ADRESL);
}

// Display Temperature on LCD
void Display_Temperature() {
    unsigned int adc_value = ADC_Read(0);
    float temperature = (adc_value * 500.0) / 1023.0;
    
    LCD_Command(0x80);
    LCD_String("Temp: ");
    
    int temp_int = (int)temperature;
    LCD_Char((temp_int / 10) + '0');
    LCD_Char((temp_int % 10) + '0');
    LCD_Char(223);  // Degree Symbol
    LCD_Char('C');
}

7. Testing and Troubleshooting Tips

Common Issues and Fixes:

LCD not displaying data:

  • Check contrast potentiometer (10kΩ).
  • Ensure RS, E, and Data pins are correctly wired.

Wrong temperature values displayed:

  • Check LM35 connections (VCC, GND, Vout to AN0).
  • Verify ADC conversion formula in the code.

Microcontroller not responding:

  • Ensure power supply is 5V.
  • Check oscillator and capacitor connections.

ADC not working:

  • Verify ADCON0 and ADCON1 register configurations.

8. Project Extensions

  • Add a buzzer if the temperature exceeds a threshold.
  • Use an EEPROM to log temperature data.
  • Implement serial communication (UART) to transmit data to a PC.

This project provides a complete embedded system using PIC16F877A, covering hardware, software, and debugging techniques. Let me know if you need modifications! 🚀