MODÜL 02 DERS 4 / 6 · 60 DK

Yazılım B: düz koda ilk adım

Bloktan yazıya (10 dk)

Geçen ders robotu ilk kez sürdün, üstelik tek satır yazı yazmadan. Blokları sürükledin, motorları tanımladın, joystick'i motora bağladın ve arcade bloğuyla robotu ortada döndürdün. Bu ders aynı işi yapacak, ama bu kez blok yok; her şeyi yazıyla söyleyeceksin.

Neden? Çünkü blok, aslında senin yerine yazılan koddur. Sürüklediğin her blok, arka planda bir ya da birkaç satır metne çevrilir ve ESP32'ye o metin yüklenir. Blok, o metni senden gizler. Bu ders o perdeyi kaldırıyor: hangi bloğun hangi satıra karşılık geldiğini yan yana göreceksin.

🎬 VİDEO · kanca · 45 sn · Solda Blocks'taki "arcade sür" bloğu, sağda aynı işi yapan iki satır kod; blok tıklanınca sağdaki satır parlar

Peki blok çalışıyorken neden yazıya geçiyoruz? Çünkü yazı sana daha çok kontrol verir. Blok kutusunun sunduğu seçeneklerle sınırlısın; yazıda ise istediğin satırı istediğin yere koyabilir, kendi kuralını ekleyebilirsin. Bu ders bittiğinde robota "RB'ye basılıyken yavaşla" gibi, hazır blok olarak bulunmayan bir davranışı sen ekleyeceksin. Blok bir başlangıç rampasıdır; yazı ise robotun tüm dilini konuşmaktır.

Başlamadan bir tahmin yürüt: sence Blocks'taki "motor tanımla" bloğunda seçtiğin 16 ve 17 numaralı pinler, yazıya döndüğünde nereye gider? Bir arkadaşınla konuş, sonra kodda ararız.

Hazır kodu yükle ve sür (20 dk)

Önce çalışan bütünü göreceğiz, sonra parçalayacağız. Aşağıdaki kod, geçen ders blokla kurduğun sürüşün tam metin karşılığı. Şimdilik anlamadığın satırlar olacak; sorun değil, önce çalıştığını görelim. Robot askıda, tekerler havada olsun.

Kodu Arduino IDE'ye olduğu gibi yapıştır ve yükle:

#define PROBOT_WIFI_AP_SSID     "RobotAdi"
#define PROBOT_WIFI_AP_PASSWORD "sifre1234"
#define PROBOT_WIFI_AP_CHANNEL  1
#include <probot.h>

const int SOL_RPWM = 16, SOL_LPWM = 17;   // sol motorun iki sinyal pini
const int SAG_RPWM = 18, SAG_LPWM = 19;   // sag motorun iki sinyal pini

// hazir yardimci: motoru hizina gore surer (-1 geri, 0 dur, +1 ileri)
void surMotor(int rpwm, int lpwm, float hiz) {
  hiz = constrain(hiz, -1.0f, 1.0f);
  if (hiz > 0) { analogWrite(rpwm, (int)(hiz * 255));  analogWrite(lpwm, 0); }
  else         { analogWrite(rpwm, 0);  analogWrite(lpwm, (int)(-hiz * 255)); }
}

void robotInit() {
  pinMode(SOL_RPWM, OUTPUT); pinMode(SOL_LPWM, OUTPUT);
  pinMode(SAG_RPWM, OUTPUT); pinMode(SAG_LPWM, OUTPUT);
}
void robotEnd() {
  surMotor(SOL_RPWM, SOL_LPWM, 0); surMotor(SAG_RPWM, SAG_LPWM, 0);
}
void teleopInit() {}
void teleopLoop() {
  auto js = probot::io::joystick_api::makeDefault();
  float ileri = js.getLeftY();
  float donus = js.getRightX();
  surMotor(SOL_RPWM, SOL_LPWM, ileri + donus);
  surMotor(SAG_RPWM, SAG_LPWM, ileri - donus);
  delay(20);
}
void autonomousInit() {}
void autonomousLoop() { delay(20); }
🎬 VİDEO · ekran-kaydi · 3 dk · Kodu yapıştır, doğru kart ve portu seç, yükle; telefonla robotun ağına bağlan, Driver Station'dan Init ve Start ile sür; sonra tek bir değeri değiştirip yeniden yükle

Yüklemeden önce bir tahmin yürüt: sol çubuğu tam ileri ittiğinde iki teker de aynı yöne mi döner, ters yönlere mi? Sağ çubuğu ittiğinde ne beklersin? Tahminini aklında tut, birazdan sınayacağız.

Bağlan ve sür. Telefonu robotun açtığı RobotAdi ağına bağla. Tarayıcıya http://192.168.4.1 yaz (https değil). Driver Station açılınca kumandayı telefona bağla ve herhangi bir tuşuna bas; tarayıcı kumandayı ancak bir tuşa basınca tanır. Sonra Init'e, ardından Start'a bas. Sol çubuk ileri geri, sağ çubuk dönüş. Tekerler dönüyorsa robotun yazılımı çalışıyor, tebrikler.

Şimdi tahminini sına. Sol çubuğu ileri it: iki teker de aynı yöne dönüp robotu ileri götürür. Sağ çubuğu it: bir taraf ileri, öbür taraf geri döner ve robot olduğu yerde döner. Diferansiyel sürüşün mantığını gövdede görüyorsun, birazdan aynı mantığı kodda bulacağız.

Şimdi bir şeyi dene ve gözle: Start'a bastıktan sonra Stop'a bas. Tekerler duruyor mu? Duruyorsa, bunu sağlayan bir satır var; birazdan onu bulacağız.

Her blok bir satır (7 dk)

Robot çalıştı. Şimdi kodun haritasını çıkaralım. İşin güzel yanı, buradaki her parçayı geçen ders zaten blokla yaptın. Karşılıkları şöyle:

Blocks'ta ne yaptınKoddaki karşılığı
Robot kurulum bloğuvoid robotInit() içi (bir kez çalışır)
Motor tanımla, pin 16 ve 17 seçconst int SOL_RPWM = 16, SOL_LPWM = 17;
Teleop loop bloğuvoid teleopLoop() içi (saniyede ~50 kez)
Joystick ekseni bloğujs.getLeftY() ve js.getRightX()
Arcade sürüş bloğuileri + donus ve ileri - donus satırları
Motor durdur bloğusurMotor(..., 0)

Tahminin doğru çıktı mı? Bloktaki 16 ve 17 pinleri, kodda en üstteki const int satırına gitti. const int, "bu bir sabit sayıdır, değişmez" demektir; pin numaralarını tek yerde tutar ki gerekince kolayca bulasın.

Dört bölgeyi tanıyalım:

Kodu kendine göre ayarla (15 dk)

Artık kodu tanıyorsun. Şimdi üstünde bilinçli değişiklikler yapacaksın. Her görevden sonra yükle, dene, ne değiştiğini gözle. Bozmaktan korkma; yukarıdaki kod her zaman burada.

  1. Robotuna isim ver. PROBOT_WIFI_AP_SSID içindeki "RobotAdi" yazısını kendi robot adınla değiştir. Yükle. Telefonun WiFi listesinde yeni adı gör. Yeni ağa bağlanıp tekrar sür.
  2. Hızı yarıya indir. teleopLoop içindeki iki değer okuma satırını şöyle yap:
    float ileri = js.getLeftY() * 0.5f;
    float donus = js.getRightX() * 0.5f;
    Robot artık en fazla yarım güçte. Yeni sürücü için birebir. 0.5f yerine 0.25f yazsan ne olurdu, tahmin et, sonra dene.
  3. Tank kontrolüne geç. Arcade'de tek çubuk yönü, tek çubuk dönüşü verir. Tank'ta ise her çubuk kendi tarafını sürer. Sürüş satırlarını şununla değiştir:
    float solHiz = js.getLeftY();
    float sagHiz = js.getRightY();
    surMotor(SOL_RPWM, SOL_LPWM, solHiz);
    surMotor(SAG_RPWM, SAG_LPWM, sagHiz);
    İki çubuk, iki taraf. Hangisi sana daha doğal geldi, arcade mi tank mı?
  4. Ters dönen motoru düzelt. Bir teker yanlış yöne dönüyorsa çözüm kodda. O motorun iki pin sabitini yer değiştir. Örneğin sağ motor tersse:
    const int SAG_RPWM = 19, SAG_LPWM = 18;   // 18 ve 19 yer degistirdi
    İleri sinyali artık öbür pine gider, motor ters yöne döner. Kabloya dokunmadan yönü düzelttin.

Küçük bir ekleme: yavaş mod butonu. Şimdi hazır koda kendin bir özellik katacaksın. Hedef: RB butonuna basılı tutunca robot yarım hızda sürülsün, bırakınca normale dönsün. Tek bir if ve bir çarpan yeter. teleopLoop'un başına şunu ekle:

float carpan = 1.0f;
if (js.getRB()) carpan = 0.5f;
float ileri = js.getLeftY() * carpan;
float donus = js.getRightX() * carpan;

js.getRB() buton basılıysa true döner; o an çarpan 0.5 olur ve iki eksen de yarıya iner. Düz koridorda RB'li ve RB'siz sürüşün farkını gör. Dar bir yerde yavaş mod ne kadar işine yarıyor, dene.

Ders sonu kontrolü (7 dk)

Kısa bir öz kontrol. Cevabını kendi cümlelerinle ver:

Günlük hayat bağı. Telefon uygulamalarındaki "sürükle bırak" ekranlar da tıpkı Blocks gibi arka planda kod üretir. Bugün yaptığın şey, o perdenin arkasına geçmek: bir aracın nasıl çalıştığını görmek yerine, ona ne yapacağını doğrudan söylemek. Bir kez metni gördükten sonra, blokların içinde ne olduğunu artık tahmin edebilirsin.

Erken bitirdiysen