📊 hal::pwm

Pulse Width Modulation - PWM Sinyal Üretimi

~320 lines ~12 function STM32/GD32/ESP32

📖 Overview

PWM modülü, timer donanımını kullanarak let genişlikli dijital sinyaller üretir. Motor hız kontrolü, LED parlaklık ayarı, servo kontrol ve analog çıkış simülasyonu for kullanılır.

🔑 Key Features

🚀 Quick Start

import hal::pwm, hal::gpio

// PWM pin setup (TIM3 CH1 -> PA6)
gpio.pin_init(gpio.PORT_A, 6, do
    mode: gpio.MODE_AF,
    af: gpio.AF2_TIM3
end)

// PWM initialization (1 kHz, 50% duty)
let pwm_handle = pwm.init(pwm.TIM3, pwm.CHANNEL_1, do
    frequency: 1000,      // 1 kHz
    duty_cycle: 50,       // 50%
    polarity: pwm.ACTIVE_HIGH,
    mode: pwm.MODE_PWM1
end)

// 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
}

struct PWMConfig do
    frequency: int,        // Hz (1-1000000)
    duty_cycle: float,      // 0.0-100.0
    polarity: Polarity,
    mode: Mode,
    alignment: Alignment
end

💡 Example 1: LED Dimming (Parlaklık Kontrolü)

LED parlaklığını PWM ile kontrol etme

import hal::pwm, hal::core

function led_dimmer() do
    // PWM setup (10 kHz)
    let led_pwm = pwm.init(pwm.TIM2, pwm.CHANNEL_1, do
        frequency: 10000,
        duty_cycle: 0,
        polarity: pwm.ACTIVE_HIGH,
        mode: pwm.MODE_PWM1
    end)
    
    pwm.start(led_pwm)
    
    // Fade in/out loop
    loop do
        // Fade in (0% -> 100%)
        for brightness in 0..100 for do
            pwm.set_duty_cycle(led_pwm, brightness.float())
            core.delay_ms(10)
        end
        
        core.delay_ms(500)
        
        // Fade out (100% -> 0%)
        for brightness in (0..100).reverse() for do
            pwm.set_duty_cycle(led_pwm, brightness.float())
            core.delay_ms(10)
        end
        
        core.delay_ms(500)
    end
end

💡 Example 2: DC Motor Hız Kontrolü

L298N sürücüsü ile motor kontrolü

import hal::pwm, hal::gpio

struct Motor do
    pwm: PWMHandle,
    dir_pin1: GPIOPin,
    dir_pin2: GPIOPin
end

function motor_init() -> Motor do
    // Direction pins
    let in1 = gpio.pin_init(gpio.PORT_B, 0, gpio.MODE_OUTPUT)
    let in2 = gpio.pin_init(gpio.PORT_B, 1, gpio.MODE_OUTPUT)
    
    // PWM for speed (20 kHz)
    let motor_pwm = pwm.init(pwm.TIM1, pwm.CHANNEL_1, do
        frequency: 20000,
        duty_cycle: 0,
        polarity: pwm.ACTIVE_HIGH,
        mode: pwm.MODE_PWM1
    end)
    
    pwm.start(motor_pwm)
    
    return Motor do
        pwm: motor_pwm,
        dir_pin1: in1,
        dir_pin2: in2
    end
end

function motor_set_speed(motor: Motor, speed: float) do
    // speed: -100 to +100 (negative = reverse)
    if speed > 0  do
        // Forward
        gpio.pin_write(motor.dir_pin1, gpio.HIGH)
        gpio.pin_write(motor.dir_pin2, gpio.LOW)
        pwm.set_duty_cycle(motor.pwm, speed)
    else if speed < 0  do
        // Reverse
        gpio.pin_write(motor.dir_pin1, gpio.LOW)
        gpio.pin_write(motor.dir_pin2, gpio.HIGH)
        pwm.set_duty_cycle(motor.pwm, -speed)
    else do
        // 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)
    end
end

function ana() do
    let motor = motor_init()
    
    // Acceleration test
    for speed in 0..100 for do
        motor_set_speed(motor, speed.float())
        core.delay_ms(50)
    end
    
    core.delay_ms(2000)
    
    // Deceleration
    for speed in (0..100).reverse() for do
        motor_set_speed(motor, speed.float())
        core.delay_ms(50)
    end
    
    motor_set_speed(motor, 0.0)  // Stop
end

💡 Example 3: Servo Motor Kontrolü (SG90)

50Hz PWM ile servo açı kontrolü

import hal::pwm

struct Servo do
    pwm: PWMHandle,
    min_pulse: float,  // ms
    max_pulse: float   // ms
end

function servo_init(timer: Timer, channel: Channel) -> Servo do
    // Servo: 50Hz, 1-2ms pulse width
    let servo_pwm = pwm.init(timer, channel, do
        frequency: 50,      // 50 Hz (20ms period)
        duty_cycle: 7.5,    // 1.5ms pulse (90°)
        polarity: pwm.ACTIVE_HIGH,
        mode: pwm.MODE_PWM1
    end)
    
    pwm.start(servo_pwm)
    
    return Servo do
        pwm: servo_pwm,
        min_pulse: 1.0,  // 1ms = 0°
        max_pulse: 2.0   // 2ms = 180°
    end
end

function servo_set_angle(servo: Servo, angle: float) do
    // angle: 0-180 degrees
    let clamped = angle.clamp(0.0, 180.0)
    
    // Map angle to pulse width (1-2ms)
    let pulse_ms = servo.min_pulse + 
        (clamped / 180.0) * (servo.max_pulse - servo.min_pulse)
    
    // Convert to duty cycle (20ms period)
    let duty = (pulse_ms / 20.0) * 100.0
    
    pwm.set_duty_cycle(servo.pwm, duty)
end

function ana() do
    let servo = servo_init(pwm.TIM2, pwm.CHANNEL_1)
    
    // Sweep 0° to 180°
    loop do
        for angle in 0..180 for do
            servo_set_angle(servo, angle.float())
            core.delay_ms(15)
        end
        
        for angle in (0..180).reverse() for do
            servo_set_angle(servo, angle.float())
            core.delay_ms(15)
        end
    end
end

💡 Example 4: Buzzer Melodi Çalma

PWM frekans değiştirerek nota üretme

import hal::pwm, hal::core

// Note frequencies (Hz)
const DO = 262
const RE = 294
const MI = 330
const FA = 349
const SOL = 392
const LA = 440
const SI = 494
const DO_HIGH = 523

function buzzer_init() -> PWMHandle do
    let buzzer = pwm.init(pwm.TIM3, pwm.CHANNEL_2, do
        frequency: 440,  // Default: LA (440 Hz)
        duty_cycle: 50,
        polarity: pwm.ACTIVE_HIGH,
        mode: pwm.MODE_PWM1
    end)
    
    return buzzer
end

function play_tone(buzzer: PWMHandle, freq: int, duration_ms: int) do
    pwm.set_frequency(buzzer, freq)
    pwm.start(buzzer)
    core.delay_ms(duration_ms)
    pwm.stop(buzzer)
end

function play_melody(buzzer: PWMHandle) do
    // "Twinkle Twinkle Little Star"
    let 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) in melody for do
        play_tone(buzzer, note, duration)
        core.delay_ms(50)  // Short pause between notes
    end
end

function ana() do
    let buzzer = buzzer_init()
    
    loop do
        play_melody(buzzer)
        core.delay_ms(2000)
    end
end

📊 API Referansı

Initialization

function init(timer: Timer, channel: Channel, config: PWMConfig) -> PWMHandle
function deinit(handle: PWMHandle)
function start(handle: PWMHandle)
function stop(handle: PWMHandle)

Configuration

function set_duty_cycle(handle: PWMHandle, duty: float)  // 0.0-100.0
function get_duty_cycle(handle: PWMHandle) -> float
function set_frequency(handle: PWMHandle, freq: int)  // Hz
function get_frequency(handle: PWMHandle) -> int
function set_polarity(handle: PWMHandle, pol: Polarity)

Advanced

function set_pulse_width(handle: PWMHandle, width_us: int)  // Microseconds
function enable_complementary(handle: PWMHandle, deadtime_ns: int)
function set_phase_shift(handle: PWMHandle, phase_degrees: float)
function configure_dma(handle: PWMHandle, buffer: Dizi[int])

⚙️ Platform Desteği

PlatformTimersMax FreqResolution
STM32F4TIM1-1484 MHz16-bit
STM32F1TIM1-472 MHz16-bit
ESP32LEDC 0-740 MHz20-bit
GD32VF103TIM0-6108 MHz16-bit

💡 Best Practices

🔗 Related Modules

← HAL Modules | 🇬🇧 Turkish