Çizgi izleyen robot kodu:

#include <QTRSensors.h> //Qtr v4.0 

#define AIN1 4 //A sağ motor.
#define AIN2 3
#define ENA 5

#define ENB 6 //B sol motor.
#define BIN1 7
#define BIN2 8
#define STBY 9

#define sensorSayisi 8
#define sensorOrnekSayisi 4
#define emiterPini 11
#define LED 13

int maxHiz = 70; // Motor pwm ayarı 0 - 255.

int hata = 0, turev = 0;
float KP = 0.03, KD = 0.5; // Oran (KP) ve türev (KD) sabitleri. (Her araca göre ayar yapılmalıdır.)

unsigned int pozisyon = 3500;

int fark = 0; // Motorlara uygulanan fark.
int sonHata; // Orantılı son değer. (Hatanın türevini hesaplamak için kullanılır.)
int hedef = 3500; // Sensörden gelen 0 - 7000 arası değerin orta noktası.

QTRSensors qtr; // qtr isimli nesne oluşturuldu.
unsigned int sensor[sensorSayisi];

void setup() {
  qtr.setTypeAnalog();  //QTR-8A ayarla. (QTR-8RC için qtr.setTypeRC() fonksiyonu kullanılır.)
  qtr.setSensorPins((const uint8_t[]) {
    A0, A1, A2, A3, A4, A5, A6, A7
  }, 8);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(STBY, OUTPUT);

  delay(1000); //Araca enerji verince 1sn bekle
  kalibrasyon(1); // 0 elle, 1 otomatik kafa sallama.
}

void loop() {
  sensorOku();
  pd();
}

void sensorOku() {
  pozisyon = qtr.readLineWhite(sensor); // Beyaz çizginin pozisyonunu oku. (0 - 7000)
  hata = pozisyon - hedef; // Pozisyondan 3500 (hedef) çıkar. Hatayı bul.
  qtr.read(sensor); // Sekiz sensörün ham değelerini oku.
}

void pd() {
  turev = hata - sonHata; // Hatadan bir önceki hatayı çıkar.
  sonHata = hata; // Şimdiki hatayı kaydet.

  fark = ( hata * KP) + ( turev * KD ); // Motorlara uygulanacak farkı hesapla.

  constrain(fark, -maxHiz, maxHiz); // fark en fazla maxHiz olsun.

  if ( fark < 0 ) // fark negatif ise
    motor(maxHiz, maxHiz + fark); // Sağ motorun hızını düşür.
  else // fark negatif değilse
    motor(maxHiz - fark, maxHiz); // Sol motorun hızını düşür.
}

void motor(int solMotorPWM, int sagMotorPWM) {
  digitalWrite(STBY, HIGH);

  if ( solMotorPWM >= 0 )  { // İleri.
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);
  }
  else  { // Negatifse geri döndür.
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);
    solMotorPWM *= -1;
  }
  analogWrite(ENB, solMotorPWM);

  if ( sagMotorPWM >= 0 )  { // İleri.
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
  }
  else  { // Negatifse geri döndür.
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    sagMotorPWM *= -1;
  }
  analogWrite(ENA, sagMotorPWM);
}

void kalibrasyon(bool secim) { // 1 otomatik, 0 elle.
  if (secim) { // secim 1 ise otomatik kalibrasyon yap.
    byte hiz = 40; // Aracın kafasını sallama hızı.
    for (byte i = 0; i < 3; i++) {  // Sağa sola üç kez kafa salla.
      while (sensor[7] < 300) {
        motor(hiz, -hiz);
        qtr.calibrate();
        sensorOku();
      }
      while (sensor[7] > 700) {
        motor(hiz, -hiz);
        qtr.calibrate();
        sensorOku();
      }
      while (sensor[0] < 300) {
        motor(-hiz, hiz);
        qtr.calibrate();
        sensorOku();
      }
      while (sensor[0] > 700) {
        motor(-hiz, hiz);
        qtr.calibrate();
        sensorOku();
      }
      while (sensor[3] > 500)  { // Ortada dur.
        motor(hiz, -hiz);
        qtr.calibrate();
        sensorOku();
      }
    }
  } else { // secim 0 ise elle kalibrasyon yap.
    for ( byte i = 0; i < 70; i++)  { // Dahili LED yanıp söndüğü sürece (3 sn) elle kalibrasyon yap.
      digitalWrite(LED, HIGH); delay(20);
      qtr.calibrate();
      digitalWrite(LED, LOW); delay(20);
      qtr.calibrate();
    }
  }
  motor(0, 0);
  delay(2000); // Kalbirasyondan sonra 3 sn bekle.
}

hizliCizgiIzleyenQtrV4


hizliCizgiIzleyenQtrV3

ÖNEMLİ UYARI! Yukarıdaki kod Qtr 3.0 kütüphane kodlarıdır. Arduino güncel kütüphanesi 4.0 dır. aşağıdaki kütüphaneyi yüklemezseniz hata verecektir.

qtr-sensors-arduino-3.0.0 kütüphane dosyası

QTR-8x datasheet

QTR_arduino_library

Hızlı Çizgi izleyen robot (PCB gövde)

araba_hizli proteus dosyası

hizli_cizgi_izleyenSTL

L298N motor sürücü için fonksiyon


// BTS7960 (veya L298N) motor sürücü bağlantıları.
#define solRPWM 6 // Sol motor.
#define solLPWM 10 // Sol motor.
#define sagRPWM 5 // Sağ motor.
#define sagLPWM 9 // Sağ motor.


void motor(int solMotorPWM, int sagMotorPWM) {
  if ( solMotorPWM >= 0 )  { // İleri.

    analogWrite(solRPWM, solMotorPWM);
    analogWrite(solLPWM, 0);
  }
  else  { // Negatifse geri döndür.
    analogWrite(solRPWM, 0);
    analogWrite(solLPWM, abs(solMotorPWM));
  }

  if ( sagMotorPWM >= 0 )  { // İleri.
    analogWrite(sagRPWM, sagMotorPWM);
    analogWrite(sagLPWM, 0);
  }
  else  { // Negatifse geri döndür.
    analogWrite(sagRPWM, 0);
    analogWrite(sagLPWM, abs(sagMotorPWM));
  }
}

void ileri() {
  motor(hiz, hiz);
}
void geri() {
  motor(-hiz, -hiz);
}
void sol() {
  motor(-hiz, hiz);
}
void sag() {
  motor(hiz, -hiz);
}
void dur() {
  motor(0, 0);
}

void ileriSol() {
  motor(hiz / 2, hiz);
}
void ileriSag() {
  motor(hiz, hiz / 2);
}




52 Responses

  1. yardım lütfen
    l293 shild sürücü ve 6 sensör kullanarak kodları bir türlü uyarlayamadım yardımlarınızı bekliyorum

      • Aşağıdaki fonksiyonu kullanabilirsiniz.

        // BTS7960 (veya L298N) motor sürücü bağlantıları.
        #define solRPWM 6 // Sol motor.
        #define solLPWM 10 // Sol motor.
        #define sagRPWM 5 // Sağ motor.
        #define sagLPWM 9 // Sağ motor.

        void motor(int solMotorPWM, int sagMotorPWM) {
        if ( solMotorPWM >= 0 ) { // İleri.

        analogWrite(solRPWM, solMotorPWM);
        analogWrite(solLPWM, 0);
        }
        else { // Negatifse geri döndür.
        analogWrite(solRPWM, 0);
        analogWrite(solLPWM, abs(solMotorPWM));
        }

        if ( sagMotorPWM >= 0 ) { // İleri.
        analogWrite(sagRPWM, sagMotorPWM);
        analogWrite(sagLPWM, 0);
        }
        else { // Negatifse geri döndür.
        analogWrite(sagRPWM, 0);
        analogWrite(sagLPWM, abs(sagMotorPWM));
        }
        }

        void ileri() {
        motor(hiz, hiz);
        }
        void geri() {
        motor(-hiz, -hiz);
        }
        void sol() {
        motor(-hiz, hiz);
        }
        void sag() {
        motor(hiz, -hiz);
        }
        void dur() {
        motor(0, 0);
        }

        void ileriSol() {
        motor(hiz / 2, hiz);
        }
        void ileriSag() {
        motor(hiz, hiz / 2);
        }

  2. merhaba sayenizde çok şey öğrendim teşekkürler.
    Şimdi l293d shield kullanarak robot yaptım ancak bir türlü kodlarınız uyarlayamadım yardımcı olursanız çok sevinirim kolay gelsin

  3. Kapsamlı videonuzu haziran sonu gibi yayınlayacaktınız ne zaman yayınlayacaksınız kolay gelsin.

  4. Merhaba hocam size bir bilgi danışmak istiyorum, yaptığım bir projede hem sd kart modülü (wav uzantılı müzik çalacak) hem de servo motor kullanmam gerekiyor. Fakat ile kütüphaneleri çakışıyor, hata veriyor. VE kütüphaneleri ile de denedim istediğim yerlerde istediğim müzik çalmıyor. Yardımcı olursanız sevinirim.

  5. Öncelikle paylaşımınız çok güzel , çok yardımcı oldu, emeğinize sağlık. Söylediğiniz daha kapsamlı videonuzu ne zaman yayınlayacaksınız hayırlı geceler.

  6. Merhaba qtr 8 a sensör kullanıyoruz aurdino uno kullandığımızdan dolayı 6 tane analog çıkış kullanıyoruz tek tekeri dönüyor sadece bunu sebebi ne olabilir aceba?

    • Sensörden çok motor sürücü problemi gibi görünüyor. Kodu veya kablorı kotrol edin motor sürücüde.

  7. Ustam emeğine sağlık. Çok güzel bir paylaşım. AIN1-AIN2-BIN1-BIN2 pinlerini motor dönüş yönü için kullanıyorsun sanırım. Sadece AIN1 ve BIN1 kullanamazmıyız..

  8. Öncelikle iyi günler. Kodu yüklediğimde aşağıda belirttiğim kodu işaret edip “expected identifier before numeric constant” diye bir hata alıyorum. Bunu düzeltmek için ne yapmalıyım?
    } while((sensor([3])<200)||(sensor([4])<200));//çizgi dışında olduğun sürece dön

  9. hocam en kısa zamanda bir sumo calışmasıda bekliyorum.. harika anlatım.. allah razı olsun

    • stby 0 yapıldığında pololu tb6612fng motor sürücüsünü pasif bırakır. şuan kodda işlevi yok. kaldırılabilir.

        • Şöyleki bu devrede stby ucu kullanılmak için tasarlanmış. ama farklı bir tasarımda motor sürücünün STBy ucunu 5 volta verirsek yazılımda bunu kullanmak zorunda da kalmayız

  10. Merhabalar , verdiğiniz kod ile qtr8a ve 1000 rpm motor kullanarak bir çizgi izleyen robot geliştirdim . Ancak bu robot 90 derecelik dönüşleri alamıyor. hızını biraz düşürüp (bahsettiğim değer 45 civarında ) denediğimde ise yumuşak dönüşleri alıp 90 derece olanları zorlanarak bazen geçiyor bazen geçmiyor.
    Sizce sıkıntı nerededir ?
    Kp&Kd değerlerini değiştirmeyi denedim ancak sağlıklı sonuçlar alamadım , değerleri denerken nasıl bir yol izlemeliyim ?
    18*14cm bir robot için nasıl Kp&Kd değerleri atamalıyım ?

      • verdiğiniz bu linkteki de hata verdi.

        ” “kontrolBiti” wasnt declared in this scope”

          • tekrar denedim fakat kafasına göre hareket ediyor robot. neden kaynaklanabilir? kp-kd değerleriyle de oynadım ama pek değişmiyor gibi.

          • son verdiğinizi de denedim. önceki hiç çalışmıyordu ama bu daha iyi tabi ufak tefek değişiklikler yaparak. ben 6 sensör kullanıyorum. uno da 6 adet anolog çıkış var diğer 2 sini nasıl bağlayabilirim? bir de bu son denediğim kodda sanki ortadaki 2 sensör işlevsiz gibi devamlı sağ ya da sol motor çalışıyor tekler gibi gidiyor. devamlı sağa ya da sola ata ata gidiyor yani. normal yolunda hızlanıp gitmiyor hiç. çoğu yeriyle oynadım. bu 2 sorumu cevaplarsanız çok sevinirim.

          • Uno da 6 analog giris oldugundan 6 adet sensör kullanabilirsiniz. Sağa sola kafa atmasının titremesinin sebebi kp kd degerlerinin büyük gelmesidir. Kucultun.

          • merhabalar tekrar :)sizin kodlar üzerinde çalışıyorum ama tam olarak oturmadı sanki. son verdiğiniz kodlara göre birkaç sorum olacak.

            1- verdiğiniz kodlardaki en keskin dönüş 90 derece diye anlıyorum doğru mu acaba? Mesela Z tarzındaki dönüşlerde sıkıntı oluyor gibi? yoksa ben mi yanlış yapıyorum birşeyleri? 🙂

            2- daha önceden hiç bilmediğimiz(ölçülerini vs vs gibi) bi pistte sorunsuz çalışması için hızını ister istemez düşük tutmamız gerekir sanırım değil mi? başka nelere dikkat etmeli?

          • Z leri dönebilecek komut ile diğerini birleştirmemiz mi gerekiyor o zaman? yani hem normal hem 90 hem de z gibi dönüşler için. yani amacım hiç bilmeden koyduğum pisti sonuna kadar tamamlatmak. 🙂

            ayrıca hızlanma komutlarını da gönderirim demişsin yapisti bilmeden nerde hızlanıp yavaşlayacağımız biraz zor olur sanırım değil mi?

            Bu arada çok teşekkürler cevaplar için.

          • son gönderdiğim kod aslında tüm dönüşleri yapar. pisti bilinmeyen yerde hızlanmak için tek çare uzun mesafe renk sensörü.ancak garip açılı boşlukları olan pistlerde özel kod yazmadan geçmek imkansız tabii ki

  11. Merhaba, ben bu kodu L298N ile uyumlu olacak hale getirdim fakat kod çalışmadı. Sensör değer veriyor fakat motorlar çalışmıyor. Yardımcı olur musunuz? Kod bu:

    #include

    const int enA = 10; //L298N
    const int enB = 5;
    const int in1 = 9; //motor a (sol)
    const int in2 = 8; //motor a (sol)
    const int in3 = 7; //motor b (sağ)
    const int in4 = 6; //motor b (sağ)

    #define NUM_SENSORS 6
    #define TIMEOUT 4
    #define EMITTER_PIN 2

    #define LED 13
    #define MZ80 4

    int maxhiz = 70;

    boolean zemin = 0; //1 siyah 0 beyaz

    //PD’yi kullanmak için değişkenleri bildirme (her araca göre ayar yapılmalı)
    int hata = 0; float KP = 0.01; // hata (her araca göre ayar yapılmalı)
    int turev = 0; float KD = 0.1; // turev

    unsigned int pozisyon = 0;

    int fark = 0; // motorlara uygulanan fark
    int son_hata; // Orantılı son değer (hatanın türevini hesaplamak için kullanılır)
    int hedef = 3500;

    QTRSensorsAnalog qtra((unsigned char[]) {
    0, 1, 2, 3, 4, 5
    } , NUM_SENSORS, TIMEOUT, EMITTER_PIN);

    unsigned int sensor[NUM_SENSORS];

    void setup()
    {
    pinMode(in1 , OUTPUT);
    pinMode(in2 , OUTPUT);
    pinMode(enA , OUTPUT);
    pinMode(in3 , OUTPUT);
    pinMode(in4 , OUTPUT);
    pinMode(enB , OUTPUT);
    pinMode(LED , OUTPUT);
    pinMode(MZ80 , INPUT);

    // Dahili Led yanıp söndüğü sürece (3sn) Elle Kalibrasyon yap
    for ( int i = 0; i maxhiz ) fark = maxhiz;
    else if ( fark < -maxhiz ) fark = -maxhiz;

    ( fark = 0 )
    {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    }
    else
    {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    deger *= -1;
    }
    analogWrite(enA, deger);
    }

    void solmotor(int deger)
    {
    if ( deger >= 0 )
    {
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
    }
    else
    {
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
    deger *= -1;
    }
    analogWrite(enB, deger);
    }

    void motor(int sol, int sag)
    {
    solmotor(sol);
    sagmotor(sag);
    }

    • Herhangi bir değişiklik yapmadan l298n motor sürücü ile de kullanabilirsin kodu.

      Senin buraya yazdıgin kodda loop fonksiyonu ve pek çok şey eksik.

    • 6 sensör kullandın hedef 3500 olmaz 2500olur. ( Sensör sayısı-1)*1000 /2
      Her sensör beyazda 0 a yakın siyahta 1000e yakın değer verir

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Dersler