Analyzing the task above, we need to vary the LED's brightness as the potentiometer rotates
To control LED brightness, both the potentiometer and the LED must be properly interfaced with the microcontroller. Here’s how this is typically done:
Potentiometer Interfacing
Note: We can use any of the potentiometers with values between 1kΩ and 10kΩ.
LED Interfacing
Case 1: 5V Supply
Standard resistor values near 320 Ω: 330 Ω or 300 Ω (whichever is available).
Similarly, Case 2: 3.3V Supply
Standard resistor value: 150 Ω.
So, by selecting a proper resistor, LED, and potentiometer, we can implement the task.
Below are the solutions to the given task using different microcontrollers
We’re using an STM32 NUCLEO-F103RB board, which runs at a 3.3V logic level.
Circuit Diagram
Project Setup in STM32CubeIDE
SystemClock_Config
).HAL_Init()
→ Initializes the HAL library.SystemClock_Config()
→ Configures system clock (HSI + PLL).MX_GPIO_Init()
→ Initializes GPIO clocks.MX_USART2_UART_Init()
→ Configures USART2.MX_ADC1_Init()
→ Initializes ADC1 on Channel 0.MX_TIM1_Init()
→ Initializes TIM1 for PWM generation.PWM control (TIM1 configurations)
static void MX_TIM1_Init(void) {
htim1.Instance = TIM1;
htim1.Init.Prescaler = 1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 4095; // ARR value
// ... other configurations
}
TIM1 is configured as a PWM output:
ADC configuration
static void MX_ADC1_Init(void) {
ADC_ChannelConfTypeDef sConfig = { 0 };
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
if (HAL_ADC_Init(&hadc1) != HAL_OK) {
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
Error_Handler();
}
}
This initializes the ADC1 channel 0.
Main Firmware Logic
int main(void) {
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_ADC1_Init();
MX_TIM1_Init();
// Start PWM generation on Timer 1, Channel 1
// This enables the PWM output on the specified timer channel
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
while (1) {
// Start ADC conversion
HAL_ADC_Start(&hadc1);
// Wait for ADC conversion to complete with a timeout of 20ms
HAL_ADC_PollForConversion(&hadc1, 20);
// Read the converted ADC value (0-4095 for 12-bit ADC)
uint16_t adcValue = HAL_ADC_GetValue(&hadc1);
// Update PWM duty cycle based on ADC reading
// This creates a direct relationship between analog input and PWM output
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, adcValue);
// Small delay to stabilize the system and prevent overwhelming the ADC
HAL_Delay(1);
}
}
HAL_Init()
: Initializes hardware abstraction layer (HAL) libraries.SystemClock_Config()
: Sets up the system clock (CPU speed).The complete STM32CubeIDE project (including .ioc
configuration, main.c
, and HAL files) is available here
📥Download Project
We are using the ESP32 DevKit v4 development board and programming it using the Arduino IDE.
PWM Options on ESP32
Among these, the LEDC (LED Controller) peripheral is a dedicated hardware PWM controller, optimized for applications like LED brightness control, and we will use it in this task.
In Arduino Core v2.x for ESP32, LEDC API functions like ledcSetup()
and ledcAttachPin()
are used for PWM configuration.
In Arduino Core v3.x, these functions are removed to avoid compilation errors, use the updated LEDC API instead; otherwise, you will encounter a compilation error. e.g.:
ledcAttach(pin, freq, resolution);
ledcWrite(channel, dutyCycle);
Reference: ESP32 Arduino Core 2.x → 3.0 Migration Guide
Circuit Diagram
Code
#define LED_PIN 14
#define POT_PIN 34
void setup() {
Serial.begin(115200);
// Attach the LED pin with PWM frequency 1 kHz and 12-bit resolution
ledcAttach(LED_PIN, 1000, 12);
// Set ADC resolution to 12 bits (0–4095)
analogReadResolution(12);
// Start with LED OFF (duty = 0)
ledcWrite(LED_PIN, 0);
}
void loop() {
// Read the potentiometer value (0–4095 for 12-bit ADC)
int pot_value = analogRead(POT_PIN);
// Write the ADC value directly as PWM duty cycle (0–4095)
ledcWrite(LED_PIN, pot_value);
delay(1); // Small delay for stability
}
We are using the Arduino UNO development board and programming it using the Arduino IDE.
In Arduino UNO, we have to control LED brightness using PWM(8-bit) by providing values from 0 to 255.
ADC (10-bit) will provide us with the value from 0 to 1023, so we need to map the ADC value to the PWM brightness value.
To map the ADC value with PWM, we are going to use two methods.
Method-1
We can do it by using the default function map();
We can provide the ADC and PWM ranges, so this function returns the proper mapping value accordingly.
Code(Method 1):
#define POT_PIN A0 // potentiometer is connected to A0 pin
#define LED_PIN 9 // LED is connected to pin no.9
void setup() {
pinMode(LED_PIN , OUTPUT); // Set the LED pin as an output
}
void loop() {
int adcValue = analogRead(POT_PIN); // Read the analog value from pin A0 (range: 0–1023)
// Read the potentiometer value (0-1023) and map it to the PWM range (0-255)
int brightness = map(adcValue, 0, 1023, 0, 255);
// Adjust the LED brightness
analogWrite(LED_PIN, brightness);
}
So as we can see, in the above map function, we have passed a total of 5 parameters, from which the ADC_value will be converted from Range (0-1023) to (0-255).
Method-2
We can calculate the mapping factor,
Mapping Factor = ADC Value / corresponding PWM value
= 1024 / 256
= 4
So whatever ADC value we receive, dividing it by 4 will give us the corresponding PWM value.
Code(Method 2):
#define POT_PIN A0 // potentiometer is connected to A0 pin
#define LED_PIN 9 // LED is connected to pin no.9
void setup() {
pinMode(LED_PIN, OUTPUT); // Configure pin 9 as an output to control the LED
}
void loop() {
// Read the analog value from pin A0 (range: 0–1023)
// The potentiometer adjusts this value based on its position
int adcValue = analogRead(POT_PIN);
// Map the potentiometer value (0–1023) to the PWM range (0–255)
// Dividing by 4 is equivalent to the mapping (1023 / 255 = ~4)
int brightness = adcValue / 4;
// Write the mapped brightness value to the LED
// This controls the LED brightness proportionally to the potentiometer position
analogWrite(LED_PIN, brightness);
}