Light-Sensing System with LDR, Potentiometer, and LED – Using the PIC16F15313

We’ve already done some amazing , 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 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

LDR POT LED

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:

  1. Initialization: The microcontroller is set up using CORE.Initialize(), which handles all the necessary startup tasks.
  2. 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.
  3. 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.
  4. 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 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 : Main Doc Page

Core MCU Framework Versions : Supported Devices


Have a Project or Idea!?

Seeking Bespoke Technology Solutions?

jamie@jamiestarling.com


Pin It on Pinterest

Share This