PWM ve analogWrite
Arduino’nun dijital pinleri yalnızca 0 V veya 5 V verebilir. Peki bir LED’i yarı parlaklıkta yakmak veya bir motoru yarı hızda döndürmek nasıl mümkün oluyor?
Cevap PWM (Pulse Width Modulation — Darbe Genişlik Modülasyonu).
PWM Nasıl Çalışır?
PWM, pini çok hızlı bir şekilde açıp kapatarak ortalama gerilimi değiştirir.
Bir saniyede yüzlerce kez açılıp kapanan bir LED’i göz sürekli yanıyor gibi algılar. Ancak açık kalma süresi kısaltılırsa LED daha sönük görünür.
Anahtar kavram duty cycle (görev döngüsü): sinyalin bir periyot içinde ne kadar süre HIGH kaldığının yüzdesidir.
| Duty cycle | Ortalama gerilim (5 V’ta) | analogWrite değeri |
|---|---|---|
| %0 | 0 V | 0 |
| %25 | 1,25 V | 64 |
| %50 | 2,5 V | 127 |
| %75 | 3,75 V | 191 |
| %100 | 5 V | 255 |
analogWrite() Kullanımı
analogWrite(pin, deger); // deger: 0 - 255İsmine rağmen bu fonksiyon gerçek analog çıkış üretmez; PWM sinyali üretir. Bu ayrımın neden önemli olduğunu aşağıda açıklıyoruz.
const int LED_PIN = 9;
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// Yavasca parlaklasma
for (int i = 0; i <= 255; i++) {
analogWrite(LED_PIN, i);
delay(8);
}
// Yavasca sonme
for (int i = 255; i >= 0; i--) {
analogWrite(LED_PIN, i);
delay(8);
}
}Hangi Pinler PWM Destekler?
Kart üzerinde ~ işaretiyle gösterilen pinler.
| Kart | PWM pinleri |
|---|---|
| Arduino Uno / Nano | 3, 5, 6, 9, 10, 11 |
| Arduino Mega | 2 – 13, 44, 45, 46 |
| Arduino Leonardo | 3, 5, 6, 9, 10, 11, 13 |
| ESP8266 | Tüm GPIO pinleri (yazılımsal PWM) |
| ESP32 | 16 kanal, herhangi bir GPIO’ya atanabilir |
PWM desteklemeyen bir pinde analogWrite() çağırmak yalnızca 128’in altı için LOW, üstü için HIGH etkisi yapar.
PWM Frekansı
Arduino Uno’da PWM frekansı pine göre değişir:
| Pinler | Frekans | Timer |
|---|---|---|
| 5, 6 | ~980 Hz | Timer0 |
| 9, 10 | ~490 Hz | Timer1 |
| 3, 11 | ~490 Hz | Timer2 |
Bu frekanslar işitme aralığındadır. Bu yüzden PWM ile sürülen bir motor veya trafo ıslık gibi öter.
Frekansı 20 kHz üzerine çıkarmak sesi duyulmaz hale getirir, ancak bu timer register’larını doğrudan değiştirmeyi gerektirir. Timer0’a dokunmak millis() ve delay() fonksiyonlarını bozar; dokunacaksanız Timer1 veya Timer2’yi tercih edin.
ESP32’de PWM (LEDC)
ESP32’de analogWrite() yoktur (bazı çekirdek sürümlerinde eklenmiştir). Yerine LEDC birimi kullanılır ve frekans ile çözünürlük ayarlanabilir:
const int LED_PIN = 5;
const int KANAL = 0;
const int FREKANS = 5000; // 5 kHz
const int COZUNURLUK = 8; // 8 bit -> 0-255
void setup() {
ledcSetup(KANAL, FREKANS, COZUNURLUK);
ledcAttachPin(LED_PIN, KANAL);
}
void loop() {
for (int i = 0; i <= 255; i++) {
ledcWrite(KANAL, i);
delay(8);
}
}12 bit çözünürlük seçerseniz değer aralığı 0–4095 olur; çok daha ince parlaklık kontrolü sağlar.
PWM Gerçek Analog Çıkış Değildir
Bu ayrım, birçok kafa karışıklığının kaynağıdır.
PWM çıkışı hâlâ kare dalgadır: sürekli 0 V ile 5 V arasında gidip gelir. Ortalaması istediğiniz değere eşittir, ama anlık gerilim asla ara bir değerde değildir.
Ne zaman sorun olmaz?
- LED parlaklığı — göz ortalar
- Motor hızı — motorun ataleti ortalar
- Isıtıcı gücü — ısıl atalet ortalar
Ne zaman sorun olur?
- Bir sensöre veya op-amp’a referans gerilim vermek
- Ses sinyali üretmek
- Bir devrenin besleme gerilimini ayarlamak
Bu durumlarda gerçek analog gerilim gerekir. İki yol vardır:
1. RC alçak geçiren filtre. PWM çıkışına seri direnç ve GND’ye kondansatör eklemek dalgayı düzleştirir:
PWM pini ──[ 10 kΩ ]──┬── analog çıkış
│
[100 nF]
│
GNDFiltre çıkışı yavaş tepki verir ve akım veremez; bir op-amp tampon eklemek gerekebilir.
2. Gerçek DAC kullanmak. MCP4725 (I2C, 12 bit) gibi bir DAC entegresi gerçek analog gerilim üretir. ESP32’nin GPIO25 ve GPIO26 pinlerinde dahili DAC bulunur.
Motor Hızı Kontrolü
PWM’in en yaygın kullanımlarından biridir.
const int MOTOR_PWM = 9;
const int MOTOR_IN1 = 8;
const int MOTOR_IN2 = 7;
void motorSur(int hiz) { // -255 ile +255 arasi
bool ileri = hiz >= 0;
int pwm = constrain(abs(hiz), 0, 255);
digitalWrite(MOTOR_IN1, ileri ? HIGH : LOW);
digitalWrite(MOTOR_IN2, ileri ? LOW : HIGH);
analogWrite(MOTOR_PWM, pwm);
}
void loop() {
motorSur(150); // ileri, orta hiz
delay(2000);
motorSur(0); // dur
delay(1000);
motorSur(-200); // geri, hizli
delay(2000);
}Motor düşük PWM’de dönmüyor
Motorun sürtünmeyi yenmesi için minimum bir torka ihtiyacı vardır. PWM değeri genellikle 60–100’ün altında motor sadece titrer ve ısınır.
Çözüm, kısa bir tam güç darbesiyle motoru başlatmaktır:
void motorBaslat(int hiz) {
analogWrite(MOTOR_PWM, 255);
delay(50);
analogWrite(MOTOR_PWM, hiz);
}Alternatif olarak, kullanılabilir aralığı ölçekleyin:
int gercekPwm = map(istenenHiz, 1, 100, 80, 255); // %1 bile motoru dondursunLED Parlaklığı ve Göz Algısı
İnsan gözü ışığı logaritmik algılar. analogWrite(128) değeri, elektriksel olarak yarı güç demektir ama göze yarı parlaklık gibi görünmez — çok daha parlak görünür.
Doğrusal görünen bir sönme efekti için değeri karesel ölçekleyin:
void ledParlaklik(int pin, int yuzde) { // 0-100
int deger = (yuzde * yuzde) * 255 / 10000;
analogWrite(pin, deger);
}Bu, LED animasyonlarını gözle görülür şekilde daha doğal hale getirir.
Timer Çakışmaları
analogWrite() timer donanımını kullanır ve bazı kütüphaneler aynı timer’ları paylaşır:
| Kütüphane | Etkilediği PWM pinleri |
|---|---|
Servo | D9, D10 çalışmaz |
tone() | D3, D11 bozulur |
Servo ve buzzer kullanan bir projede PWM için D5 veya D6 tercih edin.
Özet
PWM, pini çok hızlı açıp kapatarak ortalama gerilimi değiştiren bir tekniktir. analogWrite(pin, 0–255) ile kullanılır ve yalnızca ~ işaretli pinlerde çalışır.
Bu derste şunları öğrendik:
- Duty cycle kavramını ve 0–255 karşılıklarını
- Hangi pinlerin PWM desteklediğini
- PWM frekansını ve motorların neden ıslık çaldığını
- PWM’in gerçek analog çıkış olmadığını, RC filtre ve DAC alternatiflerini
- Motor hız kontrolünü ve düşük PWM sorununu
- Göz algısına uygun karesel parlaklık ölçeklemesini
- Servo ve
tone()ile timer çakışmalarını