Temperature-Controlled Fan Using PIC Microcontroller
Temperature-Controlled Fan Using PIC Microcontroller file EjWeXwdg1WAGVCEb12N774

Temperature-Controlled Fan Using PIC Microcontroller


This project demonstrates how to build a temperature-controlled fan using a PIC microcontroller. The fan speed is adjusted based on the temperature sensed by a sensor (LM35). This project has practical applications in automatic cooling systems for electronic devices or HVAC systems.


Learning Objectives

  • Understand the basics of analog-to-digital conversion (ADC) in PIC microcontrollers.
  • Learn how to interface sensors and actuators with PIC microcontrollers.
  • Implement Pulse Width Modulation (PWM) for fan speed control.
  • Debug and calibrate sensor-based systems.

Tools and Components

Hardware

  • PIC16F877A microcontroller
  • LM35 temperature sensor
  • 12V DC fan
  • L293D motor driver (or any suitable DC motor driver)
  • 16×2 LCD display
  • 10kΩ potentiometer (for LCD contrast adjustment)
  • Resistors: 10kΩ, 1kΩ
  • Capacitors: 22pF (for crystal oscillator)
  • 8 MHz crystal oscillator
  • Power supply (5V for PIC and 12V for fan)
  • Breadboard and jumper wires

Software

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

Background/Definitions

  1. LM35 Sensor: A precision temperature sensor with a linear output of 10mV/°C.
  2. ADC: The PIC16F877A includes a 10-bit ADC module, converting analog signals to digital values.
  3. PWM: A technique for controlling power delivered to devices like motors and fans.
  4. L293D: A motor driver IC used to control the speed and direction of DC motors.

Step-by-Step Guide

1. Circuit Wiring

  1. Microcontroller Setup
    • Connect the 8 MHz crystal oscillator and 22pF capacitors to pins OSC1 and OSC2 of the PIC16F877A.
    • Connect MCLR to Vcc through a 10kΩ pull-up resistor.
  2. Temperature Sensor (LM35)
    • Connect the Vcc and GND pins of the LM35 to the power supply.
    • Connect the output pin of the LM35 to the AN0 pin (RA0) of the PIC.
  3. LCD Display
    • Connect RS, RW, and E pins of the LCD to RB0, RB1, and RB2 respectively.
    • Connect the data pins (D4-D7) of the LCD to RB4-RB7.
    • Connect the contrast pin (V0) to the 10kΩ potentiometer.
  4. Fan Connection via L293D
    • Connect the fan to the output pins of the L293D.
    • Connect the control pins of L293D to RC0 and RC1 of the PIC for direction control.
    • Connect the PWM input pin of L293D to RC2.
  5. Power Supply
    • Provide 5V to the PIC and LM35, and 12V to the fan and L293D motor driver.

2. Programming

Here’s the fully annotated code:

cCopy code#include <xc.h>

#define _XTAL_FREQ 8000000 // Define the oscillator frequency

// 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 Code Protection disabled
#pragma config WRT = OFF      // Flash Program Memory Write Protection disabled
#pragma config CP = OFF       // Flash Program Memory Code Protection disabled

// Function Prototypes
void ADC_Init();
unsigned int ADC_Read(unsigned char channel);
void PWM_Init();
void PWM_Set_Duty(unsigned int duty);
void LCD_Init();
void LCD_Command(char cmd);
void LCD_Write_Char(char data);
void LCD_Write_String(const char *str);
void LCD_Set_Cursor(char row, char col);

void main() {
    unsigned int adc_value;
    float temperature;
    unsigned int duty_cycle;
    
    ADC_Init();     // Initialize ADC module
    PWM_Init();     // Initialize PWM module
    LCD_Init();     // Initialize LCD
    
    LCD_Set_Cursor(1, 1);
    LCD_Write_String("Temp: ");
    LCD_Set_Cursor(2, 1);
    LCD_Write_String("Fan: ");
    
    while(1) {
        adc_value = ADC_Read(0);             // Read analog value from LM35
        temperature = (adc_value * 4.88) / 10.0; // Convert ADC value to temperature (mV to °C)
        
        // Display temperature on LCD
        LCD_Set_Cursor(1, 7);
        LCD_Write_Char((temperature / 10) + '0');
        LCD_Write_Char((int)temperature % 10 + '0');
        LCD_Write_String("C ");
        
        // Determine fan speed based on temperature
        if (temperature < 25) {
            duty_cycle = 0; // Fan OFF
        } else if (temperature >= 25 && temperature <= 40) {
            duty_cycle = ((temperature - 25) * 10); // Linear ramp
        } else {
            duty_cycle = 100; // Fan FULL speed
        }
        
        PWM_Set_Duty(duty_cycle);
        
        // Display fan speed
        LCD_Set_Cursor(2, 6);
        LCD_Write_Char((duty_cycle / 10) + '0');
        LCD_Write_Char((duty_cycle % 10) + '0');
        LCD_Write_String("% ");
        
        __delay_ms(500); // Delay for readability
    }
}

void ADC_Init() {
    ADCON0 = 0x41;  // ADC ON and select channel 0
    ADCON1 = 0x80;  // Right justified result
}

unsigned int ADC_Read(unsigned char channel) {
    ADCON0 &= 0xC5; // Clear channel selection bits
    ADCON0 |= (channel << 3); // Select the required channel
    __delay_ms(2); // Acquisition time
    GO_nDONE = 1; // Start conversion
    while (GO_nDONE); // Wait for conversion to finish
    return ((ADRESH << 8) + ADRESL); // Return result
}

void PWM_Init() {
    TRISC2 = 0; // Set RC2 as output for PWM
    PR2 = 124;  // Set PWM period (frequency)
    CCP1CON = 0x0C; // Configure PWM mode
    T2CON = 0x01; // Start Timer2
}

void PWM_Set_Duty(unsigned int duty) {
    if (duty > 100) duty = 100; // Clamp duty cycle to 100%
    duty = ((float)duty / 100) * 1023; // Scale to 10-bit resolution
    CCP1CONbits.DC1B = duty & 0x03; // Set 2 LSBs
    CCPR1L = duty >> 2; // Set 8 MSBs
}

void LCD_Init() {
    // LCD initialization commands here
}

void LCD_Command(char cmd) {
    // LCD command handling here
}

void LCD_Write_Char(char data) {
    // Write a single character to LCD
}

void LCD_Write_String(const char *str) {
    // Write a string to LCD
}

void LCD_Set_Cursor(char row, char col) {
    // Set cursor position on LCD
}

Testing and Debugging Tips

  1. ADC Not Working: Ensure the analog pin is properly connected and configured.
  2. Incorrect Temperature: Calibrate the LM35 sensor and verify the ADC calculations.
  3. PWM Issues: Check the Timer2 configuration and ensure the motor driver PWM pin is connected.
  4. LCD Display Problems: Verify connections and adjust the contrast potentiometer.

Extensions

  • Use a DHT22 sensor to add humidity-based fan control.
  • Incorporate EEPROM to store and recall preferred temperature thresholds.
  • Add a buzzer to alert when the temperature exceeds a critical value.

This project provides a solid foundation in embedded systems, combining sensor interfacing, ADC, and PWM techniques for practical applications. Happy building! 🚀