Temperature-Controlled Fan using PIC16F877A and LM35 Sensor
Temperature-Controlled Fan using PIC16F877A and LM35 Sensor file TLfrqvR6vNMdh73YD4h73P

Temperature-Controlled Fan using PIC16F877A and LM35 Sensor

1. Introduction

This project demonstrates how to control a fan’s speed using a PIC16F877A microcontroller and a PWM (Pulse Width Modulation) technique based on the temperature measured by an LM35 temperature sensor. It’s a practical application of temperature monitoring and control commonly used in HVAC systems, server cooling, and smart appliances.

Project Overview:

  • The LM35 sensor measures the temperature.
  • The PIC16F877A reads the sensor value and converts it into a PWM signal.
  • The PWM output controls the speed of a DC fan.

2. Learning Objectives

By the end of this project, you will:

  • Understand how to use ADC (Analog-to-Digital Converter) on a PIC microcontroller.
  • Implement PWM for speed control.
  • Learn how to interface an LM35 temperature sensor with a PIC microcontroller.
  • Develop robust code with error handling and debugging.

3. Tools and Components

Hardware:

  • PIC16F877A Microcontroller
  • LM35 Temperature Sensor
  • 12V DC Fan
  • L293D Motor Driver IC (to drive the fan)
  • 16×2 LCD (optional for temperature display)
  • Breadboard and connecting wires
  • Power supply (5V and 12V)
  • Crystal oscillator (20 MHz)
  • Capacitors (22pF, 100nF)
  • Resistors (1kΩ, 10kΩ)

Software:

  • MPLAB X IDE
  • XC8 Compiler
  • PICkit 3 Programmer (for uploading the code)

4. Background and Key Concepts

LM35 Temperature Sensor

The LM35 is an analog temperature sensor with an output voltage proportional to the temperature. It outputs 10 mV/°C, which means at 25°C, the output voltage is 250 mV.

PWM (Pulse Width Modulation)

PWM is a technique used to control the speed of motors by adjusting the duty cycle of a signal. A higher duty cycle means more power to the fan, increasing its speed.

PIC16F877A

A popular 8-bit microcontroller with built-in ADC (10-bit), multiple PWM channels, and plenty of I/O pins, making it suitable for embedded projects.


5. Step-by-Step Guide

Step 1: Circuit Diagram

Connection Overview:

  1. LM35 Sensor
    • VCC → 5V
    • GND → GND
    • Output → RA0 (AN0/ADC Channel 0 on PIC16F877A)
  2. DC Fan (connected to L293D motor driver)
    • Enable pin of L293D → CCP1 (RC2/PWM output of PIC)
    • Input pins of L293D connected to 12V DC supply and GND
  3. LCD Display (optional for temperature readout)
    • RS → RC0, EN → RC1, D4-D7 → RD4-RD7

Step 2: PIC16F877A Configuration

  • Use the internal ADC to read the analog value from the LM35.
  • Convert the ADC result to a temperature value.
  • Generate a PWM signal with the duty cycle proportional to the temperature.

Step 3: Code with Detailed Comments

#include <xc.h>

// 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 disabled
#pragma config CP = OFF // Code protection disabled

#define _XTAL_FREQ 20000000 // 20 MHz crystal oscillator frequency

// Function Prototypes
void ADC_Init();
unsigned int ADC_Read(unsigned char channel);
void PWM_Init();
void PWM_Set_Duty(unsigned int duty);

void main() {
unsigned int adc_value = 0;
unsigned int temperature = 0;
unsigned int pwm_duty = 0;

// Initialize peripherals
ADC_Init();
PWM_Init();

while(1) {
// Read temperature from LM35 (connected to AN0)
adc_value = ADC_Read(0); // Read ADC value from channel 0
temperature = (adc_value * 500) / 1023; // Convert ADC value to temperature in °C

// Set PWM duty cycle based on temperature
pwm_duty = (temperature * 1023) / 100; // Scale temperature to duty cycle (0-100%)
if (pwm_duty > 1023) pwm_duty = 1023; // Limit duty cycle to 100%

PWM_Set_Duty(pwm_duty); // Update PWM duty cycle

__delay_ms(500); // Wait for 500 ms
}
}

// ADC Initialization
void ADC_Init() {
ADCON0 = 0x41; // ADC ON, Fosc/8
ADCON1 = 0x80; // Right justified result
}

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

// PWM Initialization
void PWM_Init() {
PR2 = 0xFF; // Set PWM frequency
T2CON = 0x04; // Timer2 ON, Prescaler = 1
CCP1CON = 0x0C; // Configure CCP1 module for PWM mode
CCPR1L = 0x00; // Initial duty cycle = 0
}

// Set PWM Duty Cycle (0-1023)
void PWM_Set_Duty(unsigned int duty) {
if (duty > 1023) duty = 1023; // Limit duty cycle to 10 bits
CCPR1L = duty >> 2; // Set the high 8 bits of duty cycle
CCP1CONbits.DC1B = duty & 0x03; // Set the lower 2 bits
}

6. Testing and Debugging Tips

  1. Verify Power Connections:
    Ensure the PIC microcontroller and peripherals are receiving the correct voltage. Use a multimeter to confirm.
  2. Check ADC Reading:
    If the temperature seems incorrect, verify the ADC conversion by checking the LM35 output voltage directly.
  3. PWM Output:
    Use an oscilloscope to check the PWM signal on the CCP1 pin. Ensure the duty cycle changes with temperature.
  4. LCD Display (if used):
    If the temperature doesn’t display, check the data and control pin connections.
  5. Fan Speed:
    Confirm the L293D is properly connected. Ensure the 12V supply is adequate for the fan.

7. Extensions

  1. Add Hysteresis: Prevent rapid fan speed changes by implementing hysteresis in temperature readings.
  2. Data Logging: Store temperature data over time using an external EEPROM.
  3. Bluetooth Control: Add an HC-05 Bluetooth module to monitor temperature and control the fan remotely.
  4. Graphical Interface: Use a TFT screen for a more advanced UI.