// DÖKÜMANTASYON

Arduino ile Temel Programlama

Arduino mimarisinde kod geliştirirken kullanılan çekirdek fonksiyonlar, veri tipleri, lojik yapılar ve modüler programlama mantığı.

// MODÜL 00

Çekirdek (Core) Fonksiyon Mimarisi

Bir bilgisayar programı çalıştırıldığında işletim sistemi işletim sırasını yönetir. Ancak Arduino gibi bir mikrodenetleyicide (mikrokontrolcü) bir işletim sistemi yoktur; kod doğrudan ham donanım üzerinde (bare-metal) çalışır. Bu nedenle işlemcinin hayata gözlerini açtığı andan itibaren ne yapacağını bilen iki ana bloğa ihtiyacı vardır:

// Giriş/Çıkış Komutlarının Derin Analizi

Arduino'nun dış dünya ile iletişim kurmasını sağlayan en temel 3 fonksiyon şunlardır:

LAB_00_BLINK.ino (Detaylı Analizli) [Tinkercad Devresi]
// Arduino IDE derleyicisi kodları derlemeye buradan başlar.
void setup() {
  // Arduino üzerindeki dahili L ledinin bağlı olduğu 13. pini 
  // dışarıya enerji aktarabilecek şekilde ÇIKIŞ olarak yapılandırıyoruz.
  pinMode(LED_BUILTIN, OUTPUT); 
}

// Setup bitti. Şimdi aşağıdaki loop bloğu sonsuza kadar dönecek:
void loop() {
  digitalWrite(LED_BUILTIN, HIGH); // 13. pine 5V elektrik ver. LED yanmaya başladı.
  delay(1000);                     // İşlemciyi 1 saniye boyunca bu satırda kilitle, durum değişmesin.
  digitalWrite(LED_BUILTIN, LOW);  // 13. pinin elektriğini kes (0V). LED söndü.
  delay(1000);                     // Sönük vaziyette 1 saniye bekle. 
  // Süre bittiğinde otomatik olarak loop'un ilk satırına (Line 9) geri zıpla.
}
// MEYDAN OKUMA / LABORATUVAR GÖREVLERİ
  1. Dahili LED'in 2 saniye açık kalıp, yarım saniye (500ms) kapalı kalacağı asimetrik bir ritim oluşturun.
  2. Mors alfabesindeki "S" harfi gibi (3 kez hızlıca peş peşe) yanıp sönen bir sinyal algoritması kurun.
// MODÜL 01

Konsol Dünyasına Giriş & Seri İletişim

Arduino tek başına çalışırken arka planda ne düşündüğünü, sensörlerden hangi sayısal değerleri okuduğunu veya kodun neresinde takıldığını göremeyiz. Çünkü kartın üzerinde bir ekran yoktur. İşte bu noktada imdadımıza Seri Haberleşme (Universal Asynchronous Receiver-Transmitter - UART) protokolü yetişir. Arduino, USB kablosu üzerinden bilgisayardaki "Seri Port Ekranı" (Serial Monitor) ile konuşabilir.

// Seri Port Fonksiyonlarının Farkları

LAB_01_SERIAL.ino [Tinkercad Devresi]
void setup() {
  // Haberleşme kanalı saniyede 9600 bit hızında açılıyor.
  Serial.begin(9600); 
  
  // İlk açılış mesajları basılıyor. Sadece 1 kez görünecekler.
  Serial.println("--- SISTEM BASLATILDI ---");
  Serial.print("Yazilim Yukleniyor... ");
  delay(1000); // Kullanıcı yazıyı okuyabilsin diye yapay gecikme
  Serial.println("[OK]"); // print'ten ötürü bu yazı hemen yanına eklenecek
}

void loop() {
  // Aşağıdaki metin her 3 saniyede bir alt alta ekrana akacak.
  Serial.println("Sistem hatti aktif, veri bekleniyor...");
  delay(3000); 
}
// SERİ PORT MONİTÖR ÇIKTISI (GÖRSEL AKIŞ)
--- SISTEM BASLATILDI ---
Yazilim Yukleniyor... [OK]
Sistem hatti aktif, veri bekleniyor...
Sistem hatti aktif, veri bekleniyor...
// MEYDAN OKUMA / LABORATUVAR GÖREVLERİ
  1. `setup()` bloğu içerisinde ASCII karakterlerini kullanarak ekrana bir kare kutu veya `~/root` logosu çizin.
  2. Sonsuz döngü (`loop`) içerisinde her adımda ekrana "İşlem yapılıyor..." yazan ve her satırın başına nokta koyan bir akış tasarlayın.
// MODÜL 02

Bellek Yönetimi & Değişkenler

Değişkenler, program akışında sensörlerden gelen verileri veya matematiksel hesaplama sonuçlarını geçici olarak sakladığımız RAM (SRAM) kutucuklarıdır. Klasik bir bilgisayarda gigabaytlarca RAM bulunurken, bir Arduino Uno'da sadece 2 Kilobayt (2048 bayt) RAM bulunur. Bu yüzden değişken tiplerini doğru seçmek hayati önem taşır; yanlış seçim belleğin taşmasına (`stack overflow`) ve kartın kilitlenmesine neden olur.

// Veri Tiplerinin Teknik Anatomisi

Veri Tipi Bellek Boyutu Saklayabildiği Değer Aralığı Kullanım Amacı
boolean 1 Bayt (8-bit) true (1) veya false (0) Mantıksal anahtarlar, açık/kapalı durumları.
char 1 Bayt (8-bit) -128 ile 127 (Tek bir ASCII karakteri) 'A', 'k', '9' gibi tek tırnak içinde yazılan karakterler.
int 2 Bayt (16-bit) -32,768 ile 32,767 Standart tam sayılar, döngü sayaçları.
float 4 Bayt (32-bit) -3.4028235E+38 ile 3.4028235E+38 Kesirli ve ondalıklı sayılar (Örn: Hassas sıcaklık verisi).
LAB_02_VARIABLES.ino [Tinkercad Devresi]
// Değişken Tanımlama Formülü: Veri_Tipi degisken_adi = ilk_deger;
int tamsayiX = 45;              // Hafızada 2 bayt yer kaplar
float ondalikY = 12.85;          // Hafızada 4 bayt yer kaplar
char karakterA = 'K';            // Karakterler TEK tırnak içinde yazılır
boolean sistemDurumu = true;     // Sadece true veya false alabilir

void setup() {
  Serial.begin(9600);
  
  // Farklı veri tipleri matematiksel işleme girebilir ancak veri kaybına dikkat edilmelidir.
  // int ile float toplanırsa sonuç doğruluğu korumak için float tipinde saklanmalıdır.
  float toplam = tamsayiX + ondalikY;
  
  Serial.print("Veri A: "); Serial.println(karakterA);
  Serial.print("Matematiksel Toplam: "); Serial.println(toplam); // Ekrana 57.85 yazar
  Serial.print("Sistem Durumu (Lojik): "); Serial.println(sistemDurumu); // Ekrana true yerine '1' basar
}

void loop() {}
// MEYDAN OKUMA / LABORATUVAR GÖREVLERİ
  1. Kök dizinde iki adet `int` tipinde kenar uzunluğu tanımlayıp, dikdörtgenin alanını ve çevresini hesaplayarak Seri Monitör'e basan algoritmayı kurun.
  2. Bir havuz problemi simülasyonu yapın: Saatte 5.4 litre su akıtan bir musluğun 6 saat sonunda havuzda biriktirdiği toplam su miktarını ondalıklı (`float`) olarak ekrana yazdırın.
// MODÜL 03

Karar Yapıları & Mantıksal Algoritmalar

Akıllı bir sistem, gelen verileri değerlendirip kendi kendine karar verebilen sistemdir. Program akışını dallandırmak için if (eğer), else if (değilse eğer) ve else (hiçbiri değilse) bloklarını kullanırız. İşlemci parantez içindeki ifadenin doğru (`true`) olup olmadığına bakar. Doğruysa o bloğun içine dalar, yanlışsa o bloğu pas geçer.

// Mantıksal Operatörler Kılavuzu

LAB_03_CONDITIONALS.ino [Tinkercad Devresi]
int sensorSicaklik = 34; // Sensörden bu değerin okunduğunu varsayalım

void setup() {
  Serial.begin(9600);
  
  // Koşul 1: Sıcaklık 40 dereceye eşit veya daha büyük mü?
  if(sensorSicaklik >= 40) {
    Serial.println("ALARM: Kritik Yuksek Sicaklik!");
  } 
  // Koşul 2: İlk koşul sağlanmadıysa buraya bak. Değer 20 ile 40 arasında mı?
  else if(sensorSicaklik >= 20 && sensorSicaklik < 40) {
    Serial.println("DURUM: Sicaklik Degerleri Normal."); // 34 bu aralığa uyar
  } 
  // Koşul 3: Yukarıdaki olasılıkların hiçbiri gerçekleşmediyse otomatik burası çalışır.
  else {
    Serial.println("UYARI: Dusuk Sicaklik Gerilimi.");
  }
}

void loop() {}
// MEYDAN OKUMA / LABORATUVAR GÖREVLERİ
  1. Girilen bir `int vize` ve `int final_notu` değişkenlerinin ortalamasını alıp (Vize %40, Final %60), ortalama 50 altındaysa "Kaldı", üstündeyse "Geçti" basan sistemi yazın.
  2. Bir araç hız simülasyonu kurun: Hız 120'den büyükse "Ceza Puanı İşlendi", 90-120 arasındaysa "Yüksek Hız Sınırı", 90 altındaysa "Güvenli Sürüş" çıktıları üretilsin.
// MODÜL 04

Döngüler (Loops)

Bazen bir işlemi tek bir kez değil, belirli bir sayıda veya bir şart gerçekleşene kadar ardı ardına yapmamız gerekir. Örneğin, bir uyarı buzzer'ını 5 kez peş peşe öttürmek veya bağlı olan 10 tane LED'i sırayla açmak gibi. Kod satırlarını kopyala-yapıştır yapmak yerine döngü mimarilerini kullanırız. En sık kullanılan döngü yapısı for döngüsüdür.

// For Döngüsünün 3 Silahşörü

Bir `for` parantezi içerisine noktalı virgüllerle ayrılmış 3 parametre yazılır:
for(başlangıç_değeri; döngü_şartı; değişim_miktarı)

  1. Başlangıç: Döngüde sayacı tutacak olan değişkenin doğduğu yerdir (Örn: `int i = 1;`).
  2. Şart: Döngünün çalışmaya devam edip etmeyeceğini denetler (Örn: `i <= 5;`). Şart doğru olduğu sürece döngü döner.
  3. Değişim: Blok içindeki kodlar çalışıp bittikten sonra sayacın ne kadar artacağını veya azalacağını belirler (Örn: `i++` ifadesi sayacı 1 arttırır).
LAB_04_LOOPS.ino [Tinkercad Devresi]
void setup() {
  Serial.begin(9600);
  
  Serial.println("Siralama Dongusu Basliyor:");
  
  // i değişkeni 1'den başlar, 5'e eşit veya küçük olduğu sürece döner, her turda i bir artar.
  for(int i = 1; i <= 5; i++) {
    Serial.print("Dongu Tur Numarasi: ");
    Serial.println(i);
    delay(250); // Her turun arasında çeyrek saniye bekle
  }
  
  Serial.println("Dongu bitti, siradaki kod satirlarina geciliyor.");
}

void loop() {}
// MEYDAN OKUMA / LABORATUVAR GÖREVLERİ
  1. `for` veya `while` döngüsü kullanarak 1 ile 50 arasındaki yalnızca 3'e tam bölünebilen sayıları süzüp ekrana basan kodu yazın.
  2. Seri ekranda yıldız (`*`) karakterini kullanarak yan yana 10 adet yıldız basan, ardından bir alt satıra geçen döngü mekanizmasını tasarlayın.
// MODÜL 05

Diziler (Arrays)

Aynı türdeki verileri (örneğin 10 farklı odanın sıcaklık bilgisini) saklamak için 10 ayrı değişken (`sicaklik1`, `sicaklik2`...) tanımlamak hamallıktır. Bunun yerine, ortak bir isim altında bir çekmece dolusu veri saklamamıza imkan veren yapılara Dizi (Array) denir. Yazılım dünyasında dizilerin ilk elemanı her zaman 0. indekste yer alır.

// Kritik İndeks ve Sınır Kuralları

Eğer bir diziyi 4 elemanlı tanımladıysanız (`int veri[4]`), bu dizinin geçerli odacıkları 0, 1, 2 ve 3'tür. Olmayan 4. indeksteki elemanı okumaya veya değiştirmeye çalışırsanız (`veri[4]`), Arduino RAM'deki başka rastgele bir verinin üzerine yazar. Buna "Sınır Taşması Hatası" denir ve projelerde çözülmesi en zor donanımsal sapmalara yol açar.

LAB_05_ARRAYS.ino [Tinkercad Devresi]
// 4 eleman kapasiteli tam sayı dizisi beyanı
// Indeksler:        0.  1.  2.  3.
int analogNotlar[4] = {70, 85, 40, 95};

void setup() {
  Serial.begin(9600);
  
  // Dizinin 3. elemanına (yani 2. indekse) ulaşalım:
  Serial.print("Dizinin 3. Elemani: ");
  Serial.println(analogNotlar[2]); // Ekrana 40 basar
  
  // Bir elemanın değerini güncelleme:
  analogNotlar[0] = 100; // Artık 70 silindi, yerine 100 yazıldı.
}

void loop() {}
// MEYDAN OKUMA / LABORATUVAR GÖREVLERİ
  1. İçinde 5 adet tam sayı barındıran bir dizi oluşturun. Bir `for` döngüsü yardımıyla bu dizideki tüm sayıların aritmetik ortalamasını hesaplayıp ekrana yazdırın.
  2. Dizi elemanlarını tarayarak içlerindeki en büyük sayıyı (Maximum Value) bulup ekrana yazdıran arama algoritmasını kurgulayın.
// MODÜL 06

Fonksiyonlar (Metotlar)

Yazılım mühendisliğinin en temel kuralı **DRY (Don't Repeat Yourself - Kendini Tekrar Etme)** ilkesidir. Kod yazarken aynı hesaplamayı veya işlem serisini defalarca kullanıyorsak, bunu bağımsız bir paket haline getirmeliyiz. İşte bu paketlere Fonksiyon denir. Fonksiyonlar bir işi yapmak için parametre (girdi) alabilir ve işlem sonucunu çağrıldıkları yere geri fırlatabilirler (çıktı).

// Void ve Geri Dönüş Tiplerinin Ayrımı

Eğer bir fonksiyon yapacağı işin sonunda geriye matematiksel bir sayı veya lojik bir cevap döndürmeyecekse, sadece içine yazılan kod satırlarını çalıştırıp görevi bitirecekse başına void kelimesi konur (Tıpkı `setup()` ve `loop()` gibi). Ancak hesaplama yapıp çağrıldığı yere bir değer verecekse, döndüreceği verinin tipi (`int`, `float`, `char`) yazılmak zorundadır ve fonksiyon içerisinde return anahtar kelimesiyle süreç sonlandırılır.

LAB_06_FUNCTIONS.ino [Tinkercad Devresi]
// Geri dönüş değeri 'int' (tam sayı) olan, dışarıdan iki parametre alan fonksiyon:
int alanHesapla(int taban, int yukseklik) {
  int sonuc = (taban * yukseklik) / 2;
  return sonuc; // Hesaplanan değeri fonksiyonu çağıran satıra teslim et
}

void setup() {
  Serial.begin(9600);
  
  // Fonksiyonun çağrılması: 10 ve 5 değerleri kurye gibi fonksiyona taşınır
  int ucgenAlani = alanHesapla(10, 5); 
  
  Serial.print("Hesaplanan Ucgen Alani: ");
  Serial.println(ucgenAlani); // Ekrana 25 basar
}

void loop() {}
// MEYDAN OKUMA / LABORATUVAR GÖREVLERİ
  1. Kendisine parametre olarak gönderilen bir sayının tek mi çift mi olduğunu analiz edip geriye `true` ya da `false` dönen mantıksal bir fonksiyon yazın.
  2. Seri ekrandan çağrıldığında ekrana sürekli olarak 30 adet kısa çizgi (`------------------------------`) çeken geri dönüşsüz (`void`) bir süsleme fonksiyonu oluşturun.