Home 9 The Art of Technology 9 Bringing It to Life : Using a Potentiometer to Control an LED and Monitor Values with Serial Feedback

Using a Potentiometer to Control an LED and Monitor Values with Serial Feedback

In our last project, we used a potentiometer to control the blink speed of an LED with a PIC microcontroller—turning a simple knob to adjust how fast the light flashes. That was just the start! Today, we’re taking it a step further by adding a serial interface to the setup, allowing us to read and display the current potentiometer values in real time. It’s a small addition, but one that opens the door to deeper insights and more control over what’s happening inside our circuit. Let’s see how adding this layer of feedback can transform our project!

The Circuit

ledblink pot serial

Setting Up the Circuit: Adding Serial Feedback to the Mix

This project builds on our previous setup, where we used a potentiometer to control the blink speed of an LED. The core circuit remains the same, but now we’re adding a new element—a TTL to USB Serial Converter—to allow real-time feedback through a serial interface. With this addition, you’ll not only see the LED’s behavior change as you turn the potentiometer, but you’ll also be able to monitor the exact values in real time on your computer, adding a whole new layer of interaction.

Let’s walk through each part of the circuit:

  1. Powering the Microcontroller: At the heart of the setup is the PIC16F15313, which we’ll power with a 5V DC supply. To keep things running smoothly, a 100nF capacitor is connected for decoupling. Think of it as a small “smoothing tool” that filters out any power fluctuations, ensuring the microcontroller operates reliably.
  2. Connecting the LED to PortA.0: We’ll attach a 300-ohm resistor to PortA.0, with the LED connected right after it. The resistor limits the current, protecting the LED from burning out while making sure it glows at the right intensity. This LED will blink based on the values we read from the potentiometer.
  3. Connecting the Potentiometer to PortA.1: The middle pin (wiper) of the potentiometer connects to PortA.1 on the PIC. As you turn the knob, the voltage at this pin changes, allowing us to read its value and use it to adjust the LED’s blink speed. It’s a simple interaction, but it forms the foundation for understanding how to incorporate analog inputs.
  4. Adding Serial Output on PortA.4: Here’s the new addition: we’re using PortA.4 as the TTL serial output pin. This pin sends the potentiometer’s reading as serial data to the TTL to USB Serial Converter. From there, the converter translates it into a format that your computer can read. Connect PortA.4 (serial TX) on the PIC to the RX (receive) pin on the TTL to USB module.

Putting It All Together

With the core components—the LED, potentiometer, and now the serial interface—working together, we’ve created a circuit that not only responds to physical changes but also communicates those changes back to us. This feedback is incredibly valuable for troubleshooting, monitoring, and exploring how the circuit responds in real time.

Once you’ve built the circuit, we’ll jump into the code and set up the serial output so that you can see exactly what’s happening as you turn the knob. It’s all about adding that extra layer of visibility and control, making this project more interactive and, hopefully, even more satisfying to experiment with. Ready to take the next step? Let’s get started!

Now for the Code

/****************************************************************************
* Title                 :   Blinks LED based on POT Analog Value - Outputs POT Value to Serial Port
* Filename              :   blink_led_pot_serial.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.2 to Analog and Maps ANA2 Channel - Initializes Analog*/
  GPIO_Analog.PinSet(PORTA_1,ANA1); //  

/*Initializes Serial1 to 9600 Baud
*On the PIC16F15313 Receive is PORTA.5 : Transmit is on PORTA.4 */
  SERIAL1.Initialize(BAUD_9600);  //Initializes Serial1 - On the PIC16F15313 Receive is RA4
 
  while(1) //Program loop
    {      
      uint16_t POT_Value; 
      char SerialTransmit_Buffer[25]; 
      
      GPIO.PinToggle(PORTA_0); //Toggles LED on PORTA_0
      
      POT_Value = GPIO_Analog.ReadChannel();
      sprintf(SerialTransmit_Buffer, "POT Value : %d\n", POT_Value);
      SERIAL1.WriteString(SerialTransmit_Buffer);  
      CORE.Delay_MS(POT_Value);    //Delay based on reading from the Analog     
    }
}




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

Blinking LED with Serial Feedback

This code takes what we did in the last project and adds an exciting new layer: a live readout of the potentiometer values through a serial interface. With this setup, not only does the LED blink at a rate controlled by the potentiometer, but we also get real-time feedback on your computer, showing exactly what value the potentiometer is reading as you turn it.

Here’s a breakdown of how the code works:

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

We start by including the Core Framework library, which handles a lot of the heavy lifting, so we can focus on making things happen.

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

The CORE.Initialize() function sets up the core system configurations for the PIC16F15313. It’s like flipping the main switch to get everything ready and in order.

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

This line configures PortA.0 as an output, which is where the LED is connected. It lets the microcontroller send signals to 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>

PortA.1 is configured as an analog input here. The potentiometer is connected to this pin, so we can read its position and translate it into a value using the built-in Analog-to-Digital Converter (ADC).

/* Initializes Serial1 to 9600 Baud<br>  * On the PIC16F15313 Receive is PORTA.5 : Transmit is on PORTA.4 */<br>  SERIAL1.Initialize(BAUD_9600); <br>

This line initializes the serial communication at a 9600 baud rate. We’re using PortA.4 as our Transmit (TX) pin. This will send data out to the TTL to USB Serial Converter, so you can see the potentiometer values on your computer through a serial terminal.

Inside the Endless Loop

while(1) // Program loop<br>  {      <br>      uint16_t POT_Value; // Variable to hold the potentiometer reading<br>      char SerialTransmit_Buffer[25]; // Buffer to store the serial message<br>

Here, we declare a variable POT_Value to store the potentiometer’s current value and a SerialTransmit_Buffer to hold the formatted message we’ll send out.

GPIO.PinToggle(PORTA_0); // Toggles LED on PORTA_0<br>

This function toggles the state of the LED on PortA.0. If the LED is on, it turns off; if it’s off, it turns on. This creates the blinking effect.

POT_Value = GPIO_Analog.ReadChannel();<br>

We read the value from the potentiometer on PortA.1 using the analog channel. This value ranges from 0 to 1023, depending on the knob’s position.

sprintf(SerialTransmit_Buffer, "POT Value : %d\n", POT_Value);<br>

We then format the potentiometer value into a readable string using sprintf(), creating a message like: "POT Value : 512\n".

SERIAL1.WriteString(SerialTransmit_Buffer);  <br>

This line sends the formatted string over the serial port, displaying the potentiometer’s current reading on your serial terminal in real time.

CORE.Delay_MS(POT_Value); // Delay based on reading from the Analog     <br>

Finally, we use the potentiometer value to control the delay between blinks. A lower value means a faster blink; a higher value slows it down.

What’s Happening Here?

With this setup, each time the loop runs:

  1. The LED blinks at a rate based on the potentiometer’s value.
  2. The potentiometer’s position is read and stored in POT_Value.
  3. The value is sent out over the serial port using the SERIAL1.WriteString() function.
  4. The blink delay is adjusted based on the potentiometer value.

Real-Time Feedback: What You’ll See

As you turn the potentiometer, the LED will blink faster or slower. Meanwhile, on your computer’s serial terminal, you’ll see a steady stream of messages like:

POT Value : 250<br>POT Value : 500<br>POT Value : 750<br>

This live feedback is incredibly useful for debugging, understanding how your circuit responds, and making the interaction more tangible. It’s a small but powerful addition that helps bridge the gap between hardware and software, turning simple adjustments into something visible and trackable.

Where to Go from Here

This project is just the beginning! Now that you have serial feedback, you can start using this value to control other outputs, monitor , or even build a more complex control system. With each addition, you’re adding another layer of interaction and learning more about how your microcontroller responds in real time. Keep experimenting, and see how far you can take it! Happy tinkering!

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