Project: Temperature-Controlled Fan using PIC16F877A
Project: Temperature-Controlled Fan using PIC16F877A

Project: Temperature-Controlled Fan using PIC16F877A


🧠 1. Introduction

In this project, we’ll design a Temperature-Controlled Fan using a PIC16F877A microcontroller. The system monitors temperature via an LM35 temperature sensor and automatically adjusts the fan speed based on the detected temperature using PWM (Pulse Width Modulation).

Real-world applications:

  • Smart cooling systems
  • Greenhouses
  • Computer cooling
  • Industrial equipment cooling

🎯 2. Learning Objectives

By completing this project, you will:

  • Understand ADC (Analog-to-Digital Conversion) in PIC microcontrollers.
  • Implement PWM to control motor speed.
  • Read data from a temperature sensor.
  • Integrate sensors and actuators.
  • Develop structured, well-commented code.

🛠️ 3. Tools and Components

Hardware:

  • PIC16F877A microcontroller
  • LM35 Temperature Sensor
  • 12V DC Fan
  • MOSFET (e.g., IRF540) for switching
  • 16×2 LCD Display (optional)
  • Resistors (1kΩ, 10kΩ)
  • Potentiometer (for LCD contrast)
  • Breadboard and connecting wires
  • 5V Regulated Power Supply

Software:

  • MPLAB X IDE
  • XC8 Compiler
  • PICKit3 or another PIC programmer

📚 4. Background/Definitions

  • ADC (Analog-to-Digital Converter): Converts analog signals like temperature into a digital form.
  • PWM (Pulse Width Modulation): Simulates analog output using digital pulses to control devices like motors.
  • LM35: A linear temperature sensor providing 10mV per °C.

🛠️ 5. Step-by-Step Guide

Circuit Wiring Overview

LM35 Temperature Sensor Connections:

  • Vcc pin connects to +5V.
  • GND pin connects to GND.
  • Output pin connects to RA0 (AN0) of PIC16F877A.

Fan and MOSFET Connections:

  • Fan positive terminal connects to 12V supply.
  • Fan negative terminal connects to Drain of MOSFET.
  • MOSFET Source connects to ground.
  • MOSFET Gate connects to CCP1 PWM output (RC2).

LCD Connections (optional for displaying temperature):

  • LCD RS pin connects to RC0.
  • LCD RW pin connects to RC1.
  • LCD E pin connects to RC2.
  • LCD Data pins (D4 to D7) connect to RD4 to RD7.
  • Potentiometer connects for LCD contrast control.

PIC Configuration Notes:

  • Use a 4MHz crystal oscillator.
  • Enable ADC module for analog input.
  • Configure CCP1 module for PWM output.

Source Code (With Full Comments)

// Configuration bits
#pragma config FOSC = HS     // High-Speed Oscillator
#pragma config WDTE = OFF    // Watchdog Timer Disable
#pragma config PWRTE = ON    // Power-up Timer Enable
#pragma config BOREN = ON    // Brown-out Reset Enable
#pragma config LVP = OFF     // Low-Voltage Programming Disable
#pragma config CPD = OFF     // Data EEPROM Memory Code Protection
#pragma config WRT = OFF     // Flash Program Memory Write Protection
#pragma config CP = OFF      // Flash Program Memory Code Protection

#include <xc.h>
#define _XTAL_FREQ 4000000  // Define crystal frequency

void ADC_Init();
unsigned int ADC_Read(unsigned char channel);
void PWM_Init();
void LCD_Init();
void LCD_Command(char cmd);
void LCD_Char(char data);
void LCD_String(const char *str);
void LCD_Clear();

void main() {
    unsigned int temp_raw;
    float temperature;
    int duty_cycle;
    
    ADC_Init();
    PWM_Init();
    LCD_Init();
    
    while(1) {
        temp_raw = ADC_Read(0);
        temperature = (temp_raw * 5.0 / 1023.0) * 100; // Convert ADC to Celsius

        LCD_Command(0x80);
        LCD_String("Temp: ");
        
        char buffer[5];
        sprintf(buffer, "%2.1f", temperature);
        LCD_String(buffer);
        LCD_String("C");

        // Set fan speed based on temperature
        if (temperature < 30)
            duty_cycle = 0;
        else if (temperature >= 30 && temperature < 40)
            duty_cycle = 30;
        else if (temperature >= 40 && temperature < 50)
            duty_cycle = 60;
        else
            duty_cycle = 90;
        
        CCPR1L = (duty_cycle * 4) / 100;

        __delay_ms(500);
        LCD_Clear();
    }
}

void ADC_Init() {
    ADCON0 = 0x41;
    ADCON1 = 0x80;
}

unsigned int ADC_Read(unsigned char channel) {
    if(channel > 7) return 0;
    ADCON0 &= 0x11000101;
    ADCON0 |= channel<<3;
    __delay_us(30);
    GO_nDONE = 1;
    while(GO_nDONE);
    return ((ADRESH<<8)+ADRESL);
}

void PWM_Init() {
    PR2 = 0xFF;
    CCP1CON = 0x0C;
    T2CON = 0x04;
}

void LCD_Init() {
    TRISD = 0x00;
    TRISC = 0x00;

    LCD_Command(0x02);
    LCD_Command(0x28);
    LCD_Command(0x0C);
    LCD_Command(0x06);
    LCD_Command(0x01);
}

void LCD_Command(char cmd) {
    PORTD = (cmd & 0xF0);
    RC0 = 0; RC1 = 0; RC2 = 1;
    __delay_ms(1);
    RC2 = 0;
    
    PORTD = ((cmd<<4) & 0xF0);
    RC0 = 0; RC1 = 0; RC2 = 1;
    __delay_ms(1);
    RC2 = 0;
}

void LCD_Char(char data) {
    PORTD = (data & 0xF0);
    RC0 = 1; RC1 = 0; RC2 = 1;
    __delay_ms(1);
    RC2 = 0;
    
    PORTD = ((data<<4) & 0xF0);
    RC0 = 1; RC1 = 0; RC2 = 1;
    __delay_ms(1);
    RC2 = 0;
}

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

void LCD_Clear() {
    LCD_Command(0x01);
    __delay_ms(2);
}

🔍 6. Testing and Debugging Tips

If Fan is Not Moving:

  • Verify PWM signal using an oscilloscope or LED blinking technique.
  • Check MOSFET gate-source voltage.
  • Confirm correct motor voltage supply.

If LCD Displays Garbage:

  • Recheck LCD wiring.
  • Confirm timing delays are sufficient.
  • Double-check contrast settings via potentiometer.

Incorrect Temperature Readings:

  • Ensure proper LM35 wiring (especially Vout to RA0).
  • Verify correct ADC reference voltage (should be stable 5V).

Fan Speed Irregularity:

  • Check if Timer2 is correctly configured.
  • Validate duty cycle calculations.

🌟 7. Extensions

  • Implement a PID Controller for more accurate fan speed control.
  • Store temperature history into EEPROM for later analysis.
  • Add Bluetooth (HC-05 module) to monitor via mobile phone.
  • Manage multiple fans in different zones based on sensor inputs.
  • Replace LCD with an OLED display for better readability and compact design.

Would you also like me to create a schematic drawing or simulate this project step-by-step next? 🚀