
π‘ Project: Digital Thermometer Using PIC16F877A and LM35 Sensor
1. Introduction
This project demonstrates how to read analog temperature data from an LM35 sensor, convert it to digital using the PIC16F877A’s ADC, and display the temperature in Celsius on a 16×2 LCD.
Real-world applications:
Used in HVAC systems, greenhouses, weather stations, and industrial temperature monitors.
2. Learning Objectives
By completing this project, you’ll:
- Learn to interface analog sensors with a PIC microcontroller.
- Understand how to configure and use the ADC module.
- Gain hands-on experience with 16×2 LCDs in 4-bit mode.
- Develop confidence using MPLAB X IDE and XC8 for embedded C.
3. Tools and Components
Hardware:
- PIC16F877A Microcontroller
- LM35 Temperature Sensor
- 16×2 Alphanumeric LCD Display
- 10K Potentiometer (for LCD contrast)
- 0.1 Β΅F Capacitor (for LM35 decoupling)
- Breadboard and Jumper Wires
- 5V Regulated Power Supply
Software:
- MPLAB X IDE
- XC8 Compiler
- Proteus (for optional simulation)
4. Background/Definitions
- ADC (Analog-to-Digital Converter): Converts analog input voltage (0β5V) into a digital value (0β1023 for 10-bit resolution).
- LM35: Analog temperature sensor that outputs 10 mV per Β°C, meaning 250 mV = 25Β°C.
- PIC16F877A: A widely-used 8-bit PIC MCU with built-in ADC, UART, and timers.
5. Step-by-Step Guide
A. Circuit Wiring
- LM35 Sensor:
- Vout β RA0 (AN0)
- Vcc β +5V
- GND β GND
- 16×2 LCD (4-bit mode):
- RS β RD0
- E β RD1
- D4 β RD2
- D5 β RD3
- D6 β RD4
- D7 β RD5
- VSS β GND, VDD β +5V
- VEE (contrast) β Middle pin of 10K potentiometer (other pins to VCC and GND)
- Add a 0.1 Β΅F capacitor between LM35 Vout and GND for stable readings.
B. Embedded C Code (XC8 Compiler)
#include <xc.h>
#include <stdio.h>
#include "lcd.h" // Custom 4-bit LCD driver
#define _XTAL_FREQ 20000000
// CONFIGURATION BITS
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
void ADC_Init() {
ADCON1 = 0x80; // Right justified, Vref=Vdd
ADCON0 = 0x41; // ADC on, channel 0 (AN0)
}
unsigned int ADC_Read() {
GO_nDONE = 1;
while(GO_nDONE); // Wait for ADC conversion to finish
return ((ADRESH << 8) + ADRESL); // Combine high and low bytes
}
void main() {
unsigned int adc_value;
float temp_c;
char buffer[16];
TRISA = 0x01; // RA0 input
TRISD = 0x00; // LCD pins as output
LCD_Init();
ADC_Init();
LCD_Clear();
LCD_Set_Cursor(1, 1);
LCD_Write_String("Temp: ");
while(1) {
adc_value = ADC_Read();
temp_c = (adc_value * 5.0 / 1023.0) * 100;
sprintf(buffer, "%.2f C", temp_c);
LCD_Set_Cursor(1, 7);
LCD_Write_String(buffer);
__delay_ms(1000);
}
}
Note: Ensure the
lcd.handlcd.cdriver files match your LCD pin setup.
6. Testing and Debugging Tips
When working with microcontroller projects, hardware miswiring and software misconfiguration are common. Here’s a list of typical issues and how to resolve them.
Issue 1: LCD Displays Nothing or Garbled Characters
- Cause: Incorrect wiring or LCD not initialized correctly.
- Fix: Verify that RS, E, and D4βD7 are correctly wired. Adjust the potentiometer connected to VEE for proper contrast. Use a known-good βHello Worldβ LCD test to validate functionality.
Issue 2: Temperature Always Reads 0.00Β°C
- Cause: Sensor not connected, or ADC misconfigured.
- Fix: Ensure LM35 is wired correctly and Vout is connected to RA0. Confirm that
ADCON0andADCON1registers are properly configured.
Issue 3: Temperature Reading Fluctuates or Is Inaccurate
- Cause: Electrical noise or calculation errors.
- Fix: Place a 0.1 Β΅F capacitor between Vout and GND of LM35. Check the conversion formula:
temp_c = (adc_value * 5.0 / 1023.0) * 100;
Issue 4: LCD Updates Incorrectly or Lags
- Cause: Too many refreshes or incorrect delays.
- Fix: Insert appropriate delays after LCD updates (
__delay_ms(1000)is used here for 1-second intervals).
7. Extensions and Enhancements
Take the project further with these creative ideas:
- Display in Fahrenheit:
Add a conversion:temp_f = (temp_c * 9 / 5) + 32; - Overheat Alarm:
Add a buzzer that triggers when temperature exceeds a threshold. - Data Logging:
Store temperature data to EEPROM or send via UART to a computer. - Wireless Transmission:
Use an ESP8266 or NRF24L01 to transmit data wirelessly. - Improve UI:
Use an I2C LCD module to reduce wiring and use fewer I/O pins.