MODÜL 07 DERS 4 / 6 · 60 DK

Kalibrasyon: mesafe ve açı katsayıları

Önceki derslerde robotuna kendi başına hareket etmeyi öğrettin: fazlara böldün, her fazı millis ile zamanladın. Ama bir sorun hâlâ ortada duruyor. Sen koda "2 saniye ileri git" yazdın; robot 2 saniye gitti. Peki bu kaç metre etti? "0.8 saniye dön" yazdın; bu kaç derece etti? Bilmiyorsun. Bu derste robotuna "şu kadar saniye" yerine "1 metre git, 90 derece dön" dedirteceğiz. Bunu bir sihirle değil, ölçerek yapacağız.

Kanca: gözü olmayan robot (10 dk)

🎬 VİDEO · kanca · 45 sn · robot otonom modda düz gidip masadan düşecek gibi oluyor; sonra aynı robot yerdeki bant çizgisinde tam durup 90 derece dönüyor; alt yazı "Robotun gözü yok. O zaman 1 metreyi nereden biliyor?"

Videodaki robotun üstünde ne bir kamera var, ne mesafe ölçen bir göz. Tekerleğinin kaç tur döndüğünü sayan bir parça bile yok. Yani robot, gittiği yolu göremiyor. Buna rağmen tam 1 metre gidip duruyor. Nasıl?

Sınıfa sor, önce tahmin etsinler:

Kesin cevabı şimdi vermiyoruz. Robotun elinde tek bir bilgi var: güç (ne kadar bastığı) ve süre (ne kadar sürdüğü). Bu derste bu ikisinden mesafeyi ve açıyı çıkaracağız. Ama baştan dürüst olalım: bu bir tahmin yöntemi. Ne kadar iyi tahmin olduğunu ve ne zaman yanıltacağını dersin sonunda göreceksin.

Ana etkinlik: ölç ve katsayı çıkar (20 dk)

Robotun hızını bir sayıyla bilmiyoruz. O yüzden deneyle ölçeceğiz. Yani robotu çalıştırıp kronometreyle süreyi tutacağız. İki şeyi ölçeceğiz: 1 metre kaç saniye, 90 derece kaç saniye.

Hazırlık. Robotu açık düz zemine koy. Yere bantla iki çizgi çek, aralarını metreyle tam 1 metre ölç. Robotu birinci çizginin üstüne, tekerlekleri çizgiye değecek şekilde yerleştir.

Ölçüm kodu. Ölçüm için robotun sadece düz gitmesi yeter. Otonom koduna geçici olarak şu tek satırı koy (fazları şimdilik bir kenara bırak, sadece ölçüyoruz):

void autonomousLoop() {
  surSasi(0.6f, 0.0f);   // sadece duz ileri: olcum icin
  delay(20);
}

1 metre ölçümü. Otonomu başlat ve tam o anda kronometreye bas. Robotun ön tarafı ikinci çizgiye gelince kronometreyi durdur (robotu da yakala, durmayacak). Süreyi bir kağıda yaz. Bunu 3 kez yap; robotu her seferinde başa al. Üç ölçümün ortasını (ortalamasını) al. Diyelim üç ölçüm 2.3, 2.5, 2.4 saniye çıktı; ortalaması 2.4 saniye. İşte bu senin katsayın:

0.6 güçte 1 metre = yaklaşık 2.4 saniye. Buna SANIYE_PER_METRE diyeceğiz.

90 derece ölçümü. Şimdi dönüşü ölç. Robotu düz koy, önüne baktığı yönü bantla işaretle. Ölçüm kodundaki satırı dönüş yapacak şekilde değiştir: surSasi(0.0f, 0.5f). Otonomu başlat, kronometreye bas; robot çeyrek tur (90 derece) dönüp yan tarafa bakınca durdur. Bunu da 3 kez yap, ortalamasını al. Diyelim 1.1 saniye çıktı. Ama biz "90 derece" değil, "1 derece" başına süre istiyoruz ki sonra istediğimiz açıyı hesaplayabilelim. O yüzden bölüyoruz:

90 derece 1.1 saniye ise, 1 derece = 1.1 ÷ 90 = yaklaşık 0.012 saniye. Buna SANIYE_PER_DERECE diyeceğiz.

📷 Görsel alanı · yerde iki bant çizgisi 1 metre arayla; robot birinci çizgide, ok ikinci çizgiye doğru; yanda kronometre çizimi

İki katsayını da bir kenara yaz. Bunlar senin robotunun, senin zemininin, o anki pilinin katsayıları. Başka bir robotta başka çıkar.

Kavram köprüsü: katsayı ve ölü hesap (7 dk)

Az önce yaptığın şeyin bir adı var.

Katsayı, bir çeviri kuralıdır. SANIYE_PER_METRE = 2.4 demek, "istediğim her metre için 2.4 saniye güç ver" demektir. Artık robota "1 metre" diyebilirsin; çünkü kod arkada 2.4 × 1 = 2.4 saniye hesabını yapar. 2 metre istersen 2.4 × 2 = 4.8 saniye. Katsayı, senin anladığın dili (metre, derece) robotun anladığı dile (saniye) çeviren köprüdür.

Bu yönteme ölü hesap denir. Gözü olmayan bir robotun, sadece "ne kadar güç, ne kadar süre" bilgisiyle nerede olduğunu tahmin etmesine ölü hesap denir. Denizciler yüzlerce yıl, pusula ve hızlarıyla, karayı görmeden nerede olduklarını böyle hesapladı. Robotun da şu an yaptığı tam olarak bu.

Ve şimdi bu dersin en önemli cümlesi geliyor. Ölü hesap bir tahmindir, ölçüm değil:

Robot gerçekte 1 metre gittiğini görmüyor. Sadece "1 metre kadar sürmüş olmalı" diye güveniyor. Pilin dolarken tekerlek hızlanır, robot fazla gider. Zemin halıya dönerse tekerlek kayar, robot eksik gider. Her fazda oluşan küçük sapma bir sonrakine eklenir; robot ne kadar çok hareket yaparsa hedeften o kadar uzaklaşır. Buna hata birikmesi denir.

Bunu düzeltecek bir sensör (mesela tekerleğin turunu sayan bir parça) bu robotta yok. O yüzden çözüm, katsayına körü körüne güvenmemek: kısa rutinler kur, pilin doluyken yeniden ölç, ve robotu her zaman kontrol edebileceğin bir alanda çalıştır.

Uygulama: "1 metre git, 90 derece dön" rutini (15 dk)

Şimdi katsayılarını gerçek bir otonom rutinine koyalım. Ölçüm satırını sil, faz makineni geri getir. Katsayıları en üste sabit olarak yaz (senin ölçtüğün değerlerle):

const float ILERI_GUC = 0.6f;
const float DONUS_GUC  = 0.5f;

// ÖLÇEREK bulduğun katsayilar (kendi degerlerini yaz)
const float SANIYE_PER_METRE  = 2.4f;    // 0.6 gucte 1 metre kac saniye
const float SANIYE_PER_DERECE = 0.012f;  // ayni donus gucunde 1 derece kac saniye

int faz = 0;
unsigned long fazBasi = 0;

void autonomousInit() {
  faz = 0;                 // her baslangicta bastan basla
  fazBasi = millis();
}
void autonomousLoop() {
  unsigned long gecen = millis() - fazBasi;

  // katsayidan sure hesabi (metre ve derece -> milisaniye)
  unsigned long ileriSure = (unsigned long)(SANIYE_PER_METRE  * 1.0f  * 1000);  // 1 metre
  unsigned long donusSure = (unsigned long)(SANIYE_PER_DERECE * 90.0f * 1000);  // 90 derece

  if (faz == 0) {                     // 1 metre ileri
    surSasi(ILERI_GUC, 0.0f);
    if (gecen > ileriSure) { faz = 1; fazBasi = millis(); }
  } else if (faz == 1) {              // 90 derece don
    surSasi(0.0f, DONUS_GUC);
    if (gecen > donusSure) { faz = 2; fazBasi = millis(); }
  } else {                            // dur
    surSasi(0.0f, 0.0f);
  }
  delay(20);
}

Dikkat et: kodun hiçbir yerinde artık "2400 milisaniye" gibi elle yazılmış bir sayı yok. Onun yerine SANIYE_PER_METRE * 1.0 yazıyor. Bu çok işine yarayacak: yarın robotuna 1 metre yerine 2 metre git dedirtmek istersen, 1.0f yerine 2.0f yazman yeter. 45 derece dönmesini istersen 90.0f yerine 45.0f. Katsayı hesabı gerisini kendi yapar.

Yükle, robotu boş zemine koy, otonomu başlat ve izle: robot yaklaşık 1 metre gidip yaklaşık 90 derece dönmeli. Şimdi denemeler yap:

  1. Mesafeyi değiştir. 1.0f değerini 0.5f yap. Robot şimdi yarım metre mi gidiyor? Bant çizgisiyle ölç, tuttu mu?
  2. Açıyı değiştir. 90.0f yerine 180.0f yaz. Robot geri dönecek şekilde yarım tur atıyor mu? Tutmuyorsa SANIYE_PER_DERECE katsayın biraz kaymış olabilir; yeniden ölç.
  3. Sapmayı gör. Rutini üst üste 3 kez çalıştır (robotu başa almadan, otonomu tekrar başlatarak). Robot her seferinde tam aynı yere mi geliyor, yoksa yavaşça kayıyor mu? İşte hata birikmesi bu.

Pekiştirme ve değerlendirme (6 dk)

Kısa öz-kontrol. Kodu kapat, sözlü ya da kağıda cevapla:

Günlük hayat bağı: gözleri kapalı, bir odada "üç adım at, sağa dön, iki adım at" diye kendi kendine sayarak yürümeyi dene. İlk denemede fena değilsindir. Ama bunu on kez üst üste yaparsan başladığın yerden nereye savrulduğuna bak. Gözün yokken her küçük hata bir sonrakine eklenir; senin robotun da tam olarak bu yüzden zamanla hedeften kayar. Ölü hesap ucuz ve gözsüz çalışır, ama sınırı vardır ve bu sınırı bilmek onu doğru kullanmanın anahtarıdır.

Erken bitirene ek görev: kareyi çiz (opsiyonel)

Robotuna yerde bir kare çizdir: 1 metre git, 90 derece dön, ve bunu dört kez tekrarla. Robot başladığı noktaya dönmeli.

İpucu: faz makineni uzat. faz == 0 ileri, faz == 1 dön, faz == 2 ileri, faz == 3 dön... diye sekiz faza kadar götür (dört kenar, dört köşe). Her fazda aynı ileriSure ve donusSure süreleri kullanılır.

Sonra şunu gözle ve bir arkadaşınla tartış: robot dördüncü köşeden sonra tam başladığı noktaya oturuyor mu, yoksa birkaç santim kaymış mı? Bu kayma nereden geliyor? Kareyi bir kez daha, pil biraz daha boşken çalıştır; kayma büyüdü mü? Bu deneme, ölü hesabın neden tek başına yeterli olmadığını sana en açık şekilde gösterir.