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 | ![]() |
||
1 | LED | ![]() |
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.
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Ω.
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 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.
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.).
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.
analogReference(DEFAULT);
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.