📊 hal::pwm
Pulse Width Modulation - PWM Sinyal Üretimi
~320 satır
~12 fonksiyon
STM32/GD32/ESP32
📖 Genel Bakış
PWM modülü, timer donanımını kullanarak değişken genişlikli dijital sinyaller üretir. Motor hız kontrolü, LED parlaklık ayarı, servo kontrol ve analog çıkış simülasyonu için kullanılır.
🔑 Temel Özellikler
- Konfigüre edilebilir frekans (1 Hz - 1 MHz+)
- 0-100% duty cycle kontrolü
- Çoklu kanal desteği (4 kanala kadar)
- Complementary output (dead-time ile)
- Hardware sync ve trigger
- DMA destekli dalga formu üretimi
- One-pulse mode
- Encoder interface mode
🚀 Hızlı Başlangıç
içe_aktar hal::pwm, hal::gpio
// PWM pin setup (TIM3 CH1 -> PA6)
gpio.pin_init(gpio.PORT_A, 6, yap
mode: gpio.MODE_AF,
af: gpio.AF2_TIM3
son)
// PWM initialization (1 kHz, 50% duty)
değişken pwm_handle = pwm.init(pwm.TIM3, pwm.CHANNEL_1, yap
frequency: 1000, // 1 kHz
duty_cycle: 50, // 50%
polarity: pwm.ACTIVE_HIGH,
mode: pwm.MODE_PWM1
son)
// Start PWM
pwm.start(pwm_handle)
// Update duty cycle
pwm.set_duty_cycle(pwm_handle, 75) // 75%
📦 Tipler ve Enum'lar
// Timer Seçimi
enum Timer {
TIM1, TIM2, TIM3, TIM4, TIM5,
TIM8, TIM9, TIM10, TIM11, TIM12
}
// PWM Kanalları
enum Channel {
CHANNEL_1, CHANNEL_2, CHANNEL_3, CHANNEL_4
}
// PWM Modları
enum Mode {
PWM1, // Active when CNT < CCR
PWM2 // Active when CNT > CCR
}
// Polarity
enum Polarity {
ACTIVE_HIGH, // High is active
ACTIVE_LOW // Low is active
}
// Alignment Mode
enum Alignment {
EDGE, // Edge-aligned
CENTER1, // Center-aligned mode 1
CENTER2, // Center-aligned mode 2
CENTER3 // Center-aligned mode 3
}
yapı PWMConfig yap
frequency: sayı, // Hz (1-1000000)
duty_cycle: kesir, // 0.0-100.0
polarity: Polarity,
mode: Mode,
alignment: Alignment
son
💡 Örnek 1: LED Dimming (Parlaklık Kontrolü)
LED parlaklığını PWM ile kontrol etme
içe_aktar hal::pwm, hal::core
fonksiyon led_dimmer() yap
// PWM setup (10 kHz)
değişken led_pwm = pwm.init(pwm.TIM2, pwm.CHANNEL_1, yap
frequency: 10000,
duty_cycle: 0,
polarity: pwm.ACTIVE_HIGH,
mode: pwm.MODE_PWM1
son)
pwm.start(led_pwm)
// Fade in/out loop
döngü yap
// Fade in (0% -> 100%)
için brightness içinde 0..100 için yap
pwm.set_duty_cycle(led_pwm, brightness.kesir())
core.delay_ms(10)
son
core.delay_ms(500)
// Fade out (100% -> 0%)
için brightness içinde (0..100).reverse() için yap
pwm.set_duty_cycle(led_pwm, brightness.kesir())
core.delay_ms(10)
son
core.delay_ms(500)
son
son
💡 Örnek 2: DC Motor Hız Kontrolü
L298N sürücüsü ile motor kontrolü
içe_aktar hal::pwm, hal::gpio
yapı Motor yap
pwm: PWMHandle,
dir_pin1: GPIOPin,
dir_pin2: GPIOPin
son
fonksiyon motor_init() -> Motor yap
// Direction pins
değişken in1 = gpio.pin_init(gpio.PORT_B, 0, gpio.MODE_OUTPUT)
değişken in2 = gpio.pin_init(gpio.PORT_B, 1, gpio.MODE_OUTPUT)
// PWM for speed (20 kHz)
değişken motor_pwm = pwm.init(pwm.TIM1, pwm.CHANNEL_1, yap
frequency: 20000,
duty_cycle: 0,
polarity: pwm.ACTIVE_HIGH,
mode: pwm.MODE_PWM1
son)
pwm.start(motor_pwm)
dön Motor yap
pwm: motor_pwm,
dir_pin1: in1,
dir_pin2: in2
son
son
fonksiyon motor_set_speed(motor: Motor, speed: kesir) yap
// speed: -100 to +100 (negative = reverse)
eğer speed > 0 ise yap
// Forward
gpio.pin_write(motor.dir_pin1, gpio.HIGH)
gpio.pin_write(motor.dir_pin2, gpio.LOW)
pwm.set_duty_cycle(motor.pwm, speed)
yoksa eğer speed < 0 ise yap
// Reverse
gpio.pin_write(motor.dir_pin1, gpio.LOW)
gpio.pin_write(motor.dir_pin2, gpio.HIGH)
pwm.set_duty_cycle(motor.pwm, -speed)
yoksa yap
// Stop
gpio.pin_write(motor.dir_pin1, gpio.LOW)
gpio.pin_write(motor.dir_pin2, gpio.LOW)
pwm.set_duty_cycle(motor.pwm, 0.0)
son
son
fonksiyon ana() yap
değişken motor = motor_init()
// Acceleration test
için speed içinde 0..100 için yap
motor_set_speed(motor, speed.kesir())
core.delay_ms(50)
son
core.delay_ms(2000)
// Deceleration
için speed içinde (0..100).reverse() için yap
motor_set_speed(motor, speed.kesir())
core.delay_ms(50)
son
motor_set_speed(motor, 0.0) // Stop
son
💡 Örnek 3: Servo Motor Kontrolü (SG90)
50Hz PWM ile servo açı kontrolü
içe_aktar hal::pwm
yapı Servo yap
pwm: PWMHandle,
min_pulse: kesir, // ms
max_pulse: kesir // ms
son
fonksiyon servo_init(timer: Timer, channel: Channel) -> Servo yap
// Servo: 50Hz, 1-2ms pulse width
değişken servo_pwm = pwm.init(timer, channel, yap
frequency: 50, // 50 Hz (20ms period)
duty_cycle: 7.5, // 1.5ms pulse (90°)
polarity: pwm.ACTIVE_HIGH,
mode: pwm.MODE_PWM1
son)
pwm.start(servo_pwm)
dön Servo yap
pwm: servo_pwm,
min_pulse: 1.0, // 1ms = 0°
max_pulse: 2.0 // 2ms = 180°
son
son
fonksiyon servo_set_angle(servo: Servo, angle: kesir) yap
// angle: 0-180 degrees
değişken clamped = angle.clamp(0.0, 180.0)
// Map angle to pulse width (1-2ms)
değişken pulse_ms = servo.min_pulse +
(clamped / 180.0) * (servo.max_pulse - servo.min_pulse)
// Convert to duty cycle (20ms period)
değişken duty = (pulse_ms / 20.0) * 100.0
pwm.set_duty_cycle(servo.pwm, duty)
son
fonksiyon ana() yap
değişken servo = servo_init(pwm.TIM2, pwm.CHANNEL_1)
// Sweep 0° to 180°
döngü yap
için angle içinde 0..180 için yap
servo_set_angle(servo, angle.kesir())
core.delay_ms(15)
son
için angle içinde (0..180).reverse() için yap
servo_set_angle(servo, angle.kesir())
core.delay_ms(15)
son
son
son
💡 Örnek 4: Buzzer Melodi Çalma
PWM frekans değiştirerek nota üretme
içe_aktar hal::pwm, hal::core
// Note frequencies (Hz)
sabit DO = 262
sabit RE = 294
sabit MI = 330
sabit FA = 349
sabit SOL = 392
sabit LA = 440
sabit SI = 494
sabit DO_HIGH = 523
fonksiyon buzzer_init() -> PWMHandle yap
değişken buzzer = pwm.init(pwm.TIM3, pwm.CHANNEL_2, yap
frequency: 440, // Default: LA (440 Hz)
duty_cycle: 50,
polarity: pwm.ACTIVE_HIGH,
mode: pwm.MODE_PWM1
son)
dön buzzer
son
fonksiyon play_tone(buzzer: PWMHandle, freq: sayı, duration_ms: sayı) yap
pwm.set_frequency(buzzer, freq)
pwm.start(buzzer)
core.delay_ms(duration_ms)
pwm.stop(buzzer)
son
fonksiyon play_melody(buzzer: PWMHandle) yap
// "Twinkle Twinkle Little Star"
değişken melody = [
(DO, 500), (DO, 500), (SOL, 500), (SOL, 500),
(LA, 500), (LA, 500), (SOL, 1000),
(FA, 500), (FA, 500), (MI, 500), (MI, 500),
(RE, 500), (RE, 500), (DO, 1000)
]
her (note, duration) içinde melody için yap
play_tone(buzzer, note, duration)
core.delay_ms(50) // Short pause between notes
son
son
fonksiyon ana() yap
değişken buzzer = buzzer_init()
döngü yap
play_melody(buzzer)
core.delay_ms(2000)
son
son
📊 API Referansı
Initialization
fonksiyon init(timer: Timer, channel: Channel, config: PWMConfig) -> PWMHandle
fonksiyon deinit(handle: PWMHandle)
fonksiyon start(handle: PWMHandle)
fonksiyon stop(handle: PWMHandle)
Configuration
fonksiyon set_duty_cycle(handle: PWMHandle, duty: kesir) // 0.0-100.0
fonksiyon get_duty_cycle(handle: PWMHandle) -> kesir
fonksiyon set_frequency(handle: PWMHandle, freq: sayı) // Hz
fonksiyon get_frequency(handle: PWMHandle) -> sayı
fonksiyon set_polarity(handle: PWMHandle, pol: Polarity)
Advanced
fonksiyon set_pulse_width(handle: PWMHandle, width_us: sayı) // Microseconds
fonksiyon enable_complementary(handle: PWMHandle, deadtime_ns: sayı)
fonksiyon set_phase_shift(handle: PWMHandle, phase_degrees: kesir)
fonksiyon configure_dma(handle: PWMHandle, buffer: Dizi[sayı])
⚙️ Platform Desteği
| Platform | Timers | Max Freq | Resolution |
|---|---|---|---|
| STM32F4 | TIM1-14 | 84 MHz | 16-bit |
| STM32F1 | TIM1-4 | 72 MHz | 16-bit |
| ESP32 | LEDC 0-7 | 40 MHz | 20-bit |
| GD32VF103 | TIM0-6 | 108 MHz | 16-bit |
💡 Best Practices
- Frekans seçimi: Motor kontrolü için 20-25 kHz (insan işitme aralığı dışı)
- Servo kontrol: 50 Hz sabit frekans, 1-2ms pulse genişliği
- LED dimming: 100+ Hz (göz yanıp sönmeyi algılamaz)
- Timer çakışması: Aynı timer'ın farklı kanallarını kullanın
- Dead-time: H-bridge kontrolünde shoot-through önlemek için gerekli
🔗 İlgili Modüller
- hal::timer - Hardware timer (PWM'in temeli)
- hal::gpio - GPIO AF configuration
- hal::dma - DMA-based waveform generation