
1. Introduction
In this project, we will build an automatic light control system using a Light Dependent Resistor (LDR) and the PIC16F877A microcontroller. The microcontroller reads ambient light intensity via the LDR and automatically turns an LED or relay-controlled lamp ON in darkness and OFF in brightness.
Real-World Applications:
- Streetlights that turn on at night
- Energy-saving home lighting
- Automatic garden or security lights
2. Learning Objectives
- Learn how to read analog signals using PIC ADC (Analog-to-Digital Converter)
- Understand light sensing with an LDR voltage divider
- Use conditional logic to drive outputs based on sensor input
- Control devices like LEDs or relays with transistors and PIC I/O
3. Tools and Components
Hardware Required:
- PIC16F877A microcontroller
- Light Dependent Resistor (LDR)
- 10kΩ resistor (for LDR voltage divider)
- LED or 5V Relay with NPN transistor (e.g., BC547)
- Flyback diode (e.g., 1N4007) for relay
- Resistors: 330Ω for LED, 1kΩ for transistor base
- Power supply: 5V regulated
- Breadboard, jumper wires
- Crystal oscillator (20MHz) + 22pF capacitors (if external)
- MPLAB X IDE + XC8 Compiler
- PIC Programmer (e.g., PICKIT 3)
4. Background Concepts
- LDR (Light Dependent Resistor): Resistance decreases as light intensity increases.
- Voltage Divider: Converts LDR resistance changes into voltage readable by the PIC ADC.
- ADC (Analog-to-Digital Converter): Converts voltage (0-5V) to a 10-bit digital value (0-1023).
- Thresholding: Define a light level threshold; below it, we turn the light ON.
5. Step-by-Step Assembly and Code
Circuit Wiring Overview
- LDR Voltage Divider:
- Connect one leg of the LDR to 5V.
- Connect the other leg to both:
- RA0 (AN0) of PIC
- One leg of the 10kΩ resistor; connect the other end of resistor to GND.
- Result: Analog voltage at RA0 changes with light intensity.
- Output Control (LED or Relay):
- LED Option:
- Connect LED anode to RB0 via 330Ω resistor.
- LED cathode to GND.
- Relay Option:
- RB0 → 1kΩ resistor → Base of BC547 transistor.
- Emitter to GND.
- Relay coil between 5V and collector.
- Diode across relay (cathode to 5V) to protect from voltage spikes.
- LED Option:
Source Code with Comments (XC8)
#include <xc.h>
#define _XTAL_FREQ 20000000 // 20MHz Oscillator
// Configuration Bits
#pragma config FOSC = HS, WDTE = OFF, PWRTE = ON, BOREN = ON, LVP = OFF, CPD = OFF, WRT = OFF, CP = OFF
void ADC_Init();
unsigned int ADC_Read(unsigned char channel);
void main() {
unsigned int light_value;
const unsigned int threshold = 500; // Set threshold (adjust as needed)
TRISA = 0x01; // RA0 as input (AN0)
TRISB0 = 0; // RB0 as output
PORTB = 0x00; // Initialize outputs to 0
ADC_Init(); // Initialize ADC
while(1) {
light_value = ADC_Read(0); // Read LDR analog value
if (light_value < threshold) {
RB0 = 1; // Turn ON light (LED or relay)
} else {
RB0 = 0; // Turn OFF light
}
__delay_ms(500); // Sampling delay
}
}
// ADC Initialization Function
void ADC_Init() {
ADCON1 = 0x80; // Right justified, Fosc/32
ADCON0 = 0x01; // Enable ADC, select AN0
}
// ADC Read Function
unsigned int ADC_Read(unsigned char channel) {
ADCON0 = (channel << 3) | 0x01; // Select channel and turn on ADC
__delay_us(20); // Acquisition delay
GO_nDONE = 1; // Start conversion
while (GO_nDONE); // Wait until conversion completes
return ((ADRESH << 8) + ADRESL); // Return result
}
6. Testing and Debugging Tips
- LDR not responding: Verify LDR connections and check voltage at RA0 using a multimeter.
- ADC reads 0 or erratic values: Confirm ADC initialization and sampling time. Add a capacitor (~0.1µF) across LDR for stability.
- Light doesn’t switch ON/OFF properly: Adjust the
thresholdvalue based on your room lighting conditions. Test different values between 300–700. - Relay chattering or no activation: Ensure sufficient base current to the transistor. Check diode placement across relay coil.
7. Project Extensions
- Add an LCD display to show real-time light levels.
- Incorporate manual override switch to force the light ON/OFF.
- Use EEPROM to store the threshold and allow dynamic adjustment.
- Implement PWM dimming instead of ON/OFF switching for adjustable brightness.