Parçalar · 12 dk okuma

DFPlayer Mini Arduino Kullanımı: MP3 Çalma, SD Kart ve Hoparlör

DFPlayer Mini Arduino'ya nasıl bağlanır? RX'e 1k direnç, SD kart ve 0001.mp3 adlandırma, kütüphane kodu, butonla parça, hoparlör, ESP32 ve Pico örneği.

DFPlayer Mini, Arduino ile MP3 çalmanın en ucuz ve en kolay yoludur: microSD karttaki ses dosyalarını kendi başına çözer, üzerindeki küçük amfiyle bir hoparlörü doğrudan sürer ve Arduino'dan yalnızca iki kabloluk bir seri bağlantıyla komut alır. Buzzer'ın bip seslerinin aksine şarkı, konuşma, kapı zili melodisi ya da "Kapı açık kaldı" gibi sesli uyarılar çalabilirsin. Modülü ilk kez bağlayanların çoğu aynı sorunlarla karşılaşır: ses gelmez, hoparlör cızırdar, dosyalar yanlış sırada çalar ya da Seri Monitör'de "Unable to begin" yazar. Bu rehber bu sorunların hepsini nedenleriyle birlikte çözüyor.

Önce modülün pinlerini ve RX hattına neden 1 kΩ direnç konduğunu öğreneceksin. Ardından SD kartı FAT32 olarak hazırlamayı, dosyaları 0001.mp3 ve 01 klasörü düzeniyle adlandırmayı, DFRobotDFPlayerMini kütüphanesiyle ilk sesi çalmayı, ses seviyesini ve EQ'yu ayarlamayı, butonlarla parça değiştirmeyi ve doğru hoparlörü ya da harici amfiyi seçmeyi göreceksin. Son bölümlerde "Unable to begin" hatasının adım adım çözümü, ESP32 ile web sayfasından kontrol edilen bir MP3 çalar ve Raspberry Pi Pico için kütüphanesiz bir MicroPython örneği var. Yalnızca bip sesi ya da basit bir melodi yetiyorsa buzzer daha basit bir seçenektir.

DFPlayer Mini MP3 çalar modülü
DFPlayer Mini: yalnızca 20 × 20 mm boyutunda; microSD kart yuvası, MP3 çözücü yonga ve 3 W'a kadar hoparlör sürebilen küçük bir amfi içerir.

DFPlayer Mini nedir, nasıl çalışır?

DFPlayer Mini; MP3 çözücü (decoder) yonga, 24 bitlik DAC, microSD kart yuvası ve küçük bir mono amfiden oluşan, kendi başına çalışan bir MP3 çalardır. Arduino'nun görevi yalnızca "3 numaralı parçayı çal" ya da "sesi 20 yap" gibi kısa komutlar göndermektir; dosyayı karttan okumak, sıkıştırılmış sesi çözmek ve hoparlörü sürmek modülün işidir. Bu yüzden 2 KB RAM'li bir Arduino Uno bile rahatça müzik çalabilir. Komutlar 9600 baud hızında, her biri 10 bayttan oluşan paketlerle gönderilir; modül de bir parça bittiğinde, kart takılıp çıkarıldığında ya da bir hata olduğunda aynı biçimde bildirim yollar. Kartların üzerindeki yonga üreticiye göre değişir (YX5200-24SS, MH2024K-24SS, GD3200B gibi). Hepsi aynı komutları anlar ama yanıt süreleri farklı olabilir; bu ayrıntı ileride "Unable to begin" hatasında önemli olacak. Modül üç yolla yönetilebilir: seri port (UART), IO düğmeleri ve ADKEY direnç merdiveni.

ÖzellikDeğer
Desteklenen dosyalarMP3, WAV, WMA
Örnekleme hızı8 / 11,025 / 12 / 16 / 22,05 / 24 / 32 / 44,1 / 48 kHz
DAC24 bit; 90 dB dinamik aralık, 85 dB sinyal/gürültü oranı
DepolamamicroSD (TF) kart, en fazla 32 GB, FAT16 ya da FAT32; USB bellek desteği de vardır
Klasör kapasitesi100 klasöre kadar, klasör başına 255 dosya
Ses seviyesi30 kademe (0–30)
Ekolayzır (EQ)6 mod: Normal, Pop, Rock, Jazz, Classic, Bass
Hoparlör çıkışıDahili mono amfi, 3 W'tan küçük hoparlör
Hat çıkışıDAC_L ve DAC_R: stereo, kulaklık ya da harici amfi için
Besleme3,2–5,0 V (tipik 4,2 V)
Bekleme akımıYaklaşık 20 mA
HaberleşmeUART, 9600 baud, 8N1
Boyut20 × 20 mm

DFPlayer Mini pinleri

PinAdGörevi
1VCCBesleme girişi, 3,2–5,0 V
2RXSeri giriş: kartın TX pinine 1 kΩ dirençle bağlanır
3TXSeri çıkış: kartın RX pinine gider
4DAC_RSağ kanal hat çıkışı (kulaklık ya da amfi)
5DAC_LSol kanal hat çıkışı (kulaklık ya da amfi)
6 ve 8SPK_1, SPK_2Hoparlör çıkışı: 3 W'tan küçük hoparlörün iki ucu buraya bağlanır
7GNDToprak
9IO_1GND'ye kısa basış: önceki parça; uzun basış: ses azalır
10GNDToprak
11IO_2GND'ye kısa basış: sonraki parça; uzun basış: ses artar
12ADKEY1Direnç merdiveniyle çoklu buton girişi
13ADKEY2İkinci direnç merdiveni girişi
14USB+USB bellek için D+
15USB−USB bellek için D−
16BUSYÇalarken LOW, boştayken HIGH

Seri portla kullanırken yalnızca VCC, GND, RX, TX ve hoparlör pinleri gerekir. BUSY pini, parçanın bitip bitmediğini seri haberleşmeye gerek kalmadan anlamanı sağlar; kartın üzerindeki küçük LED de çalma sırasında yanar. IO_1 ve IO_2 pinleri ise modülün Arduino olmadan da çalışabilmesini sağlar: bu pinlerle GND arasına bağlanan birer butona kısa basınca parça değişir, uzun basınca ses ayarlanır. ADKEY pinlerine farklı değerli dirençlerle bağlanan butonlar da belirli parçaları çalabilir. Böylece pil, hoparlör ve iki butonla mikrodenetleyicisiz bir kapı zili ya da sesli oyuncak yapabilirsin. USB+ ve USB− pinleri SD kart yerine bir USB bellekten çalmak içindir ve çoğu projede boş kalır.

DFPlayer Mini Arduino bağlantısı ve RX hattındaki 1k direnç

DFPlayer piniArduino UnoESP32Raspberry Pi Pico
VCC5V5V (VIN)VBUS (USB 5 V, pin 40)
GNDGNDGNDGND
RX1 kΩ direnç üzerinden D111 kΩ direnç üzerinden GPIO 17 (TX2)1 kΩ direnç üzerinden GP0 (UART0 TX)
TXD10GPIO 16 (RX2)GP1 (UART0 RX)
SPK_1 ve SPK_2Hoparlörün iki ucuHoparlörün iki ucuHoparlörün iki ucu
BUSY (isteğe bağlı)D5KullanılmıyorKullanılmıyor
Arduino Uno
Arduino Uno
ESP32
ESP32
Raspberry Pi Pico
Raspberry Pi Pico

Veri hatları çapraz bağlanır: modülün TX'i kartın RX'ine, RX'i de kartın TX'ine gider. Uno'nun D0 ve D1'deki donanım seri portu USB üzerinden kod yüklemek ve Seri Monitör için kullanıldığından modülü SoftwareSerial ile D10 (RX) ve D11 (TX) pinlerine bağlıyoruz. Modülün RX girişine seri bağlanan 1 kΩ direnç önemsiz bir ayrıntı değildir. DFPlayer'ın yongası 3,3 V lojik seviyesiyle çalışır, Uno'nun TX pini ise 5 V verir. Direnç olmadan aradaki fark, yonganın giriş koruma diyotları üzerinden akım akıtır; bu akım hem yongayı zorlar hem de seri haberleşme sırasında hoparlörde duyulan cızırtı ve tıkırtılara yol açar. Ohm kanunu ile hesaplarsan 1 kΩ'un bu akımı yaklaşık 1–2 mA ile sınırladığını görürsün; 9600 baud'luk sinyal ise bundan etkilenmez. 10 kΩ gibi çok daha büyük bir direnç sinyali zayıflatıp haberleşmeyi kesebilir. Modülün TX çıkışı Uno'ya doğrudan bağlanır, çünkü Uno 3,3 V'u HIGH olarak okur (eşik yaklaşık 3,0 V).

SPK_1 ve SPK_2 pinlerinin hiçbirini GND'ye bağlama. Kart üzerindeki amfi köprü (BTL) çıkışlıdır: iki uç da ses sinyali taşır ve biri toprağa bağlanırsa amfi kısa devre olup bozulabilir. Aynı nedenle SPK pinlerini harici bir amfinin girişine bağlama; amfi için DAC_L ve DAC_R hat çıkışlarını kullan. Empedansı 4 Ω'dan düşük hoparlör de bağlama.

SD kart hazırlığı: FAT32, klasörler ve 0001.mp3 adlandırma

DFPlayer Mini, en fazla 32 GB'lık microSD kartları FAT16 ya da FAT32 dosya sistemiyle okur. 64 GB ve üzeri kartlar fabrikadan exFAT biçimiyle gelir ve modül bu biçimi okumaz; birkaç yüz parça için 1–16 GB'lık bir kart fazlasıyla yeterlidir. MP3'leri 128–192 kbps ve 44,1 kHz ile kaydetmek hem uyumluluk hem de kart okuma hızı açısından en güvenli seçimdir. Modül dosyaları adlarıyla değil numaralarıyla tanır; hangi fonksiyonla çalacağına göre klasör ve dosya adlarının belirli bir düzene uyması gerekir:

Kartta konumÖrnekKütüphane fonksiyonuKural
Kök dizin/0001.mp3, /0002.mp3play(1)Ada göre değil, dosyaların karta kopyalanma sırasına göre çalar
Numaralı klasörler/01/001.mp3 … /99/255.mp3playFolder(1, 1)Klasör adı 2 hane (01–99), dosya adı 3 hane (001–255)
mp3 klasörü/mp3/0001.mp3playMp3Folder(1)Dosya adı 4 hane; dosya, adındaki numarayla bulunur
advert klasörü/advert/0001.mp3advertise(1)Çalan parçayı keser, anons bitince kaldığı yerden devam eder
Büyük klasörler/01/0001.mp3 … /15/3000.mp3playLargeFolder(1, 1)En fazla 15 klasör, klasör başına 3000 dosya, 4 haneli adlar
  1. Kartı bilgisayarda FAT32 olarak biçimlendir (Windows'ta sağ tık > Biçimlendir, macOS'te Disk İzlencesi > Sil > MS-DOS (FAT)).
  2. Kök dizinde mp3 adlı bir klasör ve gerekiyorsa 01, 02 gibi numaralı klasörler oluştur.
  3. Dosyaları 0001.mp3, 0002.mp3 biçiminde (numaralı klasörlerde 001.mp3) yeniden adlandır. Numaradan sonra açıklama ekleyebilirsin: 0001_merhaba.mp3 gibi; modül yalnızca baştaki rakamlara bakar.
  4. Kök dizindeki dosyaları play() ile çalacaksan onları tek tek ve sırayla kopyala; toplu kopyalamada sıra karışabilir.
  5. Kartı bilgisayardan güvenle çıkar ve modüle güç yokken tak; çalışırken takıp çıkarmak dosyaları bozabilir.
macOS her dosya için ._0001.mp3 gibi gizli kopyalar ve .Spotlight-V100, .fseventsd gibi gizli klasörler oluşturur. DFPlayer bunları da dosya sayar; sonuçta yanlış parça çalar, sessizlik olur ya da readFileCounts() olması gerekenden fazla dosya gösterir. Kartı Mac'te hazırladıysan Terminal'de dot_clean -m /Volumes/KART_ADI komutunu çalıştır ya da gizli dosyaları elle sil. Windows'un oluşturduğu System Volume Information klasörü genellikle sorun çıkarmaz.

DFRobotDFPlayerMini kütüphanesi ve ilk test kodu

  1. Arduino IDE'de Kütüphane Yöneticisi'ni aç, DFRobotDFPlayerMini yaz ve DFRobot'un kütüphanesini kur. Kurulumun ayrıntıları Arduino'ya kütüphane ekleme yazısında.
  2. SD kartın kök dizinine en az bir MP3 kopyala, kartı modüle tak ve devreyi tablodaki gibi kur.
  3. Aşağıdaki kodu yükle ve Seri Monitör'ü 115200 baud hızında aç.
  4. Birkaç saniye içinde "DFPlayer Mini online." yazısını ve karttaki dosya sayısını görmeli, ardından ilk parçayı duymalısın.
Arduino (C++)
1#include <SoftwareSerial.h>
2#include <DFRobotDFPlayerMini.h>
3
4SoftwareSerial dfSerial(10, 11);   // RX = D10 ← DFPlayer TX, TX = D11 → 1 kΩ → DFPlayer RX
5DFRobotDFPlayerMini player;
6
7void setup() {
8  Serial.begin(115200);
9  dfSerial.begin(9600);                       // DFPlayer her zaman 9600 baud / DFPlayer always uses 9600 baud
10  Serial.println(F("DFPlayer baslatiliyor / Starting DFPlayer..."));
11
12  if (!player.begin(dfSerial)) {              // reset gönderir, kartı bekler / sends a reset, waits for the card
13    Serial.println(F("Unable to begin: kablolari ve SD karti kontrol et / check wiring and SD card"));
14    while (true) {}                           // burada dur / stop here
15  }
16  Serial.println(F("DFPlayer Mini online."));
17  Serial.print(F("Karttaki dosya / Files on card: "));
18  Serial.println(player.readFileCounts());    // gizli dosyalar da sayılır / hidden files are counted too
19
20  player.volume(20);                          // ses seviyesi 0-30 / volume 0-30
21  player.EQ(DFPLAYER_EQ_NORMAL);              // ekolayzır: normal / equalizer: normal
22  player.play(1);                             // kökteki ilk dosya / first file in the root
23}
24
25void loop() {
26  if (player.available()) {                   // modülden bildirim geldi / a message arrived from the module
27    uint8_t type = player.readType();
28    int value = player.read();
29    if (type == DFPlayerPlayFinished) {
30      Serial.print(F("Parca bitti / Track finished: "));
31      Serial.println(value);
32    } else if (type == DFPlayerError) {
33      Serial.print(F("Hata kodu / Error code: "));
34      Serial.println(value);                  // kodların anlamı tabloda / meanings are in the table
35    } else if (type == DFPlayerCardRemoved) {
36      Serial.println(F("SD kart cikarildi / SD card removed"));
37    }
38  }
39}
40
FonksiyonNe yapar?
begin(seri, isACK, doReset)Modülü başlatır; varsayılan olarak reset gönderir ve kartın hazır olduğunu bildiren mesajı bekler
volume(0–30)Ses seviyesini ayarlar; volumeUp() ve volumeDown() birer kademe değiştirir
EQ(DFPLAYER_EQ_POP)Ekolayzır: NORMAL, POP, ROCK, JAZZ, CLASSIC, BASS
play(n)Kök dizindeki n. dosyayı (kopyalama sırasına göre) çalar
next() / previous()Sonraki / önceki parça
pause() / start()Duraklatır / kaldığı yerden devam ettirir
stop()Çalmayı durdurur
loop(n)n. parçayı sürekli tekrarlar
enableLoopAll() / randomAll()Tüm parçaları döngüde / karışık sırada çalar
readState() / readVolume() / readFileCounts()Durumu, ses seviyesini ve karttaki dosya sayısını sorgular
available() / readType() / read()Modülden gelen bildirimi (parça bitti, hata, kart çıkarıldı) okur
begin() modüle reset gönderir ve kartın hazır olduğunu bildiren mesajı 2 saniyeye kadar bekler; açılışın birkaç saniye sürmesi bu yüzden normaldir. Kütüphane varsayılan olarak her komuttan sonra modülün onayını bekler, böylece komutlar üst üste binmez. Yine de loop() içinde her turda volume() ya da play() gönderme: sürekli komut alan modül takılabilir ve hoparlörden tık sesleri gelir. Komutları yalnızca bir şey değiştiğinde gönder.

Ses seviyesi, EQ ve BUSY pini ile sıralı anons

Ses seviyesi 0 ile 30 arasında ayarlanır. Küçük bir hoparlörde 15–20 arası çoğu oda için yeterlidir; 25'in üstünde, özellikle zayıf bir beslemede ses bozulmaya (clipping) ve modül resetlenmeye başlayabilir. EQ ayarı bas ve tiz dengesini değiştirir; küçük hoparlörlerde BASS modu sesi boğuklaştırabilir, bu yüzden NORMAL ile başla. Numaralı klasörler konuşan projelerde çok işe yarar: 01 klasörüne "Sıcaklık" ve "derece" kelimelerini, 02 klasörüne de 001.mp3'ten 100.mp3'e kadar sayıları koyarsan Arduino sayıları cümle hâlinde söyleyebilir. Bir dosyanın bittiğini anlamanın en güvenilir yolu BUSY pinidir: modül çalarken bu pin LOW, boştayken HIGH olur. Aşağıdaki kod BUSY'yi D5'ten okuyarak dosyaları birbirinin üstüne binmeden arka arkaya çalar:

Arduino (C++)
1#include <SoftwareSerial.h>
2#include <DFRobotDFPlayerMini.h>
3
4SoftwareSerial dfSerial(10, 11);            // RX = D10 ← DFPlayer TX, TX = D11 → 1 kΩ → DFPlayer RX
5DFRobotDFPlayerMini player;
6const byte BUSY_PIN = 5;                    // DFPlayer BUSY: çalarken LOW / LOW while playing
7
8// Klasör 01: 001.mp3 "Sıcaklık", 002.mp3 "derece" / folder 01: 001.mp3 "Temperature", 002.mp3 "degrees"
9// Klasör 02: 001.mp3 ... 100.mp3 = 1 ... 100 sayıları / folder 02: 001.mp3 ... 100.mp3 = numbers 1 ... 100
10
11void playAndWait(uint8_t folder, uint8_t file) {
12  player.playFolder(folder, file);          // /01/001.mp3 gibi / e.g. /01/001.mp3
13  unsigned long start = millis();
14  while (digitalRead(BUSY_PIN) == HIGH && millis() - start < 1000) {}  // çalma başlasın / wait for playback to start
15  while (digitalRead(BUSY_PIN) == LOW) {}                              // parça bitsin / wait for the track to end
16  delay(50);
17}
18
19void sayTemperature(int degrees) {
20  playAndWait(1, 1);                        // "Sıcaklık" / "Temperature"
21  if (degrees >= 1 && degrees <= 100) {
22    playAndWait(2, degrees);                // sayıyı söyle / say the number
23  }
24  playAndWait(1, 2);                        // "derece" / "degrees"
25}
26
27void setup() {
28  pinMode(BUSY_PIN, INPUT);
29  Serial.begin(115200);
30  dfSerial.begin(9600);
31  if (!player.begin(dfSerial)) {
32    Serial.println(F("Unable to begin"));
33    while (true) {}
34  }
35  player.volume(22);
36  sayTemperature(23);                       // değer bir sensörden de gelebilir / the value can come from a sensor
37}
38
39void loop() {
40}
41

playAndWait() önce komutu gönderir, BUSY'nin LOW'a inmesini en fazla 1 saniye bekler (modülün çalmaya başlaması birkaç yüz milisaniye sürer), ardından parça bitene kadar bekler. Ses dosyalarını kendi sesinle kaydedebilir ya da bir metin-ses (TTS) aracıyla üretebilirsin; dosyaların başındaki ve sonundaki sessizliği kırpmak anonsun daha doğal akmasını sağlar. Çalan bir müziği kesip kısa bir uyarı vermek istiyorsan advertise(n) fonksiyonunu kullan: modül /advert klasöründeki anonsu çalar, sonra müziğe kaldığı yerden devam eder. Bu komut yalnızca bir parça çalarken çalışır; modül boştayken çağrılırsa hata döner.

Butonla parça değiştirme ve potansiyometreyle ses ayarı

Şimdi kendi MP3 çalarını yapalım: üç buton önceki parça, oynat/duraklat ve sonraki parça görevini görsün, bir potansiyometre de sesi ayarlasın. Butonları D2, D3 ve D4 ile GND arasına bağla; dahili pull-up dirençleri kullandığımız için harici dirence gerek yok (nedenini buton nasıl bağlanır yazısında anlattık). Potansiyometrenin kenar uçları 5V ve GND'ye, orta ucu A0'a gider. Bir parça bittiğinde kod otomatik olarak sonrakine geçer.

Arduino (C++)
1#include <SoftwareSerial.h>
2#include <DFRobotDFPlayerMini.h>
3
4SoftwareSerial dfSerial(10, 11);            // RX = D10 ← DFPlayer TX, TX = D11 → 1 kΩ → DFPlayer RX
5DFRobotDFPlayerMini player;
6
7const byte BTN[3] = {2, 3, 4};              // önceki, oynat/duraklat, sonraki / previous, play/pause, next
8const byte POT_PIN = A0;                    // ses ayarı potu / volume potentiometer
9bool lastState[3] = {HIGH, HIGH, HIGH};
10unsigned long lastChange[3] = {0, 0, 0};
11bool paused = false;
12int lastRaw = -100;                         // ilk turda sesi mutlaka ayarla / always set the volume on the first pass
13unsigned long lastPotRead = 0;
14unsigned long lastFinish = 0;
15
16// Butona yeni basıldıysa true döner (50 ms sıçrama filtresi) / true on a new press (50 ms debounce)
17bool pressed(byte i) {
18  bool s = digitalRead(BTN[i]);
19  if (s != lastState[i] && millis() - lastChange[i] > 50) {
20    lastState[i] = s;
21    lastChange[i] = millis();
22    return s == LOW;                        // INPUT_PULLUP: basınca LOW / LOW when pressed
23  }
24  return false;
25}
26
27void setup() {
28  for (byte i = 0; i < 3; i++) pinMode(BTN[i], INPUT_PULLUP);
29  Serial.begin(115200);
30  dfSerial.begin(9600);
31  if (!player.begin(dfSerial)) {
32    Serial.println(F("Unable to begin"));
33    while (true) {}
34  }
35  player.play(1);
36}
37
38void loop() {
39  if (pressed(0)) { player.previous(); paused = false; }
40  if (pressed(2)) { player.next(); paused = false; }
41  if (pressed(1)) {
42    if (paused) player.start();             // kaldığı yerden devam / resume
43    else player.pause();                    // duraklat / pause
44    paused = !paused;
45  }
46
47  if (millis() - lastPotRead > 100) {       // potu saniyede 10 kez oku / read the pot 10 times per second
48    lastPotRead = millis();
49    int raw = analogRead(POT_PIN);
50    if (abs(raw - lastRaw) > 20) {          // titremeyi yok say / ignore jitter
51      lastRaw = raw;
52      player.volume(map(raw, 0, 1023, 0, 30));
53    }
54  }
55
56  if (player.available() && player.readType() == DFPlayerPlayFinished) {
57    if (millis() - lastFinish > 1000) player.next();   // parça bitince sonrakine geç / go to the next track
58    lastFinish = millis();                  // bazı modüller bitişi iki kez bildirir / some modules report the end twice
59  }
60}
61
Kod parçasıNe işe yarar?
pressed()Yalnızca butona basıldığı anı yakalar ve 50 ms içindeki sıçramaları yok sayar; buton basılı tutulsa da tek komut gider
abs(raw - lastRaw) > 20Pot okumasındaki küçük titremeler modüle sürekli komut gönderip tık sesine yol açmasın diye sesi yalnızca belirgin değişimlerde günceller
map(raw, 0, 1023, 0, 30)0–1023 arasındaki analog değeri DFPlayer'ın 0–30 ses aralığına çevirir
pausedAynı buton hem duraklatsın hem devam ettirsin diye çalma durumunu tutar
DFPlayerPlayFinishedParça bitince gelen bildirim; kod sonraki parçaya geçer
millis() - lastFinish > 1000Bazı klon modüller bitişi iki kez bildirir; bu kontrol bir parçanın atlanmasını önler

Hoparlör seçimi (3 W) ve harici amfi

DFPlayer'ın kendi amfisi (çoğu kartta 8002 tipi bir yonga), 3 W'tan küçük ve 4 Ω ya da 8 Ω empedanslı bir hoparlörü doğrudan sürer. En dengeli sonuç 8 Ω, 1–3 W'lık bir hoparlörle alınır; 0,5 W'lık küçük hoparlörler de çalışır ama yüksek seste zorlanır. 3 W, amfinin 5 V besleme ve 4 Ω yükteki, bozulmanın belirginleştiği üst sınırıdır; günlük kullanımda alacağın temiz güç bunun altındadır. Hoparlörü bir kutuya ya da en azından bir panele yerleştirmek bas sesleri belirgin biçimde artırır, çünkü hoparlörün önünden ve arkasından çıkan sesler birbirini sönümlemez. Yüksek seste modül anlık olarak birkaç yüz miliamper çekebilir; bilgisayar USB'sinden beslenen bir Arduino'da bu, gerilim düşmesine, cızırtıya ve resetlenmeye yol açabilir. Daha güçlü ya da stereo ses istiyorsan DAC_L ve DAC_R hat çıkışlarını harici bir amfiye bağla:

Çıkış yoluBağlantıNe zaman?
Dahili amfiSPK_1 ve SPK_2 → 4–8 Ω, 3 W'a kadar hoparlörKapı zili, oyuncak, sesli uyarı gibi küçük projeler
KulaklıkDAC_L, DAC_R ve GND → 3,5 mm jakKişisel dinleme; sesi düşük seviyeden başlat
PAM8403 amfi modülüDAC_L, DAC_R ve GND → amfinin L, R ve GND girişleri; amfi 5 V ile beslenir2 × 3 W stereo, pille çalışan taşınabilir hoparlör
PAM8610 ya da TPA3116 amfiDAC çıkışları → amfi girişi; amfi 12 V ile beslenirDaha yüksek güç: 2 × 10 W ve üzeri
Aktif hoparlör (AUX)DAC_L, DAC_R ve GND → aktif hoparlörün AUX girişiHazır bir bilgisayar hoparlörünü kullanmak
DFPlayer'ın VCC ve GND pinleri arasına, modüle olabildiğince yakın 100–470 µF'lık bir elektrolitik kondansatör ekle; yüksek seste oluşan ani akım çekişlerini karşılar ve resetlenmeleri önler. Harici amfi kullanıyorsan amfiyi, DFPlayer'ı ve Arduino'yu aynı GND noktasında birleştir; farklı adaptörlerden beslenen ve toprakları ayrı kalan devreler uğultunun en sık nedenidir. Neden önemli olduğunu ortak toprak (GND) yazısında anlattık. Hoparlör kablolarını kısa tut ve seri haberleşme kablolarının yanından geçirme.

Cızırtı, parazit ve tık sesi nasıl giderilir?

  • Komut gönderirken cızırtı ve tıkırtı: RX hattındaki 1 kΩ direnç eksik. Direnci Arduino'nun TX pini ile modülün RX pini arasına koy.
  • Sürekli hışırtı ya da uğultu: Besleme gürültülü ya da yetersiz. DFPlayer'ı ayrı bir 5 V kaynaktan besle, VCC ile GND arasına kondansatör ekle ve tüm GND'leri birleştir.
  • Açılışta "pat" sesi: begin() fonksiyonunun gönderdiği reset komutundan kaynaklanır. Rahatsız ediyorsa player.begin(dfSerial, true, false) ile reset adımını atla.
  • ESP32'de vızıltı: Wi-Fi yayını sırasındaki akım darbeleri beslemeye ve oradan sese karışır. DFPlayer'ın beslemesine kondansatör ekle, mümkünse ayrı bir kaynak kullan.
  • Yüksek seste çatlak, bozuk ses: Hoparlör ya da amfi sınırda çalışıyor. Sesi 20–25 civarına indir, daha verimli bir hoparlör seç ya da harici amfiye geç.
  • Çalma yokken hafif hışırtı: Kart üzerindeki amfinin kendi gürültüsüdür ve küçük modüllerde tamamen yok olmaz. Sessizliğin önemli olduğu projelerde DAC çıkışını kaliteli bir harici amfiye bağlamak en iyi sonucu verir.

"Unable to begin" hatası ve çözümü

Seri Monitör'de Unable to begin: ve ardından 1.Please recheck the connection! ile 2.Please insert the SD card! satırlarını görüyorsan kütüphanenin örnek kodundaki begin() kontrolü başarısız olmuş demektir. begin() modüle bir reset komutu gönderir ve 2 saniye içinde "kart hazır" (card online) mesajının gelmesini bekler; mesaj gelmezse false döner. Yani hatanın kaynağı kablolama, SD kart, besleme ya da modülün yanıt verme biçimi olabilir. Sorunu aşağıdaki sırayla ele al:

Olası nedenKontrol ve çözüm
TX ve RX düz bağlanmışModülün TX'i D10'a (SoftwareSerial RX), RX'i 1 kΩ üzerinden D11'e (SoftwareSerial TX) gitmeli; koddaki SoftwareSerial(10, 11) sırası (RX, TX) ile aynı olmalı
GND ortak değilModülün GND'si Arduino'nun GND'sine bağlı olmalı; ayrı kaynak kullanıyorsan da GND'leri birleştir
SD kart okunmuyorKart takılı mı, FAT32 mi, 32 GB'tan küçük mü, içinde en az bir ses dosyası var mı? Kartı yeniden biçimlendir ya da başka bir kartla dene
Yanlış dirençRX hattında 1 kΩ olmalı; 10 kΩ gibi büyük değerler sinyali zayıflatır
Yetersiz beslemeVCC'de 4–5 V olmalı; hoparlörü geçici olarak sök, gerilimi multimetreyle ölç ve kondansatör ekle
Yanlış baud hızıdfSerial.begin(9600) olmalı; Seri Monitör hızıyla (115200) karıştırma
D0 ve D1 kullanılmışUno'da donanım seri portu USB ile paylaşılır; modülü SoftwareSerial pinlerine taşı
Klon yonga geç cevap veriyorbegin()'den önce delay(1000) ekle; olmazsa begin(dfSerial, true, false) ile resetten sonraki beklemeyi atla
DFPlayerError koduKütüphanedeki adıAnlamı
1BusyModül meşgul ya da kart bulunamadı (başlatma bitmedi)
2SleepingModül uyku modunda
3SerialWrongStackSeri veri bozuk geldi
4CheckSumNotMatchPaketin sağlama toplamı tutmadı
5FileIndexOutİstenen parça numarası karttaki aralığın dışında
6FileMismatchİstenen dosya bulunamadı; adlandırmayı kontrol et
7AdvertiseAnons (advert) hatası; örneğin çalma yokken advertise() çağrıldı
Bazı ucuz klon kartlar resetten sonra beklenen mesajı hiç göndermez ya da geç gönderir; bu durumda kablolar doğru olduğu hâlde begin() false döner. player.begin(dfSerial, true, false) reset adımını atlar ve kontrolü geçer; modül bu ayarla ses çıkarıyorsa sorun buydu. Ancak bu ayar gerçek bir kablolama hatasını da gizler, bu yüzden önce tablodaki maddeleri kontrol et. Modülün hiç cevap verip vermediğini anlamak için player.readFileCounts() değerine bak: -1 dönüyorsa modülden yanıt gelmiyordur.

ESP32 ile DFPlayer Mini: web sayfasından MP3 kontrolü

ESP32'de SoftwareSerial'a gerek yoktur; üç donanım UART'ından biri istediğin pinlere atanabilir. Aşağıdaki kodda UART2, GPIO 16 (RX) ve GPIO 17 (TX) pinlerinde çalışır ve DFPlayer, ESP32 kartının 5V (VIN) pininden beslenir. ESP32'nin 3,3 V'luk TX sinyali modülle doğrudan uyumludur, ama 1 kΩ direnci parazite karşı yine de kullan. Ters yönde DFRobot modülün lojik seviyesinin 3,3 V olduğunu belirtir; yine de bazı klon kartlarda 5 V beslemede TX hattında daha yüksek gerilim ölçülmüştür. Bağlamadan önce TX ile GND arasını multimetreyle ölç; 3,6 V'un üzerindeyse araya 1 kΩ + 2 kΩ'luk bir gerilim bölücü koy. Kod ev ağına bağlanır ve telefonundan açabileceğin bir sayfa sunar; sayfadaki düğmeler parça değiştirir, duraklatır ve sesi ayarlar.

Arduino (C++)
1#include <WiFi.h>
2#include <WebServer.h>
3#include <DFRobotDFPlayerMini.h>
4
5const char *WIFI_SSID = "WIFI_ADI";         // kendi ağ adın / your network name
6const char *WIFI_PASS = "WIFI_SIFRESI";     // kendi şifren / your password
7
8HardwareSerial dfSerial(2);                 // UART2
9DFRobotDFPlayerMini player;
10WebServer server(80);
11int volumeLevel = 15;
12
13const char PAGE[] = R"rawliteral(<!DOCTYPE html><html><head>
14<meta name="viewport" content="width=device-width,initial-scale=1"><title>ESP32 MP3</title>
15<style>body{font-family:sans-serif;text-align:center}button{font-size:22px;margin:6px;padding:10px 18px}</style>
16</head><body><h2>DFPlayer Mini</h2>
17<button onclick="c('prev')">Prev</button><button onclick="c('pause')">Pause</button>
18<button onclick="c('play')">Play</button><button onclick="c('next')">Next</button><br>
19<button onclick="c('down')">Vol -</button><button onclick="c('up')">Vol +</button>
20<p id="s"></p>
21<script>function c(x){fetch('/cmd?c='+x).then(r=>r.text()).then(t=>document.getElementById('s').innerText=t)}</script>
22</body></html>)rawliteral";
23
24void handleCmd() {
25  String c = server.arg("c");
26  if (c == "next") player.next();
27  else if (c == "prev") player.previous();
28  else if (c == "pause") player.pause();
29  else if (c == "play") player.start();
30  else if (c == "up" && volumeLevel < 30) player.volume(++volumeLevel);
31  else if (c == "down" && volumeLevel > 0) player.volume(--volumeLevel);
32  server.send(200, "text/plain", "Ses / Volume: " + String(volumeLevel));
33}
34
35void setup() {
36  Serial.begin(115200);
37  dfSerial.begin(9600, SERIAL_8N1, 16, 17); // RX = GPIO16 ← DFPlayer TX, TX = GPIO17 → 1 kΩ → DFPlayer RX
38  delay(1000);                              // modül kartı okusun / let the module read the card
39  if (!player.begin(dfSerial)) {
40    Serial.println("Unable to begin");
41    while (true) delay(10);
42  }
43  player.volume(volumeLevel);
44
45  WiFi.begin(WIFI_SSID, WIFI_PASS);
46  while (WiFi.status() != WL_CONNECTED) {   // ağa bağlanana kadar bekle / wait for the network
47    delay(500);
48    Serial.print(".");
49  }
50  Serial.print("\nAdres / Address: http://");
51  Serial.println(WiFi.localIP());
52
53  server.on("/", []() { server.send(200, "text/html", PAGE); });
54  server.on("/cmd", handleCmd);
55  server.begin();
56  player.play(1);
57}
58
59void loop() {
60  server.handleClient();                    // tarayıcı isteklerini işle / handle browser requests
61}
62

Kodu yükledikten sonra Seri Monitör'de görünen adresi (ör. 192.168.1.42) telefonunun tarayıcısına yaz; telefonla ESP32'nin aynı Wi-Fi ağında olması gerekir. Bağlantı kurulamıyorsa ESP32 Wi-Fi'ye bağlanmıyor yazısındaki adımlara bak. ESP32-WROVER modüllü kartlarda GPIO 16 ve 17 dahili PSRAM'e ayrıldığı için UART'ı 26 ve 27 gibi başka pinlere taşı; bunun için yalnızca dfSerial.begin() satırındaki pin numaralarını değiştirmen yeterli. Hoparlör yüksek seste çalarken ESP32 kendiliğinden yeniden başlıyorsa sorun beslemededir; ayrıntılar ESP32 brownout yazısında.

Raspberry Pi Pico ve MicroPython ile DFPlayer Mini (UART)

Raspberry Pi Pico'da hazır bir kütüphane aramak yerine modülün seri protokolünü doğrudan kullanmak hem kolay hem de öğreticidir. Her komut 10 baytlık bir pakettir: başlangıç baytı 0x7E, sürüm 0xFF, uzunluk 0x06, komut kodu, geri bildirim (0 = onay isteme), iki baytlık parametre, iki baytlık sağlama toplamı ve bitiş baytı 0xEF. Sağlama toplamı, sürümden parametrenin son baytına kadar olan altı baytın toplamının 16 bitlik eksi değeridir. Örneğin kök dizindeki 1. parçayı çalan paket 7E FF 06 03 00 00 01 FE F7 EF olur. Modül de parça bittiğinde 0x3D, kart hazır olduğunda 0x3F, hata olduğunda 0x40 kodlu bildirimler gönderir. Pico'nun 3,3 V'luk UART'ı modüle doğrudan uyar; ESP32 bölümündeki TX gerilimi uyarısı burada da geçerlidir, çünkü Pico'nun pinleri de 5 V'a dayanıklı değildir. Modülü Pico'nun VBUS (USB 5 V) pininden besle.

KomutKodParametre
Sonraki / önceki parça0x01 / 0x02Yok
Kökteki n. parçayı çal0x031–2999
Ses seviyesi0x060–30
EQ0x070–5
Reset0x0CYok
Devam / duraklat0x0D / 0x0EYok
Klasörden çal0x0FÜst bayt klasör (1–99), alt bayt dosya (1–255)
mp3 klasöründen çal0x12Dosya numarası (0001.mp3 için 1)
Anons (advert)0x13Dosya numarası
Durdur0x16Yok
Parça bitti (modülden gelir)0x3DBiten parçanın numarası
MicroPython
1from machine import UART, Pin
2import time
3
4# GP0 (UART0 TX) → 1 kΩ → DFPlayer RX, GP1 (UART0 RX) ← DFPlayer TX
5uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
6btn_next = Pin(14, Pin.IN, Pin.PULL_UP)     # sonraki parça / next track
7btn_play = Pin(15, Pin.IN, Pin.PULL_UP)     # oynat-duraklat / play-pause
8TRACKS = 5                                  # /mp3 klasöründeki dosya sayısı / number of files in /mp3
9
10def send(cmd, param=0):
11    # 10 baytlık komut paketi, onay istemeden / 10-byte command frame without ACK
12    frame = bytearray([0x7E, 0xFF, 0x06, cmd, 0x00, param >> 8, param & 0xFF, 0, 0, 0xEF])
13    checksum = -sum(frame[1:7]) & 0xFFFF    # sağlama toplamı / checksum
14    frame[7] = checksum >> 8
15    frame[8] = checksum & 0xFF
16    uart.write(frame)
17    time.sleep_ms(30)
18
19buf = b""
20
21def events():
22    # gelen 10 baytlık bildirimlerin komut kodlarını döndür / return command codes of incoming messages
23    global buf
24    if uart.any():
25        buf += uart.read()
26    codes = []
27    while True:
28        start = buf.find(b"\x7e")
29        if start < 0:
30            buf = b""
31            break
32        if len(buf) - start < 10:
33            buf = buf[start:]
34            break
35        frame = buf[start:start + 10]
36        if frame[9] == 0xEF:
37            codes.append(frame[3])
38            buf = buf[start + 10:]
39        else:
40            buf = buf[start + 1:]
41    return codes
42
43def play_track(n):
44    send(0x12, n)                           # /mp3/000n.mp3 dosyasını çal / play /mp3/000n.mp3
45
46time.sleep(2)                               # modül kartı okusun / let the module read the card
47send(0x06, 18)                              # ses 18/30 / volume 18 of 30
48track = 1
49play_track(track)
50playing = True
51last_end = 0
52
53while True:
54    if btn_next.value() == 0:
55        track = track % TRACKS + 1          # son parçadan sonra başa dön / wrap after the last track
56        play_track(track)
57        playing = True
58        time.sleep_ms(300)                  # basit sıçrama önleme / simple debounce
59    if btn_play.value() == 0:
60        send(0x0E if playing else 0x0D)     # 0x0E duraklat, 0x0D devam / 0x0E pause, 0x0D resume
61        playing = not playing
62        time.sleep_ms(300)
63    for code in events():
64        # 0x3D: SD karttaki parça bitti / 0x3D: track on the SD card finished
65        if code == 0x3D and time.ticks_diff(time.ticks_ms(), last_end) > 1000:
66            last_end = time.ticks_ms()      # çift bildirimi yok say / ignore the duplicate message
67            track = track % TRACKS + 1
68            play_track(track)
69

Kodu Thonny ile Pico'ya main.py adıyla kaydedersen Pico her açıldığında bir MP3 çalar gibi çalışır; MicroPython'a yeni başlıyorsan MicroPython temelleri yazısına göz at. GP14'teki buton sonraki parçaya geçer, GP15'teki buton duraklatır ve devam ettirir; butonların diğer ucu GND'ye gider. events() fonksiyonu gelen baytları bir tamponda biriktirir ve 0x7E ile başlayıp 0xEF ile biten paketleri ayıklar. Parça bitti (0x3D) mesajı gelince kod sıradaki dosyaya geçer, son dosyadan sonra da başa döner. TRACKS değişkenini /mp3 klasöründeki dosya sayısına göre değiştirmeyi unutma.

DFPlayer Mini ile proje fikirleri

  • Melodili kapı zili: Butona basılınca rastgele bir melodi çalan, gece saatlerinde sesini kısan bir zil.
  • Hoş geldin sistemi: Bir PIR hareket sensörü biri geldiğinde selamlama anonsu yapsın.
  • Kartlı müzik kutusu: Her RFID kartı farklı bir klasörü çalsın; çocuklar için ekransız bir müzik çalar.
  • Konuşan saat: Bir RTC saat modülü ile saati sesli söyleyen ya da her saat başı haber veren bir saat.
  • Uzaktan kumandalı MP3 çalar: IR alıcı ve kumanda ile parça ve ses kontrolü.
  • Cadılar Bayramı süsü ya da şaka kutusu: HC-SR04 biri yaklaştığını algılayınca korkutucu bir ses çalsın.
  • Sesli alarm ve uyarılar: Gaz, su baskını ya da açık kalan kapı gibi durumlarda bip yerine "Mutfakta gaz algılandı" gibi anlaşılır cümleler.
  • Ekranlı MP3 çalar: Parça numarasını ve ses seviyesini bir OLED ekranda göster.

DFPlayer Mini; doğru adlandırılmış bir SD kart, RX hattındaki 1 kΩ direnç ve sağlam bir 5 V beslemeyle Arduino projelerine dakikalar içinde gerçek ses kazandırır. Sorun yaşarsan önce kartı ve kabloları, sonra beslemeyi kontrol et; hataların neredeyse tamamı bu üç noktadan çıkar. Seri haberleşmenin temellerini merak ediyorsan UART seri haberleşme yazısı iyi bir sonraki adım olur. BlueGrays uygulamasında buzzer ile melodi çalma, İstiklal Marşı, basit piyano, hareket sensörlü kapı zili ve ESP32 ile melodi gibi ses projelerini devre şemaları ve adım adım kodlarıyla bulabilir, sonra bu projelere DFPlayer Mini ile gerçek ses ekleyebilirsin.

Sıkça sorulan sorular

DFPlayer Mini kaç GB SD kart destekler?

DFPlayer Mini en fazla 32 GB'lık microSD kartları FAT16 ya da FAT32 dosya sistemiyle okur. 64 GB ve üzeri kartlar exFAT biçimiyle geldiği için modül onları görmez. Birkaç yüz MP3 için 1–16 GB'lık bir kart fazlasıyla yeterlidir.

DFPlayer Mini neden ses vermiyor?

Önce Seri Monitör'de "online" yazısını gördüğünden emin ol; görmüyorsan sorun kablolamada ya da SD karttadır. Modül başladığı hâlde ses yoksa ses seviyesinin 0 olmadığını, hoparlörün SPK_1 ve SPK_2'ye bağlı olduğunu ve dosya adlarının çağırdığın fonksiyona uyduğunu kontrol et. Kart üzerindeki LED'in yanması modülün gerçekten çaldığını gösterir.

DFPlayer Mini'de RX pinine neden 1k direnç takılır?

Modülün yongası 3,3 V ile çalışırken Arduino Uno'nun TX pini 5 V verir. RX hattına seri bağlanan 1 kΩ direnç yongaya akan akımı sınırlar ve seri haberleşme sırasında hoparlörde duyulan cızırtıyı azaltır. ESP32 ve Pico gibi 3,3 V'luk kartlarda da parazite karşı takılması önerilir.

DFPlayer Mini Arduino olmadan çalışır mı?

Evet. IO_1 ve IO_2 pinlerini birer butonla GND'ye bağladığında kısa basış parça değiştirir, uzun basış sesi ayarlar. ADKEY pinlerine dirençlerle bağlanan butonlar da belirli parçaları çalabilir. Böylece pil, hoparlör ve birkaç butonla mikrodenetleyicisiz bir MP3 çalar ya da zil yapabilirsin.

DFPlayer Mini'ye hangi hoparlör bağlanır?

SPK_1 ve SPK_2 pinlerine 4 Ω ya da 8 Ω empedanslı, 3 W'tan küçük bir hoparlör doğrudan bağlanır; en dengeli sonucu 8 Ω, 1–3 W'lık hoparlörler verir. Hoparlörün hiçbir ucunu GND'ye bağlama. Daha yüksek ya da stereo ses için DAC_L ve DAC_R çıkışlarını PAM8403 gibi bir amfiye bağla.

DFPlayer Mini dosyaları neden yanlış sırada çalıyor?

play(n) fonksiyonu dosya adına değil, dosyaların karta kopyalanma sırasına bakar. Ada göre çalmak için dosyaları /mp3/0001.mp3 biçiminde adlandırıp playMp3Folder() ya da /01/001.mp3 biçiminde adlandırıp playFolder() kullan. Kartı Mac'te hazırladıysan gizli ._ dosyalarını da temizle.

Tüm projeleri gör
Buzzer Kullanımı
#13Başlangıç

Buzzer Kullanımı

Kapı zili ya da alarm sesi nasıl çıkar, hiç merak ettin mi? Arduino küçük bir buzzer'ı kısa aralıklarla öttürür: bip, sus, bip, sus. Sesin elektrikle nasıl üretildiğini görür, ileride melodi çalan pro

4.7(89)
158
Buzzer İle İstiklal Marşı
#15Orta

Buzzer İle İstiklal Marşı

Butona bastığında küçük bir buzzer İstiklal Marşı'nı nota nota çalmaya başlar. Arduino her notayı doğru yükseklikte ve doğru sürede çalarak marşın iki kıtasını baştan sona seslendirir, bitince yeni bi

4.9(100)
183
Buzzer İle Frekans Ayarı
#14Orta

Buzzer İle Frekans Ayarı

Dört butonla bir buzzer'dan çıkan sesi yönetirsin: biri sesi başlatır, biri susturur, diğer ikisi sesi inceltip kalınlaştırır. Artırma ya da azaltma butonunu basılı tuttukça ses adım adım değişir ve s

4.6(68)
115
ESP32 Buzzer ile Melodi Çalma
#114Başlangıç
Premium

ESP32 Buzzer ile Melodi Çalma

Pasif buzzer ile basit bir melodi (Twinkle Twinkle Little Star) çalma. Arduino'daki gibi tone() ve noTone() fonksiyonlarıyla nota çalıyoruz — ESP32 Arduino Core 3.0+ ile aynı syntax çalışır. Pasif buzzer kullanılmalı (aktif buzzer melodi çalmaz).

4.8(30)
55
IR Alıcı, Kumanda ve Buzzer ile Hazır Melodi Çalma
#18Başlangıç
Premium

IR Alıcı, Kumanda ve Buzzer ile Hazır Melodi Çalma

Televizyon kumandasının tuşlarıyla melodi çalan bir müzik kutusu yap. Kızılötesi alıcı kumandadan gelen sinyali yakalar; bir tuşa basınca hareketli bir oyun müziği, ikincisinde tanıdık bir çocuk şarkı

4.8(57)
74
Buzzer Ve Buton İle Basit Piyano
#26İleri
Premium

Buzzer Ve Buton İle Basit Piyano

Sekiz butonla kendi küçük piyanonu kur. Her buton bir notaya karşılık gelir: kalından inceye do, re, mi, fa, sol, la, si ve ince do. Basılı tuttuğun sürece nota buzzer'dan çalar, bırakınca susar; basi

4.9(66)
88
Arduino İle Mehter Marşı
#100Başlangıç
Premium

Arduino İle Mehter Marşı

Bu Proje, Sadece Arduino Uno, Buzzer ve Jumper Kablolar Kullanarak Mehter Marşını Sonsuz Döngü İle Çalmanızı Sağlar. Sadece Bağlantıları Yapın, ve Kodu Yapıştırın.

4.0(24)
36
Hareket Sensörü İle Kapı Zili ve Işık
#25Orta
Premium

Hareket Sensörü İle Kapı Zili ve Işık

Kapına biri yaklaştığında, daha zile basmadan haberin olur. Hareket sensörü birini fark edince LED yanar ve buzzer inceden kalına üç notalık bir zil sesi çalar; melodi bitince ışık söner ve sensör yen

4.7(54)
71