Practical Implementation of PWM Dimming

Why is PWM dimming considered the “dragon-slaying sword” for electronics enthusiasts? Imagine your LED lights can achieve stepless dimming from a dim candlelight to bright daylight, just like a smartphone screen, by sliding a button. It can even simulate the romantic effect of a breathing light. All of this relies on a magical electronic technique—PWM dimming. It acts like an “intelligent brain” for LEDs, controlling brightness through rapid switching, making it both energy-efficient and eye-friendly. Today, we will start from scratch and practice with the STM32 microcontroller to teach you how to turn a regular LED into a “dimming master”!

1. Basic Concept: What is PWM Dimming?

Analogy Explanation: Imagine you quickly turn a flashlight on and off (more than 100 times per second); although the light is “blinking”, the human eye perceives it as a soft glow. PWM dimming utilizes this principle by changing the ratio of “on” and “off” time (duty cycle) to control brightness.Key Parameters:

  • Duty Cycle: The ratio of high-level time to the entire cycle (e.g., 50% means equal “on” and “off”).
  • Frequency: The switching speed (recommended above 1kHz, otherwise you may see flickering or hear noise).

2. Hardware Practice: Step-by-Step Dimming Circuit Setup

1. Component List (Cost under 5 yuan)

  • STM32F103C8T6 core board (about 20 yuan)
  • LED (recommended 0603 package, 20mA current)
  • 220Ω resistor (to prevent LED burnout)
  • Several Dupont wires
  • Breadboard + header pins

2. Wiring Diagram (with Key Annotations)

STM32 PA8 (PWM output) → 220Ω resistor → LED anode → GND
          LED cathode left floating (controlled by PWM)

Note:

  • If using high-power LEDs, a MOSFET driver (e.g., IRF540N) is required.
  • Use a multimeter to measure the actual current, ensuring it does not exceed 20mA.

3. Code Practice: Three Steps to Light Up the “Smart LED”

// Initialize Timer 3 in PWM mode (STM32 HAL library)
void PWM_Init(void) {
    TIM_HandleTypeDef htim3;
    __HAL_RCC_TIM3_CLK_ENABLE();  // Enable clock (hard lesson: forgetting this step will prevent lighting up!)
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 7199;  // After division, frequency = 72MHz/7200 ≈ 1kHz
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 999;      // Duty cycle = CCR/1000 (0-1000 corresponds to 0-100%)
    HAL_TIM_PWM_Init(&htim3);
    TIM_OC_InitTypeDef sConfigOC = {0};
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 300;          // Initial 30% brightness
    HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
}

Code Explanation:

  • <span>TIM3</span> timer is configured for a 1kHz frequency,<span>CCR</span> value determines the duty cycle.
  • Modify the<span>HAL_TIM_PWM_Start</span> before the<span>Pulse</span> value to adjust brightness (e.g., 500=50%).

4. Advanced Techniques: Breathing Light & Gradient Effects

1. Breathing Light (Code Snippet)

void Breath_LED(void) {
    static uint16_t duty = 0;
    duty += 5;  // Adjusting the step value can change the breathing speed
    if (duty &gt; 999) duty = 0;
    __HAL_TIM_SET_COMPARE(&amp;htim3, TIM_CHANNEL_1, duty);
}

Effect: The LED cycles from dark to bright and back, suitable for ambient lighting.

2. Gradient Dimming (Using ADC)

Read the voltage value from a potentiometer to convert it into a duty cycle:

uint16_t adc_value = HAL_ADC_GetValue(&amp;hadc1);
uint16_t duty = (adc_value * 999) / 4095;  // 4095 corresponds to the maximum ADC value

Advanced Applications:

  • Smart temperature-controlled fan (using temperature sensor + PWM speed control).
  • Garage light automatic sensing (combined with human infrared sensor).

5. Pitfall Guide: Common Mistakes 90% of People Make!

  1. Wrong Frequency Selection: Below 100Hz will cause flickering, above 20kHz may cause whistling.
  2. Sudden Duty Cycle Change: Jumping directly from 0 to 100% will cause the LED to flicker; use linear interpolation for smooth transitions.
  3. Insufficient Drive: Directly driving high-power LEDs from IO ports can damage the chip; a MOSFET is needed.
  4. Forgetting Power Initialization: Timer configuration must be completed after<span>HAL_Init()</span><span>.</span>

6. PLC Perspective: The “Twin Brother” of Industrial Dimming

In PLCs, PWM dimming corresponds tohigh-frequency switching control of output terminals. For example, Mitsubishi PLC uses<span>PWM</span> instructions to achieve soft start of motors by setting the cycle and duty cycle; Siemens PLC adjusts the output of inverters through<span>SFB41</span> function blocks. The core logic of both is:using digital signals to simulate analog control.

Practical Suggestions (Bonus at the End)

  1. Hardware Replacement: Try replacing STM32 with Arduino Nano or ESP32 to compare PWM accuracy across different chips.
  2. Algorithm Optimization: Use PID algorithms for seamless dimming (refer to the brightness feedback mechanism on the website).
  3. Safety First: Wear safety goggles while debugging to avoid direct eye contact with bright LEDs; use an oscilloscope to observe whether the PWM waveform is regular.

Random Thoughts: Last year, I modified the lighting in a client’s machine room using PLC + PWM for zoned dimming, only to find that EMI interference caused the PLC to crash frequently. In the end, I added a ferrite filter to solve the problem—hardware design is always harder to debug than code! Next time, I will teach you how to use PWM for motor speed control; I used this principle to solve the laboratory centrifuge issue… (manual dog head)

Leave a Comment