PIC Microcontroller Project: Temperature Monitoring System with LCD Display
PIC Microcontroller Project: Temperature Monitoring System with LCD Display image 1

PIC Microcontroller Project: Temperature Monitoring System with LCD Display

1. Introduction

This project demonstrates how to design a temperature monitoring system using a PIC microcontroller, a temperature sensor (LM35), and a 16×2 LCD display. The system measures temperature in real-time and displays it on the LCD. It can be used in applications like environmental monitoring, industrial temperature control, and home automation systems.


2. Learning Objectives

  • Understand how to interface an LM35 temperature sensor with a PIC microcontroller.
  • Learn how to configure and use the ADC (Analog-to-Digital Converter) module in PIC.
  • Interface and program a 16×2 LCD display to show real-time data.
  • Gain practical skills in debugging and troubleshooting embedded systems.

3. Tools and Components

  • Hardware:
    • PIC microcontroller (e.g., PIC16F877A or PIC16F887)
    • LM35 temperature sensor
    • 16×2 LCD display
    • 10kΩ potentiometer (for LCD contrast adjustment)
    • 10µF and 0.1µF capacitors
    • 7805 voltage regulator (for 5V supply)
    • Resistors (330Ω for LCD backlight)
    • Breadboard and connecting wires
    • Power supply (5V)
    • Oscilloscope or multimeter (for testing)
  • Software:
    • MPLAB X IDE
    • XC8 compiler
    • Proteus (optional, for simulation)

4. Background/Definitions

  • LM35 Sensor: A precision temperature sensor with an analog voltage output proportional to the temperature (10mV per °C).
  • ADC: Converts the analog signal from LM35 into a digital value that the PIC microcontroller can process.
  • LCD Display: A 16×2 alphanumeric display used for outputting text or numeric data.

5. Step-by-Step Guide

Step 1: Circuit Design

  1. Connect the LM35 sensor:
    • VCC pin to 5V.
    • GND pin to GND.
    • Output pin to the analog input channel (e.g., RA0/AN0) of the PIC.
  2. Connect the LCD:
    • Data pins (D4–D7) to PORTD (e.g., RD0–RD3).
    • Control pins:
      • RS to RB0
      • RW to GND
      • E to RB1
    • Adjust contrast using a 10kΩ potentiometer connected to the VEE pin of the LCD.
  3. Add bypass capacitors (10µF and 0.1µF) near the power pins of the PIC for stability.
  4. Ensure a regulated 5V power supply to the circuit using a 7805 voltage regulator.

Circuit Diagram: (Describe connections or provide visual details to recreate the setup accurately.)


Step 2: Programming

Here’s the annotated source code:

cCopy code#include <xc.h>
#define _XTAL_FREQ 8000000  // Define oscillator frequency for delay

// Configuration bits
#pragma config FOSC = HS   // High-speed oscillator
#pragma config WDTE = OFF  // Watchdog Timer disabled
#pragma config PWRTE = ON  // Power-up Timer enabled
#pragma config BOREN = ON  // Brown-out Reset enabled
#pragma config LVP = OFF   // Low-Voltage Programming disabled
#pragma config CPD = OFF   // Data EEPROM memory code protection disabled
#pragma config WRT = OFF   // Flash Program Memory Write Protection off
#pragma config CP = OFF    // Flash Program Memory Code Protection off

// Function prototypes
void ADC_Init();
unsigned int ADC_Read(unsigned char channel);
void LCD_Init();
void LCD_Command(unsigned char cmd);
void LCD_Char(unsigned char data);
void LCD_String(const char *str);
void Display_Temperature(unsigned int temp);

void main() {
    unsigned int adcValue;
    float temperature;
    
    ADC_Init();      // Initialize ADC
    LCD_Init();      // Initialize LCD
    
    while(1) {
        adcValue = ADC_Read(0);  // Read analog value from channel 0
        temperature = adcValue * 0.488;  // Convert ADC value to temperature (LM35 scale: 10mV/°C)
        
        // Display temperature on LCD
        LCD_Command(0x80);  // Move cursor to first line
        LCD_String("Temp: ");
        Display_Temperature((unsigned int)temperature);
        LCD_String(" C");
        
        __delay_ms(1000);  // Refresh every second
    }
}

void ADC_Init() {
    ADCON0 = 0x01;  // ADC enabled, channel 0 selected
    ADCON1 = 0x0E;  // Configure AN0 as analog, others as digital
    ADRESH = 0;     // Clear ADC result registers
    ADRESL = 0;
}

unsigned int ADC_Read(unsigned char channel) {
    ADCON0 &= 0xC5;  // Clear previous channel selection
    ADCON0 |= (channel << 3);  // Select ADC channel
    __delay_ms(2);  // Acquisition time delay
    GO_nDONE = 1;   // Start ADC conversion
    while (GO_nDONE);  // Wait for conversion to complete
    return ((ADRESH << 8) + ADRESL);  // Return 10-bit ADC result
}

void LCD_Init() {
    // Initialize LCD in 4-bit mode
    LCD_Command(0x02);
    LCD_Command(0x28);
    LCD_Command(0x0C);
    LCD_Command(0x06);
    LCD_Command(0x01);
}

void LCD_Command(unsigned char cmd) {
    PORTD = (cmd & 0xF0);  // Send upper nibble
    RB0 = 0;  // RS = 0 for command
    RB1 = 1;  // Enable high
    __delay_ms(1);
    RB1 = 0;  // Enable low
    
    PORTD = ((cmd << 4) & 0xF0);  // Send lower nibble
    RB1 = 1;  // Enable high
    __delay_ms(1);
    RB1 = 0;  // Enable low
}

void LCD_Char(unsigned char data) {
    PORTD = (data & 0xF0);  // Send upper nibble
    RB0 = 1;  // RS = 1 for data
    RB1 = 1;  // Enable high
    __delay_ms(1);
    RB1 = 0;  // Enable low
    
    PORTD = ((data << 4) & 0xF0);  // Send lower nibble
    RB1 = 1;  // Enable high
    __delay_ms(1);
    RB1 = 0;  // Enable low
}

void LCD_String(const char *str) {
    while (*str) {
        LCD_Char(*str++);
    }
}

void Display_Temperature(unsigned int temp) {
    LCD_Char((temp / 100) + '0');  // Hundreds place
    temp %= 100;
    LCD_Char((temp / 10) + '0');   // Tens place
    LCD_Char((temp % 10) + '0');   // Units place
}

6. Testing and Debugging Tips

  1. LCD Display Issues:
    • Ensure the contrast potentiometer is adjusted for clear visibility.
    • Verify correct wiring for RS, RW, E, and data pins.
  2. ADC Reading Incorrect:
    • Check the voltage at the LM35 output using a multimeter.
    • Ensure the ADC reference voltage is stable and matches the configured range.
  3. Temperature Value Incorrect:
    • Verify the LM35 is connected correctly.
    • Check the conversion formula (0.488 factor may vary slightly based on ADC resolution and Vref).
  4. System Not Powering On:
    • Ensure the 7805 regulator output is 5V.
    • Use bypass capacitors to filter noise in the power supply.

7. Extensions

  • Add a buzzer to alert when the temperature exceeds a set threshold.
  • Use a serial interface (UART) to log temperature data to a PC.
  • Replace the LM35 with a digital sensor like DHT11 or DS18B20.
  • Implement a graphical user interface using an OLED display for advanced monitoring.

This complete guide ensures a smooth learning experience while building a robust temperature monitoring system.