Potentiometer-Controlled LED Brightness

Potentiometer Controlled LED Brightness


In the project Breathing LED with Pulse-Width Modulation, you built a circuit that was able to change the brightness of an LED by using a PWM signal. For that project, the chipKIT™ board controlled the LED without any form of input from the user. This project will build upon the previous exercise, adding an element of user input by allowing manual control over the brightness of the LED. To accomplish this, we will introduce a new component called a potentiometer. Using this component, we can create a voltage divider circuit that can indirectly control the brightness of our LED. Our chipKIT board will act as mediator between the voltage divider and the LED. It will essentially read the value of the voltage divider, and then output a PWM signal for the desired level of brightness.


Qty Description Typical Image Schematic Symbol Breadboard Image
1 Potentiometer dial

(resistance range from 10Ω to 10kΩ)

1 220Ω resistor


Before we can start controlling our LED, we need a way to tell the chipKIT board the desired level of brightness. In order to do this, we need to construct a voltage divider circuit. This particular voltage divider circuit will output a voltage that varies from 0V to 3.3V. The chipKIT board reads the voltage with an analog input pin and then appropriately scales the brightness level (i.e., a 3.3V signal would represent 100% brightness, a 1.65V signal would represent 50% brightness, and a 0V signal would represent 0% brightness).

To construct this voltage divider circuit, we need a component called a potentiometer. A potentiometer can be thought of as a resistor that changes its resistance value according to the position of a mechanical dial or screw. Potentiometers are used in all sorts of consumer electronics. Volume knobs on stereos or light dimmer switches are some common applications. They are also handy in situations where precise resistance values cannot be constructed from normal resistors. Figure 1 shows two different types of common potentiometers.

Figure 1. Types of potentiometers.

A potentiometer always has three pins, where two are connected to opposite ends of a resistive material. Figure 2 illustrates how the pins are connected. Pins “A” and “C” are separated by the greatest length of resistive material. This means that the resistance measured across both will always be the maximum value of the potentiometer. In this project, the max resistance is 10 kΩ.

Figure 2. Illustration of the interior view of a potentiometer.

The third pin of the potentiometer (“B” in Fig. 2), is connected to the “wiper” element. This element makes contact with the resistive material and can be repositioned by rotating the mechanical dial. If you were to measure the resistance between points “B” and “C”, you would see a value that could range anywhere from 10 kΩ to about 10 Ω. As you move the wiper, you either increase or decrease the length of the current path between pins “B” and “C” (and, similarly, from pins “A” to “B”). Increasing the length of the path between the pins means that current has to travel through more resistive material, and thus a higher overall resistance (i.e., decreasing the path decreases resistance).

Figure 3 shows a schematic diagram of the voltage divider we will use for this circuit. If you've constructed a voltage divider in the past, you probably used two fixed resistors where the output of the circuit was measured at the point between the two resistors. The circuit here may not look similar, but it functions identically.

Figure 3. Voltage divider used in our circuit.
Figure 4. Voltage divider schematic with wiper element between resistors.

Figure 4 helps illustrate the functionality of the voltage divider. In this figure, the wiper element is set directly in the middle of the resistive material. Recall Ohm's law, where Voltage = Current * Resistance. If you hold current constant, then voltage (i.e., the voltage drop across a resistor) becomes a product of varying resistance. In our voltage divider circuit, current is always constant. Current travels from pin “A” to pin “C”, regardless of the position of the wiper. Very little (if any) current splits off through pin “B”, so we can ignore it. This means that when we move the wiper, we only change the resistance value in the circuit divider. Ultimately, this changes the voltage drop between pins “A” and “B”, as well as between pins “B” and “C.” Thus, we can vary the output of our voltage divider circuit.

Step 1: Setting up the Circuit

Figure 5. Potentiometer circuit.
  1. Place the potentiometer so that it spans the gap between columns in the breadboard (as seen in Fig. 5). It is important to note that potentiometers can come in various configurations; some have all their pins located on the same side, while others may have two pins on one side and the last pin on the other side (Fig. 6 shows an example). Either configuration works, but make sure that each pin occupies its own column on the breadboard.
  2. Figure 6. Alternate potentiometer pin configuration.
  3. Now, connect a wire from pin “A” of the potentiometer to the 3.3V pin on the chipKIT board. (The potentiometer pins are labeled identically to our explanation in the theory section).
  4. Connect from pin “C” of the potentiometer to the ground (GND) pin on the chipKIT board. The column that pin “C” occupies will be called the ground column from now on.
  5. Place a 220 Ω resistor into the breadboard so that one end of the resistor is connected to the ground column.
  6. Connect the cathode (short end) of an LED to the end of the 220 Ω resistor that is not connected to the ground column. Then, connect a wire between the anode (long end) of the LED to the chipKIT board's pin 7.
  7. Finally, connect pin “B” of the potentiometer to the A0 pin of the chipKIT board.


Before going through the software sketch, we must first discuss how the chipKIT board reads analog signals.

You are probably familiar with the analogWrite() function from the “Changing Color of Tricolor LED” or “Breathing LED” projects. The function simply transmits a PWM signal, where the input parameters specify the output pin and the duty cycle of the signal. However, you may not be familiar with the analogRead() function. As its name suggests, this function will convert a signal received on one of the analog pins (analog pins on chipKIT boards have labels preceded by an “A” to distinguish them from digital pins) to signal that is readable as a numerical value.

chipKIT boards use 10-bit analog-to-digital converters (ADCs), so analog values will be approximated to one of 1024 values (the number of values an ADC can distinguish between is equal to 2N, where N is the number of bits of the ADC). This type of approximation is known as signal “quantization.” When a continuous signal (like an analog signal) is “quantized,” it only means that its value is restricted to a discrete number of levels. For example, if you have an analog signal that ranges from any value between 0V and 8V, and you have 8 discrete levels. An analog signal with a level of 6.2V would map to 6 (the closest discrete level).

The analogRead() function assigns the number 1024 to the max reference voltage (and likewise 0 for 0V). The max reference voltage is a value set with the analogReference() function. You will specify DEFAULT as the parameter most frequently when calling this function. On chipKIT boards this designates the max reference voltage as 3.3V.

Sometimes it may be useful to use the EXTERNAL parameter for analogReference(). This specifies the reference voltage to be taken from a physical pin rather than an internal reference (on the chipKIT Max32™, this is pin 44, but this will change from chipKIT board to chipKIT board. The exact pin can be found in your board's reference manual.).

Step 2: Setting up the Software

Once you have an understanding of all of the functions in this sketch, you will find that it is very simple and straightforward. The setup() portion of the sketch simply sets the ADC reference value to DEFAULT, which is 3.3V, and sets the pinMode of the LED to OUTPUT. Note that you don't have to call pinMode for analog input pins (unless you are going to use them as digital pins).

The main loop of the program will simply read from a value from the analog pin, and scale the value so that it is between 0 and 255. This value is then written to the LED pin.

The scaling function may need some explanation if you are unfamiliar with explicitly type-casting a variable. Since valueGlb is an integer variable, it has to be explicitly type-cast as a float in order to multiply it by the scale factor variable ( which is a float variable). Since the result of this multiplication will be a floating point number, it then has to be type-cast again back to an int so it can be stored in valueGlb.

              valueGlb = (int)((float)valueGlb * scaleFactorGlb); 

Once the scaling function has been implemented, turning the dial on the potentiometer sets the brightness on the LED.

              int valueGlb;
              const int aPotGlb = 0;
              const int aLEDGlb = 9;
              // scaleFactorGlb = 255/1000 
              const float scaleFactorGlb = .255;                           
              void setup() 
              // Tell the chipKIT AD converter the max analog voltage will be the default value 3.3V.
              pinMode(aLEDGlb, OUTPUT);
              void loop() 
                    // Read the value from the analog pin connected to the potentiometer, value will be between 0 and 1024.
                    valueGlb = analogRead(aPotGlb);   
                    // Scale the input value so it is within 0 -> 255
                    valueGlb = (int)((float)valueGlb * scaleFactorGlb);
                    // Output analog value to LED
                    analogWrite(aLEDGlb, valueGlb);


This project utilized methods from the previous exercise, Breathing LED with Pulse-Width Modulation, and built upon those steps by adding the use of a potentiometer to create a voltage divider circuit, which will allow manual control over the brightness of the LED. Potentiometers can be thought of as a resistor that changes its resistance value according to the position of a mechanical dial or screw.

Core Concepts:
  • Potentiometers
  • Variable resistance voltage dividers
Functions Introduced:
  • analogRead()
  • analogReference()

  • Other product and company names mentioned herein are trademarks or trade names of their respective companies. © 2014 Digilent Inc. All rights reserved.
  • Circuit and breadboard images were created using Fritzing.