Project: Temperature Monitoring System with LCD Display Using PIC16F877A
Project: Temperature Monitoring System with LCD Display Using PIC16F877A a7d7bb61 2ced 42fb 822e a39536e5

Project: Temperature Monitoring System with LCD Display Using PIC16F877A

1. Introduction

This project demonstrates how to interface an LM35 temperature sensor with a PIC16F877A microcontroller and display the temperature readings on a 16×2 LCD. The system continuously monitors the temperature and updates the display in real time.

2. Learning Objectives

By completing this project, you will:

  • Understand ADC (Analog-to-Digital Conversion) in PIC microcontrollers.
  • Learn how to interface an LCD with a PIC16F877A.
  • Work with an LM35 temperature sensor to measure temperature.
  • Develop and debug embedded C code using MPLAB X and the XC8 compiler.

3. Components and Tools Required

Hardware Components:

  • PIC16F877A microcontroller
  • LM35 temperature sensor
  • 16×2 LCD display
  • 10kΩ potentiometer (for LCD contrast adjustment)
  • 10kΩ resistor (pull-down resistor for ADC stability)
  • Crystal oscillator (20MHz) (for stable clock frequency)
  • Two 22pF capacitors (for oscillator stabilization)
  • 330Ω resistor (for LCD backlight control)
  • Breadboard and jumper wires

Software Tools:

  • MPLAB X IDE (for writing and compiling the code)
  • XC8 Compiler (for compiling C programs)
  • PICkit Programmer (for burning the code to PIC16F877A)

4. Circuit Connections

The key circuit connections are as follows:

  • LM35 sensor:
    • VCC → 5V
    • GND → Ground
    • VOUT → RA0 (AN0) of PIC16F877A (ADC input)
  • 16×2 LCD (in 4-bit mode):
    • RS (Register Select) → RD0
    • EN (Enable) → RD1
    • D4-D7 (Data Pins) → RD4-RD7
    • VEE (Contrast Pin) → Center pin of 10kΩ potentiometer
    • VSS (GND) & VDD (Power) → GND & 5V
  • Oscillator Circuit:
    • 20MHz crystal oscillator connected to OSC1 (Pin 13) and OSC2 (Pin 14)
    • 22pF capacitors between crystal terminals and ground

5. Code Implementation (MPLAB XC8)

This program reads the LM35 sensor’s output, converts it to a temperature value, and displays it on the 16×2 LCD.

#include <xc.h>
#include <stdio.h>

#define _XTAL_FREQ 20000000  // Define crystal frequency
#define RS RD0
#define EN RD1
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7

// Function prototypes
void ADC_Init();
unsigned int ADC_Read(unsigned char);
void LCD_Init();
void LCD_Command(unsigned char);
void LCD_Char(unsigned char);
void LCD_String(const char *);
void LCD_Clear();
void LCD_Set_Cursor(unsigned char, unsigned char);

void main() {
    unsigned int adc_value;
    float temperature;
    char buffer[16];

    TRISA = 0xFF; // Configure PORTA as input (ADC)
    TRISD = 0x00; // Configure PORTD as output (LCD)
    ADC_Init();
    LCD_Init();

    while(1) {
        adc_value = ADC_Read(0); // Read from AN0
        temperature = (adc_value * 4.88) / 10.0; // Convert ADC value to temperature (°C)

        LCD_Clear();
        LCD_Set_Cursor(1,1);
        LCD_String("Temp: ");
        sprintf(buffer, "%.2f C", temperature);
        LCD_String(buffer);
        
        __delay_ms(1000); // Refresh every second
    }
}

// Initialize ADC Module
void ADC_Init() {
    ADCON0 = 0x41;  // Enable ADC, select channel 0
    ADCON1 = 0x80;  // Set result format (right justified)
}

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

// Initialize LCD
void LCD_Init() {
    LCD_Command(0x02); // Initialize LCD in 4-bit mode
    LCD_Command(0x28); // Function set
    LCD_Command(0x0C); // Display ON, Cursor OFF
    LCD_Command(0x06); // Entry mode
    LCD_Command(0x01); // Clear display
}

// Send Command to LCD
void LCD_Command(unsigned char cmd) {
    RS = 0;
    D4 = (cmd >> 4) & 1;
    D5 = (cmd >> 5) & 1;
    D6 = (cmd >> 6) & 1;
    D7 = (cmd >> 7) & 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(unsigned char data) {
    RS = 1;
    LCD_Command(data);
}

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

// Clear LCD
void LCD_Clear() {
    LCD_Command(0x01);
}

// Set Cursor Position
void LCD_Set_Cursor(unsigned char row, unsigned char column) {
    unsigned char pos[] = {0x80, 0xC0}; // Line 1 & 2
    LCD_Command(pos[row-1] + (column-1));
}

6. Troubleshooting Guide

LCD Not Displaying Anything:

  • Check if the contrast potentiometer is adjusted properly.
  • Ensure all wiring connections to the LCD are correct.

Incorrect Temperature Readings:

  • Verify the LM35 connections (VCC, GND, VOUT).
  • Check if ADC conversion formula is correct.

No ADC Output:

  • Ensure ADC module is enabled properly in the code (ADCON0, ADCON1).
  • Confirm RA0 is set as an input in TRISA = 0xFF.

LCD Shows Garbage Characters:

  • Check if LCD initialization sequence is followed properly.
  • Add delays (__delay_ms(1)) between LCD commands to stabilize communication.

7. Possible Extensions

  • Add a buzzer to alert when temperature exceeds a predefined threshold.
  • Display temperature in Fahrenheit alongside Celsius.
  • Store temperature data in EEPROM for logging and retrieval.
  • Implement a wireless transmission system using Bluetooth or RF modules to send temperature data to a remote system.

This project is a great introduction to ADC interfacing, LCD handling, and embedded C programming for PIC microcontrollers. Let me know if you need any modifications or explanations. 🚀