Using a Potentiometer with a PIC Microcontroller To Change Flash Rate of LED

In the last post, we took a look at how to use a potentiometer with a PIC microcontroller and explored what’s really happening when you turn that knob. Today, we’re going to take it a step further and put that knowledge into action. Let’s see how we can use the potentiometer’s values to create something more interactive and dynamic.

Setting Up the Circuit

ledblink pot
Potentiometer Hookup Diagram

Let’s put together a simple circuit to get things rolling. For this project, we’re using a PIC16F15313 microcontroller, powered by a 5V DC supply. It’s a straightforward setup, but each piece plays an important role in making sure everything runs smoothly.

Powering the Microcontroller: At the core of our circuit is the PIC16F15313, which receives its power through the 5V supply. To keep that power stable, we’ve added a 100nF capacitor for decoupling. Think of it like a “smoothing tool” that helps filter out any small fluctuations in the power line, ensuring the PIC operates reliably.

Connecting the LED to PortA.0: The first part of the circuit is a simple LED connection. We’ll attach a 300-ohm resistor to PortA.0 on the PIC, with the LED placed right after it. The resistor is there to limit the current, protecting the LED from overheating and burning out. Once connected, the LED is ready to respond to the signals we send from our code.

Connecting the Potentiometer to PortA.1: Next, we’ll bring in the potentiometer. We’ll connect the middle pin (wiper) of the potentiometer to PortA.1 on the PIC. As you turn the knob, the voltage on this pin changes, which we’ll use to read its position and create a dynamic interaction in our code.

How It All Fits Together

These simple components—an LED, a potentiometer, and a few resistors—are more than just parts on a breadboard. Each one is a piece of the bigger picture, working together to bring your project to life. With just a few connections, you’re able to create something that responds to your touch and can be controlled with a simple twist of the knob.

Once we have the hardware set up, we’ll jump into the code and show how to read the potentiometer’s values and use it to control the LED. It’s all about taking small steps and building from there, turning these basic circuits into something that feels more like an interactive creation. Ready to see it in action? Let’s keep going!

And Now The Code

/****************************************************************************
* Title                 :   Blink LED Delay Based on POT Analog Value
* Filename              :   blink_led_pot.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);
  
 /*Set PORTA.1 to Analog and Maps ANA1 Channel - Initializes Analog*/
  GPIO_Analog.PinSet(PORTA_1,ANA1); //  

 
  while(1) //Program loop
    {      
      uint16_t POT_Value;
      GPIO.PinToggle(PORTA_0); //Toggles LED on PORTA_0
      POT_Value = GPIO_Analog.ReadChannel(); //Reads Value from Pot
      CORE.Delay_MS(POT_Value);    //Delay based on reading from the Analog     
    }
}




/*** End of File **************************************************************/

Breaking Down the Code: Blinking an LED Based on Potentiometer Input

This code takes a basic LED blink and makes it a bit more interactive by using the value from a potentiometer to adjust the delay between blinks. In other words, the speed of the LED blinking is directly controlled by how much you turn the knob on the potentiometer. Let’s go through it step-by-step to understand how it all fits together.

Code Overview

The goal here is to read the analog value from a potentiometer connected to PortA.1 of a PIC16F15313 and use that value to change how quickly an LED blinks on PortA.0. The result? The more you turn the potentiometer, the faster (or slower) the LED blinks, giving you direct control over the LED’s behavior.

Let’s dive into the details of what each section of the code does:

#include "core16F/core16F.h" // Include Core MCU Functions<br>

The code starts by including the Core Framework library, which simplifies many of the low-level configurations and provides easy-to-use functions for handling GPIO and analog inputs.

void main(void)<br>{<br>  /* Setup */<br>  CORE.Initialize(); // Initialize the Core System<br>

The CORE.Initialize() function sets up the basic system configurations for the microcontroller. Think of it as flipping the power switch and making sure all the internal systems are ready to go.

/* Set PORTA.0 to Output */<br>  GPIO.ModeSet(PORTA_0, OUTPUT);<br>

This line sets PortA.0 as an output pin. This is the pin that’s connected to our LED, allowing the microcontroller to send signals that turn the LED on and off.

/* Set PORTA.1 to Analog and Maps ANA1 Channel - Initializes Analog */<br>  GPIO_Analog.PinSet(PORTA_1, ANA1);<br>

Here, PortA.1 is configured as an analog input and mapped to the analog channel ANA1. This tells the microcontroller that it should treat the voltage on PortA.1 as an analog signal and convert it to a digital value using the ADC (Analog-to-Digital Converter).

The Endless Loop

After the setup, we enter the main program loop, which keeps running forever:

while(1) //Program loop<br>  {      <br>      uint16_t POT_Value; // Define a variable to hold the potentiometer value<br>      GPIO.PinToggle(PORTA_0); // Toggle the LED on PortA.0<br>
  • uint16_t POT_Value; declares a 16-bit variable to store the value read from the potentiometer. This value will range from 0 to 1023, depending on the position of the potentiometer knob.
  • GPIO.PinToggle(PORTA_0); toggles the LED on and off. If the LED is currently on, it turns off; if it’s off, it turns on. This is how we create the blinking effect.
POT_Value = GPIO_Analog.ReadChannel(); //Reads Value from Pot<br>
  • This line reads the current analog value from the potentiometer using the GPIO_Analog.ReadChannel() function and stores it in the POT_Value variable. The result is a number between 0 and 1023, which represents the voltage at the wiper of the potentiometer.
CORE.Delay_MS(POT_Value); //Delay based on reading from the Analog<br>
  • CORE.Delay_MS(POT_Value); pauses the program for a duration that’s directly controlled by the value of POT_Value. If POT_Value is small (meaning the potentiometer is turned down), the delay is short, making the LED blink faster. If POT_Value is high (knob turned up), the delay is longer, and the LED blinks more slowly.

What’s Happening in the Loop

Each time through the loop, the program:

  1. Toggles the LED on PortA.0 (turns it on if it’s off, or off if it’s on).
  2. Reads the value from the potentiometer on PortA.1.
  3. Adjusts the delay time between blinks based on the potentiometer’s position.

The result is a program where the LED blink speed changes smoothly as you turn the potentiometer. It’s a great way to see how analog inputs can add a layer of interactivity to your .

Why This Code Matters

This is more than just making an LED blink—it’s about using an analog input to dynamically control a digital output. It’s a small step into a world of possibilities where you can use , knobs, and other inputs to shape how your projects behave.

With just a few lines of code, you’re learning how to bridge the gap between the physical world (the knob you turn) and the digital world (the blinking LED). As you get more comfortable, you can start using these concepts to control other outputs like motors, servos, or even more complex systems.

This is just one small example of what the Core MCU Framework can do, making it easier to connect and control your hardware without getting lost in complex code. So keep experimenting and exploring—there’s so much more you can create!

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