
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
- LM35 Sensor: A precision temperature sensor with a linear output of 10mV/°C.
- ADC: The PIC16F877A includes a 10-bit ADC module, converting analog signals to digital values.
- PWM: A technique for controlling power delivered to devices like motors and fans.
- L293D: A motor driver IC used to control the speed and direction of DC motors.
Step-by-Step Guide
1. Circuit Wiring
- 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.
- Temperature Sensor (LM35)
- Connect the
VccandGNDpins of the LM35 to the power supply. - Connect the output pin of the LM35 to the AN0 pin (RA0) of the PIC.
- Connect the
- 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.
- 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.
- 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
- ADC Not Working: Ensure the analog pin is properly connected and configured.
- Incorrect Temperature: Calibrate the LM35 sensor and verify the ADC calculations.
- PWM Issues: Check the Timer2 configuration and ensure the motor driver PWM pin is connected.
- 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! 🚀