Temperature-Based Fan Control Using PIC16F877A
Temperature-Based Fan Control Using PIC16F877A file VmhRFuqY4TTMJTe9EUKVyb

Temperature-Based Fan Control Using PIC16F877A

Project Overview

This project demonstrates how to control a DC fan using a PIC16F877A microcontroller based on temperature readings from an LM35 sensor. When the temperature crosses a predefined threshold, the microcontroller activates the fan. This type of system is widely used in automatic cooling systems, home automation, and industrial temperature regulation.

Learning Objectives

  • Learn how to read analog temperature data using the ADC module of the PIC16F877A.
  • Implement PWM (Pulse Width Modulation) for fan speed control.
  • Interface a 16×2 LCD with a microcontroller to display real-time temperature readings.
  • Control a relay using a transistor switch for turning the fan ON or OFF.

Required Components

  • PIC16F877A microcontroller
  • LM35 temperature sensor
  • 16×2 LCD display
  • DC fan
  • Relay module
  • 2N2222 NPN transistor
  • 1N4007 diode (for relay flyback protection)
  • Resistors and capacitors
  • 5V and 12V power supplies
  • PIC programmer (e.g., PICKIT3)
  • MPLAB X IDE with the XC8 compiler

Circuit Description

The LM35 temperature sensor is connected to AN0 (RA0) to provide an analog voltage output proportional to the temperature. The ADC module of the microcontroller converts this signal into a digital value. A 16×2 LCD display connected to PORTD is used to display the current temperature and fan status.

To control the fan, a relay module is used. Since the microcontroller cannot directly drive a relay, a 2N2222 transistor acts as a switch. The transistor receives a control signal from RB0 and allows current to flow through the relay coil, which in turn controls the fan’s power circuit.

The PWM output (CCP1 – RC2) can be used to control the fan’s speed, but in this basic version, the fan is either ON or OFF depending on the temperature reading.

Source Code (XC8)

// PIC16F877A - Temperature-based Fan Control
#include <xc.h>
#define _XTAL_FREQ 8000000  // 8MHz Crystal Oscillator
#define LCD_RS RD0
#define LCD_EN RD1
#define FAN_PIN RB0

// Configuration bits
#pragma config FOSC = XT_XT, WDTE = OFF, PWRTE = OFF, BOREN = ON, LVP = OFF

// Function Prototypes
void LCD_Command(unsigned char);
void LCD_Char(unsigned char);
void LCD_Init();
void LCD_String(const char *);
void ADC_Init();
unsigned int ADC_Read(unsigned char);

void main() {
    unsigned int temp;
    TRISA = 0x01;  // AN0 as input (LM35)
    TRISB = 0x00;  // Fan control output
    TRISD = 0x00;  // LCD Port Output
    
    ADC_Init();  // Initialize ADC
    LCD_Init();  // Initialize LCD
    
    while(1) {
        temp = ADC_Read(0) * 0.488; // Convert ADC value to temperature
        
        LCD_Command(0x80);  
        LCD_String("Temp: ");
        LCD_Char((temp / 10) + 48);  // Display temperature
        LCD_Char((temp % 10) + 48);
        LCD_String(" C");
        
        if (temp > 30) {
            RB0 = 1; // Turn ON fan if temperature > 30°C
            LCD_Command(0xC0);
            LCD_String("Fan: ON ");
        } else {
            RB0 = 0; // Turn OFF fan
            LCD_Command(0xC0);
            LCD_String("Fan: OFF");
        }
        
        __delay_ms(1000);
    }
}

// ADC Initialization
void ADC_Init() {
    ADCON1 = 0x80;  // Configure ADC
    ADCON0 = 0x41;  // Enable ADC
}

// Read ADC value
unsigned int ADC_Read(unsigned char channel) {
    ADCON0 &= 0xC5;
    ADCON0 |= (channel << 3);
    __delay_ms(2);
    GO_nDONE = 1;
    while(GO_nDONE);
    return ((ADRESH << 8) + ADRESL);
}

// LCD Functions
void LCD_Command(unsigned char cmd) {
    PORTD = cmd;
    LCD_RS = 0;
    LCD_EN = 1;
    __delay_ms(2);
    LCD_EN = 0;
}

void LCD_Char(unsigned char data) {
    PORTD = data;
    LCD_RS = 1;
    LCD_EN = 1;
    __delay_ms(2);
    LCD_EN = 0;
}

void LCD_Init() {
    LCD_Command(0x38);  // 2 lines, 5x7 matrix
    LCD_Command(0x0C);  // Display ON, Cursor OFF
    LCD_Command(0x06);  // Auto-increment cursor
    LCD_Command(0x01);  // Clear display
}

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

Troubleshooting & Debugging

LCD Not Displaying Data

If the LCD screen does not show any output, check the wiring of RS, EN, and data lines. Make sure the contrast potentiometer is adjusted correctly, and ensure the 5V power supply is stable.

Fan Not Turning ON or OFF

Check if RB0 is configured correctly as an output. Verify the relay connections and ensure the transistor is switching properly. Use a multimeter to measure voltage at RB0 when the temperature crosses the threshold.

Incorrect Temperature Readings

Ensure the LM35 sensor is wired correctly with proper VCC, GND, and Output connections. If readings fluctuate, try adding a capacitor (100nF) across VCC and GND to stabilize power. Also, verify that ADC reference voltage is 5V.

PIC16F877A Not Responding

If the program does not execute, check the programming process using PICKIT3. Ensure the 8MHz crystal oscillator and capacitors (22pF) are properly connected. Also, verify that the MCLR pin is pulled up with a 10kΩ resistor.

Possible Enhancements

  • Implement PWM fan speed control instead of simple ON/OFF switching.
  • Use multiple temperature thresholds for variable fan speeds.
  • Add Bluetooth connectivity for remote temperature monitoring and control.
  • Replace the LCD with an OLED display for a more compact and power-efficient interface.

This project is a great way to learn sensor interfacing, ADC processing, LCD display control, and relay switching with a PIC microcontroller. Let me know if you want further modifications, such as WiFi (IoT) control or data logging! 🚀