Table of Contents
Light-Sensing System with LDR, Potentiometer, and LED – Using the PIC16F15313
We’ve already done some amazing projects, and now it’s time to combine a few components we’ve worked with before: an LDR (Light Dependent Resistor), a potentiometer, and an LED. This project will bring them all together to create a simple yet effective light-sensing system.
The idea is straightforward: we’ll use the analog functions of the CORE MCU Framework to read both the LDR and the potentiometer. By comparing the light level detected by the LDR to the value set by the potentiometer, we can control an LED. If it gets too dark, the LED will light up; otherwise, it stays off. We’ll also send the readings from both the LDR and potentiometer through a serial connection so we can easily monitor and track the values.
The Circuit
Circuit Breakdown
Let’s go through each part of the circuit step by step:
- Powering the Microcontroller: At the center of our setup is the PIC16F15313 microcontroller, powered by a 5V DC supply. To ensure stable operation, we use a 100nF capacitor for decoupling, which helps filter out any power fluctuations and keeps everything running smoothly.
- Connecting the LED to PortA.0: We’ll connect the LED to PortA.0 via a 300-ohm resistor. The resistor is crucial—it limits the current flowing through the LED, protecting it from burning out while ensuring it shines at the right intensity.
- Connecting the Potentiometer to PortA.1: The potentiometer’s middle pin (the wiper) is connected to PortA.1 on the PIC. As you turn the knob, the voltage at this pin changes, giving us a variable value to read. This forms the foundation of understanding how to integrate analog inputs.
- Connecting the LDR to PORTA.2: The LDR is connected to PORTA.2, allowing us to measure the surrounding light levels. As the light changes, the LDR’s resistance changes, which we read as an analog value.
- Adding Serial Output on PortA.4: We’ll use PortA.4 as the TTL serial output pin, sending the readings to a TTL to USB Serial Converter. This converter translates the data into a format that can be read by your computer. To set it up, simply connect PortA.4 (serial TX) on the PIC to the RX (receive) pin on the TTL to USB module.
Now for the Code
/****************************************************************************
* Title : Read LDR, POT and turn on LED.
* Filename : ldr_pot_led.c
* Author : Jamie Starling
* Origin Date : 2024/04/24
* Version : 1.0.0
* Compiler : XC8
* Target :
* Copyright : Jamie Starling
* All Rights Reserved
*
* THIS SOFTWARE IS PROVIDED BY JAMIE STARLING "AS IS" AND ANY EXPRESSED
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL JAMIE STARLING OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
/******************************************************************************
* LICENSED FOR NON-COMMERCIAL USE
* Visit https://jamiestarling.com/corelicense
* for details
*******************************************************************************/
/******************************************************************************
* Includes
*******************************************************************************/
#include "core16F/core16F.h" //Include Core MCU Functions
/******************************************************************************
* Functions
*******************************************************************************/
void main(void)
{
/*Setup*/
/*Initialize for the Core8 System */
CORE.Initialize(); //
/*Set PORTA.0 to Output*/
GPIO.ModeSet(PORTA_0,OUTPUT);
GPIO_Analog.PinSet(PORTA_1,ANA1); /*Set PORTA.1 to Analog and Maps ANA1 Channel - Initializes Analog*/
GPIO_Analog.PinSet(PORTA_2,ANA2); /*Set PORTA.2 to Analog and Maps ANA2 Channel - Initializes Analog*/
/*Initializes Serial1 to 9600 Baud
*On the PIC16F15313 Receive is PORTC.5 : Transmit is on PORTC.4 */
SERIAL1.Initialize(BAUD_9600); //Initializes Serial1 - On the PIC16F15313 Receive is RC4
while(1) //Program loop
{
uint16_t POT_Value; //Variable for POT Value
uint16_t LDR_Value; //Variable for LDR Value
char SerialTransmit_Buffer[25]; //Varible for Serial Transmit Buffer
GPIO_Analog.SelectChannel(ANA1); //Select Analog ANA1 Channel
POT_Value = GPIO_Analog.ReadChannel(); //Read Analog Value
//Writes Value to Serial Terminal
sprintf(SerialTransmit_Buffer, "POT Value : %d\n", POT_Value);
SERIAL1.WriteString(SerialTransmit_Buffer);
GPIO_Analog.SelectChannel(ANA2); //Select Analog ANA2 Channel
LDR_Value = GPIO_Analog.ReadChannel(); //Read Analog Value
//Writes Value to Serial Terminal
sprintf(SerialTransmit_Buffer, "LDR Value : %d\n", LDR_Value);
SERIAL1.WriteString(SerialTransmit_Buffer);
//Check to see if the LDR Value is Less then the set POT Value
if(LDR_Value <= POT_Value)
{
GPIO.PinWrite(PORTA_0,HIGH); //If True - Light the LED
}
else
{
GPIO.PinWrite(PORTA_0,LOW); //If False - Turn off the LED
}
CORE.Delay_MS(500); //500ms Delay
}/*END of Program Loop*/
}
/*** End of File **************************************************************/
Code Overview
To keep things simple, we’re using the CORE MCU Framework, which provides convenient pre-built functions for GPIO and analog operations. Here’s a breakdown of what the code will accomplish:
- Initialization: The microcontroller is set up using
CORE.Initialize()
, which handles all the necessary startup tasks. - Configuring the GPIO Pins: PORTA.0 is configured as an output for the LED. PORTA.1 and PORTA.2 are set as analog inputs to read the values from the potentiometer and LDR, respectively.
- Serial Communication: We initialize the serial output on PortA.4 so we can send the readings from both the potentiometer and LDR to a serial terminal for real-time monitoring.
- Main Loop Operations: In the main program loop, we:
- Read values from the potentiometer and LDR.
- Send these values to the serial terminal.
- Compare the LDR value to the potentiometer value: if the LDR reading indicates it’s too dark, the LED connected to PORTA.0 turns on; otherwise, it stays off.
Practical Use Cases
This simple project can have several practical applications. For instance, it could be used as an automatic night light that turns on when it gets dark, providing a handy lighting solution for hallways or bedrooms. Another potential use is a light-controlled fan that activates in low light conditions to simulate airflow at night. These examples show just how useful and adaptable these basic components can be in everyday situations.
With these skills, we’re ready to dive in and see how these components can come together to create something practical. Let’s get started and watch it all come to life in real time!
Where to Go From Here
Once you’re comfortable with this setup, there are plenty of ways to expand it. You could add multiple LEDs, use different analog inputs, or even incorporate sensors to create more complex lighting effects. The key takeaway is that you now have a reliable way to connect the analog world (the potentiometer) to a digital system (the PIC microcontroller) and control real-world outputs.
Core MCU Framework Information
Documentation – Knowledge Base For Core MCU Framework
Have a Creative or Technical Project in Mind?
Looking for guidance, insights, or a fresh perspective on your technical or creative journey? Or just somebody to chat with?
Reach Out
jamie@jamiestarling.com