Yazılım: servoya açı komutu ver, gripper'ı aç-kapat
Kavrayan el (10 dk)
Geçen derslerde robotun kollarını, dişlilerini ve servoya giden kabloyu yerine koydun. Şimdi o gripper'a hayat vereceksin. Bu dersin sonunda bir butona basınca gripper'ın kapanacak, başka bir butonla açılacak; kavrama ve bırakma açılarını da kendin ayarlayacaksın.
Önce bir soru. Bir DC motor, ona güç verdiğin sürece döner; gücü kestiğinde durur ama nerede durduğunu bilemezsin. Peki gripper'ın parmaklarını tam yarıya kadar kapatıp orada tutmak istesen? Sürüş motoruyla bunu yapamazsın; o sadece "dön" ya da "dur" bilir. İşte gripper'daki servo bunun için var.
Videoyu izledikten sonra bir arkadaşınla konuş: parmaklar kapandıktan sonra videoda motor sesi duyuyor musun? Cisim havadayken parmaklar geri kaymıyor, olduğu yerde kalıyor. Sence servoya sürekli "kapan" komutu mu gönderiliyor, yoksa bir kez "şu kadar kapan" deyip bırakılıyor mu? Tahminini aklında tut; kodda cevabını bulacağız.
Kodu yükle ve gripper'ı kullan (20 dk)
Önce çalışan bütünü görelim, sonra parçalayacağız. Aşağıdaki kod, senin zaten bildiğin sürüşün üstüne gripper kontrolünü ekler. Sürüş satırları eskisiyle birebir aynı; yeni olan tek şey servoyla ilgili birkaç satır. Robot askıda dursun, ama gripper serbest kalsın ki parmakların açılıp kapandığını görebilesin.
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
const int SERVO_PIN = 4; // gripper servosunun 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)); }
}
// hazir kalip: dereceyi (0-180) servo sinyaline cevirir
void servoAci(float derece) {
derece = constrain(derece, 0.0f, 180.0f);
int us = 500 + (int)(derece / 180.0f * 2000);
ledcWrite(SERVO_PIN, (uint32_t)us * 16383 / 20000);
}
void robotInit() {
pinMode(SOL_RPWM, OUTPUT); pinMode(SOL_LPWM, OUTPUT);
pinMode(SAG_RPWM, OUTPUT); pinMode(SAG_LPWM, OUTPUT);
ledcAttachChannel(SERVO_PIN, 50, 14, 7); // hazir kalip: servo icin 50 Hz sinyal kurulumu
servoAci(90.0f); // orta konumdan basla
}
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);
if (js.getA()) servoAci(20.0f); // A: parmaklari kapat
else if (js.getB()) servoAci(110.0f); // B: parmaklari ac
delay(20);
}
void autonomousInit() {}
void autonomousLoop() { delay(20); }
Yüklemeden önce bir tahmin yürüt: A'ya bir kez basıp bıraktığında parmaklar kapanacak. Sonra elini butondan çektiğinde ne olur, geri açılır mı, kapalı mı kalır? Tahminini bir kenara yaz.
Bağlan ve dene. 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 bir tuşuna bas; tarayıcı kumandayı ancak bir tuşa basınca tanır. Sonra Init'e, ardından Start'a bas.
Şimdi A'ya bas: parmaklar kapanır. B'ye bas: açılır. Bir de tahminini sına; A'ya basıp elini çektiğinde parmaklar kapalı kalır, çünkü servo son söylenen açıda durur ve orayı korur. Sürüş çubuklarını da dene; gripper açıp kapanırken robot yine sürülüyor. İkisi aynı anda çalışıyor.
Bir şeyi daha gözle ve kulağını ver: parmaklar kapandıktan sonra servodan çok hafif bir uğultu gelebilir. Bu, servonun konumunu koruma sesidir. Cismi elinle hafifçe itmeye çalış; servo geri direnir. DC motorun asla yapamayacağı şey bu.
Servo neden farklı (7 dk)
Gripper çalıştı. Şimdi olan bitenin adını koyalım.
Robotu süren motorlar DC motor. Onlara "dön" dersin, dönerler; "dur" dersin, dururlar. Ama nerede durduklarını bilmezler. Gripper'daki parça ise servo motor. Servoya bir derece söylersin, o dereceye gider ve komut değişene kadar orada durup o açıyı korur. "Yarıya kadar kapan ve orada kal" diyebildiğin motor budur.
Kodda bunu üç yerde görüyorsun:
ledcAttachChannel(SERVO_PIN, 50, 14, 7);Bu satır servoyu bir kez kurar. Servo, saniyede 50 kez tekrarlanan (yani 50 Hz) özel bir sinyal ister; bu satır o sinyali hazırlar. Nasıl çalıştığını açmana gerek yok, hazır bir kalıp; sadecerobotInitiçinde bir kez bulunsun yeter.servoAci(...)Hazır bir kalıp. Ona bir derece verirsin (0 ile 180 arası), o dereceyi servonun anlayacağı sinyale çevirip gönderir. İçindeki hesabı bilmene gerek yok; sen sadece kaç derece istediğini yazarsın.- Butonlar.
js.getA()A tuşu basılıysatruedöner. O anservoAci(20.0f)çalışır ve parmaklar 20 dereceye, yani kapalı konuma gider.js.getB()ise 110 dereceye, açık konuma götürür.
Kancadaki sorunun cevabı buydu: servoya sürekli komut yağdırmıyorsun. A'ya bastığın anda bir kez "20 dereceye git" dersin; servo oraya gider ve sen başka bir şey söyleyene kadar orada kalır. Butonu bıraksan da açı değişmez.
Kalibrasyon: doğru açıları bul (15 dk)
Koddaki 20 ve 110 değerleri bir tahminden ibaret. Senin gripper'ın tam kapanması için belki 15 derece gerekir, belki 30. Bunu hesapla bulamazsın; kalibrasyon yaparak, yani deneyerek bulursun. Robotu yakından izleyerek ve servoyu dinleyerek çalış.
Önce kapanma açısını ayarla. if (js.getA()) servoAci(20.0f); satırındaki 20.0f değerini değiştir, yükle, A'ya bas, gözle:
- Değeri biraz düşür, örneğin
15.0f. Parmaklar daha çok kapanır. Bir cisim koy; iyice kavrıyor mu? - Daha da düşür,
5.0fdene. Burada dikkat: parmaklar birbirine ya da gövdeye dayandığında servo daha ileri gitmeye çalışıp gidemez. O an servodan zorlanma sesi gelir, uzun bir uğultu duyarsın. Bu sesi duyduğun an dur. Servo, gidemeyeceği bir yere itiliyor demektir; bu ısınmasına ve yıpranmasına yol açar. - Sesi duyduğun değerden geri çek. Servo rahatça, ses çıkarmadan durabildiği en kapalı açıyı bul. Cismi tutan ama servoyu zorlamayan değer, senin doğru kapanma açındır.
Şimdi açılma açısını ayarla. servoAci(110.0f) içindeki 110.0f ile aynı şeyi yap. Parmakların cismi rahatça bırakacak kadar açıldığı, ama gripper'ın mekaniğini uçta zorlamadığı değeri bul. Çok büyük bir açı da servoyu diğer uçta zorlar; yine kulağını ver.
Servo bir uçta zorlanıp uğuldarsa, o açıyı asla kodda bırakma. Zorlanan servo ısınır, dişlileri yıpranır ve zamanla bozulur. Kural basit: servoyu duyduğun yerde değil, rahat durduğu yerde bırak.
Kalibrasyon bitince kapanma ve açılma açıların hazır. Bunları bir kenara not et; sonraki derste, farklı nesneler için bu açıları tek tek yeniden ayarlayacaksın.
Ders sonu kontrolü (6 dk)
Kısa bir öz kontrol. Cevabını kendi cümlelerinle ver:
- Gripper'ı A ve B ile açıp kapatabildin mi?
- Servo motorun DC motordan farkını bir cümleyle söyleyebiliyor musun?
- Kapanma ve açılma açılarını kalibre ettin mi? Servonun zorlandığı sesi bir kez duydun mu?
- A'ya basıp elini çekince parmakların neden açık kalmadığını açıklayabiliyor musun?
Günlük hayat bağı. Bir yazıcının kağıt tutucusu, bir kameranın açı motoru, oyuncak bir robot kolun eklemi... hepsi servo mantığıyla çalışır: bir konuma git ve orada dur. Kalibrasyon da mühendislikte her yerde var. Bir 3D yazıcı ilk çalıştırılırken, bir robot kol kurulurken uç noktaları hep denenerek ve dinlenerek ayarlanır. Bugün servoyu dinleyip geri çekmeyi öğrendin; bu, gerçek bir mühendisin refleksidir.
Erken bitirdiysen
- Nazik bırakma. Şimdi cisim tam açık konumda birden düşüyor olabilir. Açılma açını biraz azalt (örneğin 110 yerine 95), böylece parmaklar cismi tutmayı bırakır ama tam sonuna kadar açılıp fırlatmaz. Kavrama ve bırakma arasındaki farkı gözle.
- Sürüş ile eşle. Kapanma açısını daha da ince ayarla: robotu bir cisme doğru sür, tam yanına gelince A'ya bas, kaldır, taşı ve bir başka noktaya bırak. Tut-taşı-bırak zincirini baştan sona tek seferde yapabiliyor musun? Bu, sıradaki modüllerde robotuna verdiğin görevlerin provası.