đź”§ Project Title: Temperature-Controlled Fan using PIC16F877A
đź”§ Project Title: Temperature-Controlled Fan using PIC16F877A

đź”§ Project Title: Temperature-Controlled Fan using PIC16F877A


đź§­ 1. Introduction

This project demonstrates how to automatically control a fan’s speed based on the ambient temperature using a PIC16F877A microcontroller and an LM35 temperature sensor. The fan will increase speed as the temperature rises — a concept commonly used in computers, HVAC systems, and other electronic cooling applications.


🎯 2. Learning Objectives

By completing this project, you will:

  • Understand analog-to-digital conversion (ADC) on the PIC16F877A.
  • Learn how to read temperature using an LM35 sensor.
  • Generate PWM (Pulse Width Modulation) signals using the CCP1 module.
  • Interface and control a DC fan using PWM and a motor driver.
  • Display real-time temperature on an LCD.
  • Gain experience with debugging real-time control systems.

đź§° 3. Tools and Components

Hardware Required:

  • PIC16F877A microcontroller
  • LM35 temperature sensor
  • 16×2 LCD display
  • 12V DC fan or 5V brushless motor
  • L293D motor driver or NPN transistor (e.g., TIP122)
  • 10k potentiometer (for LCD contrast)
  • 20 MHz crystal oscillator
  • Two 22pF capacitors
  • 10kΩ and 1kΩ resistors
  • Breadboard and jumper wires
  • Power supply (5V for PIC, 12V for fan)

Software Required:

  • MPLAB X IDE
  • XC8 compiler
  • Proteus (optional for simulation and visualization)

📚 4. Background and Key Concepts

LM35: This is a precision temperature sensor with linear output of 10 mV/°C. At 25°C, it outputs 250 mV.

ADC (Analog to Digital Converter): Converts analog voltages (from LM35) into 10-bit digital values for processing by the PIC microcontroller.

PWM (Pulse Width Modulation): A digital technique where the width of the ON pulse is varied to simulate analog control — used to adjust fan speed.

CCP1 Module: Capture/Compare/PWM module in the PIC16F877A. In PWM mode, it is used to generate precise pulse widths.


🛠️ 5. Step-by-Step Implementation

Circuit Setup:

  1. Connect the LM35 sensor’s Vout to RA0 (AN0) on the PIC.
  2. Connect the LCD to PORTD (data lines D0–D7), with RS and E connected to RC0 and RC1 respectively.
  3. Use a 10k potentiometer to adjust LCD contrast by connecting its wiper to the LCD’s VEE pin.
  4. Connect a 20MHz crystal to OSC1 and OSC2 with 22pF capacitors to ground.
  5. Connect the CCP1 pin (RC2) to the input of the motor driver (L293D or transistor base with resistor).
  6. The fan is powered from a 12V supply, and ground is shared with the PIC circuit.

MPLAB XC8 Code (Fully Commented):

#define _XTAL_FREQ 20000000  // Define crystal frequency

#include <xc.h>

#include <stdio.h>

// CONFIG BITS

#pragma config FOSC = HS, WDTE = OFF, PWRTE = OFF, CP = OFF, BOREN = ON, LVP = OFF

// Define control pins

#define RS RC0

#define EN RC1

#define LCD PORTD

void lcd_cmd(char cmd);

void lcd_data(char data);

void lcd_init();

void lcd_string(const char *str);

void adc_init();

int read_adc();

void pwm_init();

void set_pwm(unsigned int duty);

void main(void) {

    TRISA = 0x01;       // RA0 as input (LM35)

    TRISC = 0x00;       // RC0 and RC1 as output (LCD), RC2 for PWM

    TRISD = 0x00;       // LCD data lines as output

    lcd_init();         // Initialize LCD

    adc_init();         // Initialize ADC

    pwm_init();         // Initialize PWM module

    char buffer[16];

    while (1) {

        int adc_val = read_adc();              // Get ADC value from AN0

        float temp = adc_val * 0.488;          // Convert to Celsius (approx. 0.488 = (5V/1024)*100)

        lcd_cmd(0x80);                         // Move cursor to first line

        sprintf(buffer, “Temp: %.1f C  “, temp); // Format temperature string

        lcd_string(buffer);                   // Display temp on LCD

        if (temp < 25) {

            set_pwm(0);        // Fan OFF

        } else if (temp < 30) {

            set_pwm(200);      // Low speed

        } else if (temp < 35) {

            set_pwm(500);      // Medium speed

        } else {

            set_pwm(800);      // High speed

        }

        __delay_ms(1000);

    }

}

void lcd_init() {

    lcd_cmd(0x38);  // 2-line LCD

    lcd_cmd(0x0C);  // Display ON, cursor OFF

    lcd_cmd(0x06);  // Increment cursor

    lcd_cmd(0x01);  // Clear display

    __delay_ms(2);

}

void lcd_cmd(char cmd) {

    RS = 0;

    LCD = cmd;

    EN = 1; __delay_ms(2); EN = 0;

}

void lcd_data(char data) {

    RS = 1;

    LCD = data;

    EN = 1; __delay_ms(2); EN = 0;

}

void lcd_string(const char *str) {

    while (*str) lcd_data(*str++);

}

void adc_init() {

    ADCON1 = 0x80;     // Right justified, Vref=Vdd

    ADCON0 = 0x41;     // Channel 0 (AN0), ADC ON

}

int read_adc() {

    __delay_ms(2);     // Acquisition time

    GO_nDONE = 1;      // Start conversion

    while (GO_nDONE);  // Wait for completion

    return ((ADRESH << 8) + ADRESL); // Combine high and low bytes

}

void pwm_init() {

    PR2 = 255;             // Set PWM period

    CCP1CON = 0x0C;        // Set PWM mode

    T2CON = 0x04;          // Turn on Timer2

    TRISC2 = 0;            // Set CCP1 (RC2) as output

}

void set_pwm(unsigned int duty) {

    if (duty > 1023) duty = 1023;   // Cap at 10-bit max

    CCPR1L = duty >> 2;             // Upper 8 bits

    CCP1CON = (CCP1CON & 0xCF) | ((duty & 0x03) << 4); // Lower 2 bits into CCP1CON

}


🔍 6. Testing and Debugging Tips

  • If the LCD doesn’t display anything, verify contrast voltage and connections to PORTD and control lines. Adjust the potentiometer connected to the LCD’s VEE pin until characters are visible.
  • If the temperature value is incorrect, check that LM35 is correctly powered and measure its analog output with a multimeter. Confirm it’s around 250mV at 25°C.
  • If the fan does not run or change speed, inspect the PWM output on RC2 using an oscilloscope or multimeter in duty cycle mode. Also check the motor driver (L293D or transistor) wiring.
  • If the microcontroller isn’t running, confirm the oscillator is connected correctly and the configuration bits are set properly for HS mode.

🚀 7. Extensions

You can expand this project by:

  • Adding a push-button to manually override automatic fan control.
  • Interfacing with an SD card to log temperature data.
  • Using a Bluetooth module (like HC-05) to send temperature readings to a mobile device.
  • Adding a graphical display for more intuitive visuals.
  • Implementing a PID control algorithm for more precise fan speed regulation.