MAX7219 Arduino: 8x8 LED Matris ve 4'lü Modülle Kayan Yazı
MAX7219 Arduino rehberi: 8x8 ve 4'lü 8x32 LED matris bağlantısı, MD_Parola ile kayan yazı, FC16_HW ayarı, ters görüntü çözümü, Türkçe karakter ve saat kodu.
MAX7219, Arduino ile LED matris kullanmanın en kolay yolu olan ve 64 LED'i tek başına süren ucuz bir sürücü entegresidir. Piyasada iki hâliyle karşına çıkar: üzerinde tek bir 8x8 nokta matris bulunan modül ve dört matrisin yan yana dizildiği 4'lü 8x32 dot matrix modül. MAX7219, Arduino'dan yalnızca 3 sinyal kablosu (DIN, CS, CLK) alır; satırları saniyede yüzlerce kez tarama, parlaklığı ayarlama ve her LED'in durumunu hafızasında tutma işini kendisi yapar. Böylece Arduino kayan yazı, saat, skor tabelası ya da animasyon gibi işlere serbest kalır, sen de modülleri uç uca ekleyerek ekranı istediğin kadar uzatabilirsin.
Bu yazıda MAX7219'un nasıl çalıştığını, modülü Arduino Uno, ESP32 ve Raspberry Pi Pico'ya SPI ile bağlamayı, modülleri zincirlemeyi ve MD_Parola kütüphanesiyle ilk kayan yazını göstermeyi öğreneceksin. Ardından yeni başlayanların en çok takıldığı ters ya da ayna görüntü sorununu donanım tipi (FC16_HW) ayarıyla çözecek, parlaklığı ve güç tüketimini hesaplayacak, ekrana ç, ğ, ı, ö, ş, ü harflerini ekleyecek, RTC modülüyle bir saat ve piksel piksel bir animasyon yapacaksın. Son bölümlerde ESP32 ile telefondan mesaj gönderme, Pico MicroPython kodu ve sık yapılan hataların çözümleri var.

MAX7219 nedir, nasıl çalışır?
64 LED'i tek tek Arduino pinlerine bağlamak mümkün değildir; bu yüzden LED matrislerde çoklama (multiplexing) kullanılır. 8x8 matriste LED'ler 8 satır ve 8 sütundan oluşan bir ızgaraya bağlıdır. MAX7219 her an yalnızca bir LED grubunu (veri sayfasındaki adıyla bir "digit", matriste bir satır ya da sütun) etkinleştirir, o gruptaki sekiz LED'den hangilerinin yanacağını diğer hatlardan verir, sonra bir sonraki gruba geçer. Sekiz grubun tamamı saniyede yaklaşık 800 kez taranır; göz bu hızı ayırt edemediği için görüntü sabit yanıyormuş gibi görünür. Entegre bu sırada her grubun desenini kendi içindeki 8x8 bitlik RAM'de tutar, LED akımını tek bir dirençle sınırlar ve parlaklığı 16 kademede ayarlar.
Arduino ile MAX7219 arasındaki haberleşme SPI'ye benzeyen 3 hatlı bir seri arayüzle yapılır. Her komut 16 bitlik bir pakettir: üst bayt hangi yazmaca (register) yazılacağını, alt bayt ise değeri taşır. CS (veri sayfasında LOAD) pini LOW iken bitler CLK'nin her yükselen kenarında DIN'den içeri kayar; CS tekrar HIGH olduğunda paket yazmaca işlenir. Bu yapı 74HC595 shift register ile aynı mantıktadır, ama MAX7219 tarama ve akım sınırlama işini de üstlendiği için çok daha az uğraştırır. SPI'nin genel çalışma şeklini SPI nedir? yazısında bulabilirsin.
| Özellik | Değer |
|---|---|
| Besleme gerilimi | 4,0–5,5 V (pratikte 5 V) |
| Arayüz | 3 hatlı seri (DIN, CLK, CS), en fazla 10 MHz |
| Sürdüğü LED sayısı | 64 (8x8 matris ya da 8 haneli 7 segment) |
| Tarama hızı | Tipik 800 Hz (8 hane) |
| Segment akımı | RSET direnciyle ayarlanır, en fazla 40 mA (modüllerde genellikle 10 kΩ) |
| Parlaklık | 16 kademe, görev oranı 1/32 ile 31/32 arası |
| Uyku (shutdown) akımı | Yaklaşık 150 µA |
| Girişte HIGH eşiği | En az 3,5 V (5 V beslemede) |
| Zincirleme | DOUT çıkışı bir sonraki entegrenin DIN girişine |
MAX7219'un içinde 14 adreslenebilir yazmaç vardır, ama bir LED matris için bilmen gerekenler aşağıdaki tabloda. Kütüphaneler bu yazmaçları senin yerine ayarlar; yine de ne işe yaradıklarını bilmek hata ararken çok işine yarar. Örneğin entegre ilk enerjilendiğinde uyku (shutdown) modunda başlar ve ekran karanlıktır; başlatma kodu çalışmazsa modül hiç tepki vermiyormuş gibi görünür. Kardeş entegre MAX7221 aynı yazmaçlara sahiptir, ama gerçek SPI uyumlu bir CS pini ve elektromanyetik gürültüyü azaltan, yavaş anahtarlanan segment sürücüleri vardır.
| Adres | Yazmaç | Görevi |
|---|---|---|
| 0x00 | No-Op | Zincirdeki başka bir entegreye giden paket sırasında bu entegreyi değiştirmeden bırakmak |
| 0x01–0x08 | Digit 0–7 | Sekiz satırın (ya da sütunun) 8 bitlik LED deseni |
| 0x09 | Decode Mode | 7 segment için BCD çözümleme; matriste kapalı (0x00) |
| 0x0A | Intensity | Parlaklık, 0x0 ile 0xF arası |
| 0x0B | Scan Limit | Taranacak hane sayısı; matriste 7 (sekizinin hepsi) |
| 0x0C | Shutdown | 0: uyku modu, 1: normal çalışma |
| 0x0F | Display Test | 1: bütün LED'ler tam parlaklıkta yanar |
Tek 8x8 modül mü, 4'lü 8x32 modül mü?
En sık karşılaşacağın iki modülün elektronik devresi aynıdır; fark, LED matrisin MAX7219'a nasıl bağlandığında ve kartın şeklindedir. Yeşil kartlı tek modülde DIP kılıflı (24 bacaklı) bir MAX7219 ile 1088AS gibi bir 8x8 matris bulunur; kartın bir ucunda giriş (VCC, GND, DIN, CS, CLK), diğer ucunda çıkış (VCC, GND, DOUT, CS, CLK) pinleri vardır. Mavi kartlı 4'lü modülde ise dört SMD MAX7219 matrislerin altına dizilmiştir ve dört blok fabrikada birbirine zincirlenmiştir; kartın üzerinde genellikle FC-16 yazar. Uzun bir kayan yazı için 4'lü modül hem daha ucuz hem daha derli topludur.

| Özellik | Tek 8x8 modül | 4'lü 8x32 modül (FC-16) |
|---|---|---|
| Çözünürlük | 8x8 = 64 LED | 32x8 = 256 LED |
| MAX7219 sayısı | 1 (DIP kılıf) | 4 (SMD kılıf) |
| Kodda donanım tipi | Genellikle GENERIC_HW | Genellikle FC16_HW |
| Aynı anda görünen karakter | 1 | 4–6 (harf genişliğine göre) |
| Tam parlaklıkta en fazla akım | Yaklaşık 330 mA | Yaklaşık 1,3 A |
| Uygun kullanım | Simge, zar, gülen yüz, küçük oyun | Kayan yazı, saat, skor tabelası |
MAX7219 bağlantısı: Arduino Uno, ESP32 ve Pico
Modülün beş pini vardır: VCC ve GND besleme, DIN veri, CLK saat, CS ise seçme (yükleme) hattıdır. MD_Parola ve MD_MAX72XX kütüphaneleri varsayılan olarak donanım SPI kullanır; bu durumda DIN kartın MOSI pinine, CLK ise SCK pinine bağlanmak zorundadır, CS için herhangi bir dijital pin seçebilirsin. Donanım SPI pinlerinin yerini kartına göre Pinout aracından kontrol edebilirsin. Kabloyu her zaman modülün giriş (IN) tarafına, yani DIN yazan uca tak; DOUT yazan uç bir sonraki modül içindir.
| Modül pini | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 5V (VIN) | VBUS (5 V) |
| GND | GND | GND | GND |
| DIN | D11 (MOSI) | GPIO 23 (MOSI) | GP19 (SPI0 TX) |
| CS | D10 | GPIO 5 | GP17 |
| CLK | D13 (SCK) | GPIO 18 (SCK) | GP18 (SPI0 SCK) |
ESP32 ve Pico'nun pinleri 3,3 V verir; MAX7219'un veri sayfası ise 5 V beslemede HIGH için en az 3,5 V ister. Yani 3,3 V'luk sinyaller teknik olarak sınırın biraz altında kalır. Modüllerin çoğu yine de çalışır, ama uzun kablolarda ya da bazı entegre partilerinde rastgele yanan noktalar ve bozuk görüntü görülebilir. Kalıcı çözüm DIN, CLK ve CS hatlarına 74HCT125 gibi 3,3 V'u HIGH kabul edip 5 V çıkış veren bir tampon ya da hızlı bir lojik seviye dönüştürücü koymaktır. Sinyal kablolarını 20 cm'nin altında tutmak da sorunu çoğu zaman ortadan kaldırır.
Modülleri zincirleme (daisy chain)
MAX7219'un DOUT pini, DIN'e giren veriyi 16,5 saat darbesi sonra dışarı verir. Bir modülün OUT tarafını bir sonrakinin IN tarafına bağladığında DOUT bir sonraki entegrenin DIN'ine gider, CLK ve CS ise bütün entegrelerde ortaktır. Böylece Arduino'dan yine yalnızca 3 sinyal kablosu çıkar, ama ekran 8, 16 ya da 32 blok uzunluğunda olabilir. Kütüphane her güncellemede bütün zincire sırayla paket gönderir ve CS yükseldiğinde hepsi aynı anda güncellenir. 4'lü modüllerde bu bağlantı kartın üzerinde hazırdır; iki 4'lü modülü birleştirip 8 bloklu (64x8) bir ekran yapmak için birinci modülün OUT pinlerini ikincinin IN pinlerine bağlaman ve kodda MAX_DEVICES değerini 8 yapman yeterlidir.
Kütüphanede blok numaraları DIN girişine en yakın modülden başlar ve sola doğru artar; MD_MAX72XX'e göre koordinat başlangıcı ekranın sağ üst köşesidir. Bu yüzden yazının düzgün okunması için DIN girişi sağ tarafta kalmalıdır. Zincir uzadıkça asıl sınır güç olur: her 4–8 blokta bir, 5 V ve GND'yi kalın kablolarla zincire yeniden ver ve her modülün besleme girişine 10 µF elektrolitik ile 100 nF seramik kondansatör ekle. Veri sayfası da LED'lerin anlık akım darbelerinin oluşturduğu dalgalanmayı bastırmak için bu ikiliyi önerir.
Kütüphane kurulumu: MD_MAX72XX ve MD_Parola
MAX7219 için en çok kullanılan iki kütüphane aynı yazara (majicDesigns) aittir ve birlikte çalışır. MD_MAX72XX alt seviyedeki işi yapar: modülleri başlatır, piksel ve sütun yazar, yazı tipini yönetir. MD_Parola ise bunun üzerine kayan yazı, efektler, hizalama ve bölgeler (zone) ekler. Eski örneklerde gördüğün LedControl kütüphanesi de çalışır, ama kayan yazıyı kendin yazman gerekir. Daha önce hiç kütüphane kurmadıysan Arduino kütüphane ekleme yazısına göz at.
- Arduino IDE'de Kütüphane Yöneticisi'ni aç (Araçlar > Kütüphaneleri Yönet) ve MD_Parola ara.
- majicDesigns'ın MD_Parola kütüphanesini kur. Bağımlılıkları sorduğunda Install all seç; böylece MD_MAX72XX de kurulur.
- Modülü yukarıdaki tabloya göre bağla ve 4'lü modül için kodda HARDWARE_TYPE değerini FC16_HW, MAX_DEVICES değerini 4 yap.
- Kodu yükle. Yazı ters, ayna gibi ya da dönmüş görünüyorsa endişelenme; aşağıdaki donanım tipi bölümünde tek satırla düzelteceksin.
İlk program: MD_Parola ile kayan yazı
1// MAX7219 4'lü modülde kayan yazı (MD_Parola) / Scrolling text on a 4-in-1 MAX7219 module (MD_Parola)
2#include <MD_Parola.h>
3#include <MD_MAX72xx.h>
4#include <SPI.h>
5
6#define HARDWARE_TYPE MD_MAX72XX::FC16_HW // mavi PCB'li 4'lü modül / blue-PCB 4-in-1 module
7#define MAX_DEVICES 4 // zincirdeki 8x8 blok sayısı / number of 8x8 blocks in the chain
8#define CS_PIN 10 // DIN = D11 (MOSI), CLK = D13 (SCK)
9
10MD_Parola display = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
11
12void setup() {
13 display.begin();
14 display.setIntensity(4); // parlaklık 0–15 / brightness 0–15
15 display.displayClear();
16 // metin, hizalama, hız (ms/kare), bekleme (ms), giriş efekti, çıkış efekti
17 // text, alignment, speed (ms/frame), pause (ms), entry effect, exit effect
18 display.displayText("Merhaba BlueGrays!", PA_CENTER, 50, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
19}
20
21void loop() {
22 if (display.displayAnimate()) { // efekt bittiğinde true döner / returns true when the effect ends
23 display.displayReset(); // aynı yazıyı baştan başlat / restart the same text
24 }
25}Kodun en önemli satırı displayText()'tir: sırasıyla metni, hizalamayı (PA_LEFT, PA_CENTER, PA_RIGHT), kareler arasındaki süreyi milisaniye olarak, metin yerine oturduktan sonraki bekleme süresini ve giriş ile çıkış efektlerini alır. Hız değeri küçüldükçe yazı hızlanır; 25–60 ms arası okunaklı bir kayan yazı verir. displayAnimate() ise her çağrıldığında en fazla bir kare ilerler ve hemen geri döner. Bu yüzden loop() içinde sürekli çağrılmalıdır ve kodun geri kalanında delay() kullanmamalısın; aksi hâlde yazı takılarak ilerler. Beklemeleri programı durdurmadan yapmanın yolunu millis() ve delay() yazısında bulabilirsin.
| Fonksiyon | Ne yapar? |
|---|---|
| begin() | Modülleri başlatır, uyku modundan çıkarır ve ekranı temizler |
| displayText(metin, hizalama, hız, bekleme, giriş, çıkış) | Gösterilecek metni ve efektleri ayarlar, animasyonu başlatır |
| displayAnimate() | Bir sonraki kareyi çizer; efekt bittiğinde true döner |
| displayReset() | Aynı metni ve efekti baştan oynatır |
| print("...") | Metni efektsiz ve sabit olarak yazar |
| setIntensity(0–15) | Bütün modüllerin parlaklığını ayarlar |
| setInvert(true) | Yanan ve sönük LED'leri yer değiştirir (negatif görüntü) |
| displayShutdown(true) | Ekranı uyku moduna alır; false ile yeniden açar |
| begin(2) ve setZone(0, 0, 1) | Ekranı bağımsız bölgelere böler; her bölgede ayrı yazı ve efekt olur |
Giriş ve çıkış efekti olarak PA_SCROLL_LEFT dışında birçok seçenek var: PA_PRINT (yazı birden belirir), PA_SCROLL_UP ve PA_SCROLL_DOWN (dikey kayma), PA_WIPE (silerek açılma), PA_OPENING ve PA_CLOSING (ortadan açılma ve kapanma), PA_FADE (parlaklıkla solma), PA_DISSOLVE, PA_BLINDS, PA_RANDOM ve PA_GROW_UP. Hepsini görmek için Dosya > Örnekler > MD_Parola menüsündeki Parola_Animation_Catalog örneğini yükle; HARDWARE_TYPE ve MAX_DEVICES satırlarını kendi modülüne göre değiştirmeyi unutma.
Donanım tipi (FC16_HW) seçimi ve ters/ayna görüntü hatası
MAX7219 modülü üreten firmalar 8x8 matrisi entegreye farklı şekillerde bağlar: bazılarında entegrenin "digit" hatları satırlara, bazılarında sütunlara gider; satır ya da sütun sırası da ters olabilir. Kütüphane bu farkı HARDWARE_TYPE ayarıyla telafi eder. Yanlış tip seçildiğinde modül bozuk değildir, ama harfler her 8x8 blokta ayna gibi, baş aşağı ya da 90 derece dönmüş görünür. İnternetteki eski kodların çoğu PAROLA_HW ya da GENERIC_HW ile yazıldığı için bugün satılan mavi 4'lü modüllerde en sık görülen hata budur. Aşağıdaki tablo belirtiye göre neyi değiştireceğini gösterir; tablo 4'lü FC-16 modüle göre hazırlandı.
| Ekranda gördüğün | Olası sebep | Çözüm |
|---|---|---|
| Harfler her blokta sağ-sol ayna gibi ters | PAROLA_HW seçilmiş, sütun sırası ters | FC16_HW kullan |
| Harfler her blokta 90 derece dönmüş | GENERIC_HW seçilmiş, satır ve sütun yer değiştirmiş | FC16_HW kullan |
| Harfler her blokta baş aşağı | ICSTATION_HW seçilmiş, satır ve sütun sırası ters | FC16_HW kullan |
| Bütün yazı baş aşağı ve soldan sağa akıyor | Modül ters duruyor, DIN girişi solda | Modülü 180 derece çevir; DIN girişi sağda kalsın |
| Yalnızca bazı bloklar doğru, diğerleri boş ya da karışık | MAX_DEVICES gerçek blok sayısıyla aynı değil | MAX_DEVICES'ı blok sayısına eşitle |
Parlaklık ayarı ve güç tüketimi
Parlaklık iki şeye bağlıdır. Birincisi modülün üzerindeki RSET direncidir: entegre, ISET pininden akan akımın yaklaşık 100 katını LED'lere verir. Modüllerde genellikle 10 kΩ kullanılır; bu, kırmızı LED'lerde 40 mA'in biraz üzerinde, mavi ve beyaz LED'lerde yaklaşık 40 mA'lik bir tepe akımı demektir. İkincisi yazılımla ayarlanan Intensity yazmacıdır: 0–15 arasındaki n değeri, LED'lerin her tarama aralığının (2n+1)/32'si kadar yanmasını sağlar; 0 en düşük (1/32), 15 en yüksek (31/32) parlaklıktır. Ayrıca her satır zamanın yalnızca sekizde birinde yandığı için tam parlaklıkta bile tek bir LED'in ortalama akımı yaklaşık 5 mA'dir. LED renklerine göre ileri gerilim değerlerini LED gerilimleri aracında görebilirsin.
Bir modülün ortalama akımını kabaca şöyle hesaplayabilirsin: I ≈ 8 mA + 5 mA × (2n+1)/32 × L. Burada 8 mA entegrenin kendi tüketimi, n parlaklık değeri, L ise o modülde yanan LED sayısıdır (0–64); 5 mA, 40 mA'lik tepe akımının sekizde biridir. Örneğin parlaklık 15'te 64 LED'in hepsi yanarsa 8 + 5 × 0,97 × 64 ≈ 318 mA eder; bu, veri sayfasındaki 330 mA ile uyumludur. Kayan yazıda LED'lerin genellikle yalnızca yüzde 25–35'i yanar, bu yüzden gerçek tüketim çok daha düşüktür. Aşağıdaki tablo 4'lü modül için tipik değerleri gösterir.
| Durum | Modül başına | 4'lü modül (32x8) |
|---|---|---|
| Bütün LED'ler, parlaklık 15 | ≈ 320 mA | ≈ 1,3 A |
| Bütün LED'ler, parlaklık 7 | ≈ 160 mA | ≈ 630 mA |
| Kayan yazı (LED'lerin ~%30'u), parlaklık 7 | ≈ 55 mA | ≈ 210 mA |
| Kayan yazı (LED'lerin ~%30'u), parlaklık 2 | ≈ 25 mA | ≈ 90 mA |
| Uyku modu (displayShutdown) | ≈ 0,15 mA | ≈ 0,6 mA |
Gece ekranı kısmak için parlaklığı bir LDR ışık sensörüyle otomatik ayarlayabilir, kimse yokken displayShutdown(true) ile ekranı uyutabilirsin. Pille çalışan bir tabela tasarlıyorsan yukarıdaki değerleri Pil ömrü aracına girerek kaç saat dayanacağını hesapla. İç mekânda parlaklığı 15 yerine 2–4 civarında tutmak çoğu zaman yeterlidir; hem göz yormaz hem de LED akımını yaklaşık üçte bir ile altıda bir arasına indirir.
Türkçe karakterler: ç, ğ, ı, ö, ş, ü
Arduino IDE kodu UTF-8 olarak kaydeder; yani "ş" gibi bir harf metnin içinde tek bayt değil, iki bayttır. MD_Parola ise her baytı fontta bir karakter numarası olarak arar, bu yüzden Türkçe harflerin yerinde anlamsız işaretler görünür. Kütüphanenin varsayılan fontu Latin-1 tablosundaki ç, ö, ü, Ç, Ö ve Ü harflerini içerir, ama ğ, ı, ş, Ğ, İ ve Ş bu tabloda yoktur. Çözüm iki adımlıdır: önce metni UTF-8'den fontun kodlarına çeviren küçük bir fonksiyon yazarsın, sonra eksik altı harfi addChar() ile kendi çizdiğin piksellerle eklersin.
1// MAX7219 + MD_Parola: Türkçe karakterli kayan yazı / Scrolling text with Turkish letters
2#include <MD_Parola.h>
3#include <MD_MAX72xx.h>
4#include <SPI.h>
5
6#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
7#define MAX_DEVICES 4
8#define CS_PIN 10
9
10MD_Parola display = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
11
12// Fontta olmayan 6 harf: ilk bayt genişlik, sonrakiler sütunlar (bit 0 = en üst satır)
13// 6 letters missing from the font: first byte is the width, then the columns (bit 0 = top row)
14const uint8_t trG[] = {5, 56, 69, 70, 85, 116}; // Ğ
15const uint8_t trg[] = {4, 25, 166, 166, 125}; // ğ
16const uint8_t trI[] = {3, 68, 125, 68}; // İ
17const uint8_t tri[] = {1, 124}; // ı
18const uint8_t trS[] = {5, 70, 73, 201, 73, 49}; // Ş
19const uint8_t trs[] = {4, 88, 212, 84, 52}; // ş
20
21// UTF-8 metni fontun kodlarına çevirir / converts UTF-8 text to the font's codes
22void utf8ToFont(const char *src, char *dst, size_t size) {
23 size_t n = 0;
24 while (*src && n < size - 1) {
25 uint8_t c = *src++;
26 if (c < 0x80) { dst[n++] = c; continue; } // ASCII aynen kalır / ASCII stays as is
27 if ((c & 0xE0) == 0xC0 && *src) { // 2 baytlık harf / 2-byte letter
28 uint16_t u = ((c & 0x1F) << 6) | (*src++ & 0x3F);
29 switch (u) {
30 case 0x11E: dst[n++] = (char)0x80; break; // Ğ
31 case 0x11F: dst[n++] = (char)0x81; break; // ğ
32 case 0x130: dst[n++] = (char)0x82; break; // İ
33 case 0x131: dst[n++] = (char)0x83; break; // ı
34 case 0x15E: dst[n++] = (char)0x84; break; // Ş
35 case 0x15F: dst[n++] = (char)0x85; break; // ş
36 default: dst[n++] = (u < 0x100) ? (char)u : '?'; // ç ö ü Ç Ö Ü ° fontta var / already in the font
37 }
38 continue;
39 }
40 while ((*src & 0xC0) == 0x80) src++; // desteklenmeyen karakteri atla / skip an unsupported character
41 dst[n++] = '?';
42 }
43 dst[n] = '\0';
44}
45
46char message[96];
47
48void setup() {
49 display.begin();
50 display.setIntensity(3);
51 display.addChar(0x80, trG); // addChar begin()'den sonra / addChar after begin()
52 display.addChar(0x81, trg);
53 display.addChar(0x82, trI);
54 display.addChar(0x83, tri);
55 display.addChar(0x84, trS);
56 display.addChar(0x85, trs);
57 utf8ToFont("Günaydın İstanbul! Şehirde hava 22°C, çok güzel bir gün.", message, sizeof(message));
58 display.displayText(message, PA_LEFT, 40, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
59}
60
61void loop() {
62 if (display.displayAnimate()) display.displayReset();
63}Her özel karakter dizisinin ilk baytı harfin kaç sütun genişliğinde olduğunu, sonraki baytlar ise soldan sağa sütunları verir; her baytın 0. biti en üst satırdır. Örneğin ı harfi tek bir sütundur ve 124 (0b01111100) değeri 2–6. satırları yakar; normal i harfinden tek farkı en üstteki noktanın olmamasıdır. Büyük Ğ ve İ harflerinde işarete yer açmak için harfin gövdesi iki satır kısaltıldı (7 yerine 5 satır). addChar() verileri kopyalamaz, yalnızca adreslerini saklar; bu yüzden diziler global tanımlanmalı ve begin()'den sonra eklenmelidir. Kodda 0x80–0x85 arasındaki kodlar seçildi, çünkü normal metinde bu kodlar hiç geçmez.
Saat örneği: RTC modülüyle dijital saat

Arduino'nun millis() sayacı elektrik kesilince sıfırlanır ve Uno'nun seramik rezonatörü yüzünden günde birkaç dakikaya kadar kayabilir. Gerçek bir saat için bir RTC saat modülü kullan. DS1307 modülünü I2C hattına bağla (SDA → A4, SCL → A5, VCC → 5V, GND → GND); MAX7219 SPI pinlerini kullandığı için iki modül çakışmaz. Kod için Kütüphane Yöneticisi'nden Adafruit'in RTClib kütüphanesini kur.
1// MAX7219 + DS1307 RTC ile dijital saat / Digital clock with MAX7219 + DS1307 RTC
2#include <MD_Parola.h>
3#include <MD_MAX72xx.h>
4#include <SPI.h>
5#include <RTClib.h> // Adafruit RTClib
6
7#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
8#define MAX_DEVICES 4
9#define CS_PIN 10
10
11MD_Parola display = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
12RTC_DS1307 rtc; // SDA = A4, SCL = A5
13
14char timeText[8]; // "12:34" + sonlandırıcı / + terminator
15uint8_t lastSecond = 99;
16
17void setup() {
18 display.begin();
19 display.setIntensity(2);
20 display.setTextAlignment(PA_CENTER); // print() bu hizalamayı kullanır / print() uses this alignment
21 if (!rtc.begin()) {
22 display.print("RTC?"); // modül bulunamadı / module not found
23 while (true) {}
24 }
25 if (!rtc.isrunning()) {
26 rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // ilk kurulumda derleme saati / compile time on first run
27 }
28}
29
30void loop() {
31 DateTime now = rtc.now();
32 if (now.second() != lastSecond) { // saniyede bir güncelle / update once a second
33 lastSecond = now.second();
34 // ':' ve boşluk aynı genişlikte, yazı kaymaz / ':' and space are equally wide, nothing shifts
35 sprintf(timeText, (lastSecond % 2) ? "%02d %02d" : "%02d:%02d", now.hour(), now.minute());
36 display.print(timeText);
37 }
38}Kod saniyede bir saati okur ve iki noktayı bir yakıp bir söndürür. Varsayılan fontta iki nokta (:) ile boşluk aynı genişlikte (2 sütun) olduğu için rakamlar yerinden oynamaz. RTC ilk kez çalıştırıldığında saat, kodun derlendiği an olarak ayarlanır. DS1307 ayda yaklaşık bir dakika kayabilir; daha hassas bir saat istersen DS3231 modülü al; kodda RTC_DS1307 yerine RTC_DS3231 yaz ve if (!rtc.isrunning()) koşulunu if (rtc.lostPower()) olarak değiştir. DS3231 sıcaklık dengelemeli kristali sayesinde yılda yalnızca bir dakika kadar kayar. Ekranı iki bölgeye bölerek bir tarafta saati, diğer tarafta sıcaklığı da gösterebilirsin.
Animasyon: MD_MAX72XX ile piksel piksel çizmek
Kayan yazının ötesine geçmek için MD_MAX72XX kütüphanesini doğrudan kullanabilirsin. Bu kütüphane bütün zinciri tek bir piksel ekranı gibi görür: 4'lü modülde 32 sütun ve 8 satır vardır. setPoint(satır, sütun, durum) tek bir LED'i yakar ya da söndürür, setColumn() bir sütunun 8 bitini birden yazar, clear() ekranı temizler. Koordinat başlangıcı (0, 0) sağ üst köşedir; sütun numaraları sola doğru, satır numaraları aşağı doğru artar. Aşağıdaki kod ekranın kenarlarına çarpıp seken bir top çizer:
1// MD_MAX72XX ile seken top animasyonu / Bouncing ball animation with MD_MAX72XX
2#include <MD_MAX72xx.h>
3#include <SPI.h>
4
5#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
6#define MAX_DEVICES 4
7#define CS_PIN 10
8
9MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
10
11int x = 0, y = 0; // topun konumu (sütun, satır) / ball position (column, row)
12int dx = 1, dy = 1; // hareket yönü / direction of travel
13
14void setup() {
15 mx.begin();
16 mx.control(MD_MAX72XX::INTENSITY, 2);
17 mx.clear();
18}
19
20void loop() {
21 const int lastCol = mx.getColumnCount() - 1; // 4 modülde 31 / 31 with 4 modules
22 mx.control(MD_MAX72XX::UPDATE, MD_MAX72XX::OFF); // çizim bitene kadar gönderme / hold updates while drawing
23 mx.setPoint(y, x, false); // eski konumu sil / erase the old position
24 x += dx;
25 y += dy;
26 if (x <= 0 || x >= lastCol) dx = -dx; // kenara çarpınca dön / bounce off the edge
27 if (y <= 0 || y >= 7) dy = -dy;
28 mx.setPoint(y, x, true); // yeni konumu yak / light the new position
29 mx.control(MD_MAX72XX::UPDATE, MD_MAX72XX::ON); // hepsini tek seferde gönder / send everything at once
30 delay(40);
31}Her karede önce otomatik güncelleme (UPDATE) kapatılır, eski piksel silinip yenisi çizilir, sonra UPDATE açılarak değişiklikler modüllere tek seferde gönderilir. Bu yöntem yarım kalmış bir karenin ekranda görünmesini önler. Aynı mantıkla zar, gülen yüz, yılan oyunu ya da ses seviyesi çubukları çizebilirsin. MD_MAX72XX'in kendi örneklerinde Pac-Man, robot gözleri ve kum saati gibi hazır animasyonlar da bulunur. MD_Parola kullanırken aynı çizim fonksiyonlarına getGraphicObject() ile ulaşırsın.
ESP32 ile internetten mesaj: telefondan kayan yazı
ESP32 ile kayan yazı tabelasını kablosuz hâle getirebilirsin. Aşağıdaki kod ev ağına bağlanır, önce kendi IP adresini ekranda kaydırır, sonra internetten (NTP) aldığı saati gösterir. Aynı Wi-Fi'ye bağlı telefonundan tarayıcıda bu IP adresini açtığında bir metin kutusu görürsün; yazdığın mesaj bir sonraki turda ekranda akmaya başlar ve saatle sırayla gösterilir. Modül tablodaki gibi VSPI pinlerine bağlanır: CLK GPIO 18, DIN GPIO 23, CS GPIO 5. ESP32'yi ilk kez kullanıyorsan önce ESP32 nedir? yazısına göz at.
1// ESP32: telefondan mesaj + internet saati / ESP32: message from your phone + internet time
2#include <WiFi.h>
3#include <WebServer.h>
4#include <time.h>
5#include <MD_Parola.h>
6#include <MD_MAX72xx.h>
7#include <SPI.h>
8
9#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
10#define MAX_DEVICES 4
11#define CS_PIN 5 // VSPI: CLK = GPIO 18, DIN = GPIO 23
12
13const char* ssid = "AgAdi"; // Wi-Fi adın / your Wi-Fi name
14const char* password = "Sifre123"; // Wi-Fi şifren / your Wi-Fi password
15
16MD_Parola display = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
17WebServer server(80);
18
19char message[128];
20char nextMessage[128];
21char clockText[8] = "--:--";
22bool newMessage = false;
23bool showClock = false;
24
25const char PAGE[] = R"rawliteral(<!DOCTYPE html><html><head><meta charset="utf-8">
26<meta name="viewport" content="width=device-width"><title>MAX7219</title></head><body>
27<h2>Kayan yazı / Scrolling text</h2>
28<form action="/"><input name="m" maxlength="100"> <button>Gönder / Send</button></form>
29</body></html>)rawliteral";
30
31void handleRoot() {
32 if (server.hasArg("m")) { // formdan gelen mesaj / message from the form
33 server.arg("m").toCharArray(nextMessage, sizeof(nextMessage));
34 newMessage = true;
35 }
36 server.send(200, "text/html; charset=utf-8", PAGE);
37}
38
39void setup() {
40 display.begin();
41 display.setIntensity(3);
42 display.print("WiFi..");
43 WiFi.begin(ssid, password);
44 while (WiFi.status() != WL_CONNECTED) delay(500);
45 configTime(3 * 3600, 0, "pool.ntp.org"); // Türkiye UTC+3 / Turkey is UTC+3
46 snprintf(message, sizeof(message), "IP: %s", WiFi.localIP().toString().c_str());
47 server.on("/", handleRoot);
48 server.begin();
49 display.displayText(message, PA_LEFT, 40, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
50}
51
52void loop() {
53 server.handleClient();
54 if (display.displayAnimate()) { // önceki gösterim bitti / the previous show has ended
55 showClock = !showClock;
56 if (newMessage) { // yeni mesaj sırayı keser / a new message jumps the queue
57 strlcpy(message, nextMessage, sizeof(message));
58 newMessage = false;
59 showClock = false;
60 }
61 if (showClock) {
62 struct tm t;
63 if (getLocalTime(&t, 10)) strftime(clockText, sizeof(clockText), "%H:%M", &t);
64 display.displayText(clockText, PA_CENTER, 40, 3000, PA_SCROLL_DOWN, PA_SCROLL_UP);
65 } else {
66 display.displayText(message, PA_LEFT, 40, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
67 }
68 }
69}handleRoot() formdan gelen mesajı hemen ekrana basmaz, nextMessage içinde bekletir. Mesaj, ekrandaki animasyon bittiğinde (displayAnimate() true döndüğünde) kopyalanır; böylece MD_Parola'nın o sırada okuduğu metin yarıda değişmez. configTime() içindeki 3 × 3600 değeri Türkiye'nin UTC+3 saat dilimidir; başka bir ülkedeysen kendi farkını yaz. Türkçe karakterli mesajlar için yukarıdaki addChar() satırlarını ve utf8ToFont() fonksiyonunu bu koda ekle, strlcpy() satırını da utf8ToFont(nextMessage, message, sizeof(message)) ile değiştir. İnternet saati ve gerçek zamanlı web panelleri için ESP32 NTP saat ve ESP32 web server ve WebSocket yazılarına bakabilirsin.
Raspberry Pi Pico ve MicroPython ile MAX7219
Pico'da MicroPython ile en pratik yol, açık kaynaklı max7219.py sürücüsünü (micropython-max7219) Thonny ile Pico'ya kopyalamaktır. Sürücü MicroPython'un framebuf modülünü kullandığı için text(), pixel(), line() ve rect() gibi çizim fonksiyonları hazır gelir ve 4'lü FC-16 modüllerde doğru yönde çalışır. Modülü VBUS'tan (5 V) besle; DIN'i GP19'a, CLK'yi GP18'e, CS'yi GP17'ye bağla. MicroPython, SPI0'ın MISO pinini (GP16) de ayırır; bu pini başka bir işe kullanma. framebuf'un yazı tipi 8x8 piksel ve yalnızca ASCII olduğu için 4'lü modülde aynı anda 4 harf görünür ve Türkçe harfler gösterilmez. Kurulum için Raspberry Pi Pico Nedir? ve MicroPython temelleri yazılarına bakabilirsin.
1# Pico + 4'lü MAX7219 modül: kayan yazı / Pico + 4-in-1 MAX7219 module: scrolling text
2from machine import Pin, SPI
3import time
4import max7219 # max7219.py Pico'da olmalı / must be on the Pico
5
6# GP18 = SCK -> CLK, GP19 = MOSI -> DIN, GP17 -> CS; GP16 (MISO) boş kalır / GP16 (MISO) stays free
7spi = SPI(0, baudrate=5_000_000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(19))
8display = max7219.Matrix8x8(spi, Pin(17, Pin.OUT), 4)
9display.brightness(3) # parlaklık 0–15 / brightness 0–15
10
11def scroll(text, delay_ms=35):
12 width = len(text) * 8 # her harf 8 piksel / each letter is 8 px wide
13 for x in range(32, -width, -1): # sağdan girip solda kaybolur / enters right, leaves left
14 display.fill(0)
15 display.text(text, x, 0, 1)
16 display.show()
17 time.sleep_ms(delay_ms)
18
19while True:
20 scroll("BlueGrays + Pico")
21 display.fill(0)
22 display.text("Pico", 0, 0, 1) # 4 harf tam sığar / exactly 4 letters fit
23 display.show()
24 time.sleep(1)
25 display.fill(0)
26 display.rect(0, 0, 32, 8, 1) # ekran çerçevesi / display frame
27 display.show()
28 time.sleep_ms(500)MAX7219 ile proje fikirleri
- Kayan yazı tabelası: Dükkân, sınıf ya da oda kapısı için bir mesaj panosu yap; mesajı HC-05 Bluetooth ile telefondan değiştir.
- Saat, takvim ve sıcaklık: RTC'den saati ve tarihi, DHT11 sensöründen sıcaklık ve nemi sırayla göster.
- İnternet saati ve hava durumu: ESP32 ile NTP saatini ve bir hava durumu API'sinden aldığın sıcaklığı kaydır.
- Skor tabelası: Masa tenisi ya da basketbol maçı için iki bölgeli bir ekranı IR kumandayla yönet.
- Mini oyunlar: 32x8 ekranda yılan, Pong ya da engelden kaçma oyununu bir joystick ile oyna; başka fikirler Arduino oyun projeleri yazısında.
- Ses seviyesi göstergesi: Bir ses sensöründen okuduğun değerleri 32 sütunluk bir çubuk grafik olarak çiz.
- 32x32 animasyon paneli: Dört adet 4'lü modülü alt alta dizerek yağmur, yıldız ve havai fişek gibi animasyonlar oynat.
Sık yapılan hatalar ve çözümleri
| Belirti | Olası neden | Çözüm |
|---|---|---|
| Hiçbir LED yanmıyor | Besleme yok, kablo modülün OUT tarafına takılmış ya da CS pini kodla uyuşmuyor | Kabloyu DIN yazan IN tarafına tak, CS_PIN değerini ve 5 V beslemeyi kontrol et |
| Bütün LED'ler tam parlak yanıyor ve değişmiyor | Veri ulaşmıyor: DIN ile CLK yer değiştirmiş ya da entegre test modunda kalmış | DIN'i MOSI'ye, CLK'yi SCK'ye bağla, beslemeyi kesip yeniden ver |
| Harfler ayna gibi, baş aşağı ya da 90 derece dönmüş | Yanlış HARDWARE_TYPE | 4'lü modülde FC16_HW, tek modülde GENERIC_HW dene |
| Bütün yazı baş aşağı ve soldan sağa akıyor | Modül ters monte edilmiş, DIN girişi solda | Modülü 180 derece çevir; DIN girişi sağda olmalı |
| Yalnızca bir blok çalışıyor ya da yazı kesik görünüyor | MAX_DEVICES yanlış ya da modüller arası bağlantı kopuk | MAX_DEVICES'ı blok sayısı yap, OUT → IN kablolarını kontrol et |
| Parlaklık artınca Arduino resetleniyor, görüntü titriyor | USB'nin 500 mA sınırı aşılıyor, gerilim düşüyor | Harici 5 V 2 A adaptör kullan, GND'leri birleştir, parlaklığı düşür |
| ESP32'de rastgele noktalar ve bozuk karakterler | 3,3 V sinyal 3,5 V'luk HIGH eşiğinin altında, kablolar uzun | 74HCT125 ile seviyeyi yükselt, kabloları kısalt |
| Türkçe harflerin yerinde anlamsız işaretler | UTF-8 baytları doğrudan fonta gidiyor | utf8ToFont() ve addChar() yöntemini kullan |
| Kayan yazı takılarak, kesik kesik ilerliyor | loop() içinde delay() ya da uzun süren bir işlem var | displayAnimate()'i sık çağır, beklemeleri millis() ile yap |
MAX7219, birkaç kabloyla göz alıcı bir ekran elde etmenin en ucuz yollarından biridir: tarama, akım sınırlama ve parlaklık işini entegre üstlenir, sen yalnızca ne göstereceğine odaklanırsın. Tek bir 8x8 modülle simgeler çizerek başla, ardından 4'lü modülde kayan yazıya, saate ve ESP32 ile kablosuz mesajlara geç. Renkli ve tek tek kontrol edilen LED'ler istersen WS2812B NeoPixel, yalnızca rakam gösterecek bir proje için 7 segment display de iyi seçeneklerdir. BlueGrays uygulamasında MAX7219 ile dot matrix saat ve takvim, hava istasyonu, 32x8 animasyon ve kayan yazı projelerini devre şemaları ve kodlarıyla adım adım bulabilirsin.
Sıkça sorulan sorular
MAX7219 modülünde yazı neden ters ya da ayna gibi görünüyor?
Modül üreticileri 8x8 matrisi MAX7219'a farklı şekillerde bağlar; kütüphane bu farkı HARDWARE_TYPE ayarıyla telafi eder. Bugün satılan mavi 4'lü modüllerin çoğu FC16_HW, yeşil tek modüller ise GENERIC_HW ile doğru görünür. Görüntü hâlâ yanlışsa PAROLA_HW ve ICSTATION_HW tiplerini de dene; kodda yalnızca tek satır değişir.
MAX7219 modülleri kaç tane zincirlenebilir?
Entegrenin kendisinde bir sınır yoktur; MD_MAX72XX modül sayısını bir bayt olarak tuttuğu için yazılım 255'e kadar izin verir. Pratikte sınırı güç ve sinyal kalitesi belirler: her 4–8 blokta bir 5 V ve GND'yi zincire yeniden ver, kabloları kısa tut ve her modüle 10 µF ile 100 nF kondansatör ekle. Zincir uzadıkça güncelleme süresi ve RAM kullanımı da artar.
MAX7219 ESP32 ile 3,3 V'ta çalışır mı?
MAX7219 en az 4 V beslemeyle çalışır, bu yüzden modülü ESP32'nin 5V (VIN) pininden beslemelisin. Veri sayfası 5 V beslemede HIGH için 3,5 V ister; ESP32'nin 3,3 V'luk sinyalleri çoğu modülde yine de çalışır, ama bu sınırın altındadır. Kararlı bir sonuç için DIN, CLK ve CS hatlarına 74HCT125 gibi bir seviye yükseltici koy.
MAX7219 LED matris ne kadar akım çeker?
Bir 8x8 modül tam parlaklıkta bütün LED'ler yanarken yaklaşık 330 mA, 4'lü 8x32 modül ise 1,3 A'e kadar çekebilir. Kayan yazıda LED'lerin yalnızca bir kısmı yandığı ve parlaklık genellikle 2–7 arasında tutulduğu için 4'lü modülün gerçek tüketimi çoğu zaman 100–250 mA civarındadır. Uyku modunda entegre başına yalnızca yaklaşık 150 µA harcanır.
MAX7219 ile Türkçe karakter nasıl yazılır?
MD_Parola'nın varsayılan fontunda ç, ö ve ü vardır, ama ğ, ı, ş, Ğ, İ ve Ş yoktur. UTF-8 metni fontun kodlarına çeviren küçük bir fonksiyon yazar, eksik harfleri addChar() ile kendi piksel desenlerinle eklersin. Yazıdaki Türkçe karakter örneği bu iki adımı birlikte yapar.
MAX7219 ile 7 segment display sürülebilir mi?
Evet, MAX7219 aslında 8 haneye kadar ortak katotlu 7 segment display için tasarlanmıştır ve rakamları kendisi çözen bir BCD modu vardır. Hazır 8 haneli MAX7219 display modüllerini LedControl kütüphanesinin setDigit() fonksiyonuyla kolayca kullanabilirsin. Ortak anotlu display'ler ise bu entegreye doğrudan bağlanamaz.
Bu yazıdan sonra yapabileceğin projeler
Tüm projeleri gör
Dot Matrix Saat ve Takvim (MAX7219, DS1307)
Masada ya da duvarda duran, saati ve tarihi kayan yazıyla gösteren ışıklı bir pano. 8x32 LED ekranda iki noktası her saniye yanıp sönen büyük rakamlı saat durur; her dakika başında günün adı ve tarih

Dot Matrix Saat, Takvim ve Hava İstasyonu (MAX7219, DS1307)
Masada ya da duvarda durup saati, tarihi ve odanın havasını sırayla gösteren kayan yazılı bir pano. 8x32 LED ekranda önce sıcaklık hem Celsius hem Fahrenheit olarak, sonra nem, ardından iki noktası he

4x 32x8 Matrix LED Animasyon Ve Yazı
Dört uzun LED matris modülü üst üste dizilince binden fazla ışık noktası olan kare bir ekran çıkar. Önce filmlerdeki gibi yukarıdan harfler yağmur gibi düşer, ardından bir perde açılır ve iki satırda

4x 32x8 LED Matrix – 6 Animasyon Paketi
Dört adet 32x8 LED panelin üst üste dizilmesiyle oluşan kare ekranda altı animasyon sırayla oynar: yağan dijital yağmur, büyüyen bir spiral, kendi kendine doğup ölen hücreler, dalgalanan su halkaları,

Piksel Yılan: 8x8 Matris
Klasik yılan oyununu kendi ellerinle kur ve oyna. Renkli 8x8 ışık matrisinde yeşil yılanı oyun çubuğuyla yönlendirip kırmızı elmaları yersin; her elmada yılan uzar, biraz daha hızlanır ve puanın küçük

ESP32 NTP ile İnternetten Gerçek Zaman
ESP32, Wi-Fi'a bağlanıp NTP (Network Time Protocol) sunucularından milisaniye hassasiyetiyle gerçek zamanı çeker. `configTzTime()` fonksiyonu sayesinde Türkiye saat dilimi (TRT, UTC+3) otomatik uygulanır ve yaz/kış saati uygulayan ülkelerde DST geçişi POSIX TZ string'i ile otomatik yönetilir. Saat hem Serial Monitor'e hem de opsiyonel I2C LCD'ye yazdırılır. `configTzTime()` SNTP hizmetini başlatır; ağ erişimi varken periyodik yeniden senkronizasyon yapılır ve iki senkronizasyon arasında sistem s

ESP32 RTC DS1307 ile Dijital Saat (I2C + LCD)
Bu projede DS1307 gerçek zaman saati (RTC) modülü ile 16x2 I2C LCD ekrana saat ve tarih bilgisi yansıtıyoruz. DS1307 pil destekli bir RTC'dir; ESP32 kapansa bile zamanı korur. Her iki modül de aynı I2C hattını (SDA/SCL) paylaşır, böylece sadece iki sinyal kablosu ile çoklu cihaz kontrolü öğrenmiş oluruz. Bu proje sayesinde I2C haberleşme protokolünü, RTC modüllerinin çalışma prensibini ve LCD ekranda dinamik veri gösterimini pratik bir şekilde öğreneceksiniz.

4'lü 7 Segment Display İle Dijital Saat
Mutfaktaki fırın saatine benzeyen dört haneli, ışıklı bir dijital saat. DS1302 saat modülü zamanı tutar, Arduino her saniye saati ve dakikayı okuyup dört rakamlık göstergeye yazar; saatle dakika arası
Diğer yazılar
BlueGrays uygulaması
Bu devreyi telefonunda adım adım kur
Devre şeması, kod ve parça listesi tek ekranda. 160'tan fazla Arduino, ESP32 ve Pico projesi seni bekliyor.
Telefonunla tara
Kamerayı koda tut; telefonunun uygulama mağazası açılır.
ya da mağazada aç

