Arduino’da kendimi geliştirmek istiyorum. Bunun için de kod analizi üzerinde kafa yormaya karar verdim. Bunu da rastgele yapmak yerine, öncelikle bana lazım olan projeler üzerinden yapmak daha mantıklı geliyor. Sıfırdan açıklama beklentisi olan arkadaşlara önerim, ledin yanıp sönmesinden başlasınlar. Maalesef vakit sıkıntısından dolayı benim hızlı olmam gerekiyor.

Konuyu tamamlamak beklediğimden uzun sürecek. Bu yüzden birkaç güne yaymam gerekebilir.

 

Servo motor ile çizgi izleyen yapımı kodu:

/*
Easy Line Follower Robot -DIYhacking.com Arvind Sanjeev

Quick and easy line following robot using an IR reflectance
array.Connect Vcc and Gnd to the Pololu QTR-8A sensor from 
the arduino. Connect the pins 1,2,3,... to arduino's analog
pins 0,1,2,3,4,5.
If the average of the 3 values of the sensors on the left is
greater than the average of those on the right, then the robot
moves left and vice versa.
NOTE : The values in the code for analog voltages would have 
to be modified if you are not using the Pololu QTR-8A reflectance
array sensor. Use trial and error to find out max and min 
values for your own IR array sensor.
 
 */
#include <Servo.h> 

Servo left;
Servo right; 

int mid = 0;
int mn = 0;
int mx = 0;

void setup()
{

left.attach(9, 800, 2200); //left servo motor
right.attach(10, 800, 2200); //right servo motor

Serial.begin(115200);

digitalWrite(13, LOW);

right.write(90);//stop signal
left.write(90);//stop signal

for(int i=0; i<5000; i++)
{
digitalWrite(13, HIGH);

int val = 0;
for(int j=0; j<=5; j++)//Calibrating the sensor, finding max and 
{                      //min reflectance values.
val = analogRead(j);
if(val >= mx)
mx = val;
if(val <= mn)
mn = val;
}
delay(1);
}

mid = ((mx + mn)/2);
digitalWrite(13, LOW);

right.write(90);
left.write(90);
}

void loop()
{

int s0 = 0;
int s1 = 0;
int s2 = 0;
int s3 = 0;
int s4 = 0;
int s5 = 0;

s0 = analogRead(0);//Signal pin 1 on the board
s1 = analogRead(1);//Signal pin 2 on the board
s2 = analogRead(2);//Signal pin 3 on the board
s3 = analogRead(3);//Signal pin 4 on the board
s4 = analogRead(4);//Signal pin 5 on the board
s5 = analogRead(5);//Signal pin 6 on the board

Serial.print("Mid: ");
Serial.print(mid); 
Serial.print(" ");
Serial.print(s0); 
Serial.print(" ");
Serial.print(s1); 
Serial.print(" ");
Serial.print(s2); 
Serial.print(" ");
Serial.print(s3); 
Serial.print(" ");
Serial.print(s4); 
Serial.print(" ");
Serial.print(s5); 
Serial.print(" ");
Serial.println();

right.write(180);//Move forward
left.write(0);//Move forward

delay(1);

if((((s0+s1+s2)/3)>(((s3+s4+s5)/3)+240)))//Move right
{
right.write(130);//180
left.write(90);//90
Serial.print(" RIGHT");
delay(abs((((s5+s4+s3)/3)-((s0+s1+s2)/3))/2));
}

if((((s0+s1+s2)/3)<(((s3+s4+s5)/3)-240)))//Move left
{
right.write(40);//90
left.write(0);//0
Serial.print(" LEFT");
delay(abs((((s5+s4+s3)/3)-((s0+s1+s2)/3))/2));
}

if((s0 > mid)&&(s5 > mid))//Stop if all the sensors give low 
{                         //reflectance values
right.write(90);
left.write(90);
Serial.print(" STOP");

for(int k=0; k<50; k++)
{
digitalWrite(13  , HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);
}
delay(5000);
}


}

Yukarıdaki kodu şuradan aldım: https://maker.pro/projects/arduino/make-line-follower-robot

Bu siteden diğer tüm kaynaklara ulaşabilmeniz mümkün. Gelelim kod analizine;

Çizgi İzleyen Kodu Analizi

#include <Servo.h>

Servo.h kütüphanesini kullanacağız. Bu kütüphaneyi neden kullandığımızı anlamak için kütüphaneyi incelemek lazım. Öncelikle google’da aratarak bu kütüphaneyi bulalım;

İşte şurada: https://github.com/esp8266/Arduino/blob/master/libraries/Servo/src/Servo.h

Kütüphane bize şu kolaylıkları sağlıyor:

//  Servo - Class for manipulating servo motors connected to Arduino pins
//  attach(pin )  - Servo motoru Arduino'nun herhangi bir pinine i/o eklemek için
//   attach(pin, min, max  ) - Mikrosaniye olarak pinleri min ve max eklemek için
//   default min is 544, max is 2400
//
//   write()     - Servo açısını derece olarak ayarlamak için (invalid angle that is valid as pulse in microseconds is treated as microseconds)
//   writeMicroseconds() - Servo puls genişliğini mikrosaniye cinsinden ayarlama
//   read()      - Gets the last written servo pulse width as an angle between 0 and 180.
//   readMicroseconds()   - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
//   attached()  - Returns true if there is a servo attached.
//   detach()    - Stops an attached servos from pulsing its i/o pin.

devam edelim;

Servo left;
Servo right;

Arduino’da sınıf tanımlanması yapılmış. (class) . Bu sınıfa uygun left ve right (sol ve sağ) diye 2 nesne oluşturulmuş. (sol servo ve sağ servo)

int mid = 0;
int mn = 0;
int mx = 0;

Yukarıda mid(orta), mn (minimum) ve mx(maksimum) anlamında 3 değişken tanımlanmış. Başlangıç için bunlara sıfır değeri atanmış.

void setup()
{

 void setup bir fonksiyondur ve yeni Arduino IDE lerinde siz yazmadan yeni sayafada karşınıza gelir. bu fonksiyon karta elektrik verdiğimizde sadece bir sefer çaılışır ve sırasını loop fonksiyonuna bırakır. Eğer reset butonuna basarsak yani gücü kesip geri verirsek tekrar çalışır. Sadece bir defa çalıştığı için adından da anlaşıldığı üzere kartın kurulum bilgilerini barındırır. Genelde seri bağlantı başlatılması, pinlerin nasıl çalışacağının belirlenmesi gibi sadece başta ve  bir defa yapılması gereken işlemler burada belirtilir. pinlere isim takma yada değişken belirleme işleri ise bu fonksiyon çalışmadan yapılır.”

left.attach(9, 800, 2200); //left servo motor
right.attach(10, 800, 2200); //right servo motor

Servo kütüphanesinde attach kullanımı şu şekildeydi:

attach(pin, min, max  ) - Mikrosaniye olarak pinleri min ve max eklemek için

left nesnesi 9 nolu pine bağlı, 800-2200 mikro saniye min,max değeri olarak verilmiş. Right ise 10. pine bağlı.  (sol taraftaki servonun bilgi ucu ve sağ taraftaki servonun bilgi ucundan bahsediyorum.)

left.attach(9);

Şeklinde de yazabilirdik. Bu sefer de min,max değerleri için default değerler geçerli olacaktı.

Serial.begin(115200);

Serial monitöre yazı yazdıracağız anlamına geliyor. Seri iletişimi 115200 baudrate ile başlat demek.

digitalWrite(13, LOW); //Arduino üzerindeki ledi söndürmekle işe başlamış. 

right.write(90);//stop signal  // sağ servoyu 90 dereceye getirmiş
left.write(90);//stop signal  Sol servo da 90 derece

devam ediyoruz:

for(int i=0; i<5000; i++)  // i tanımla. Bunu sıfır yap. 0'dan 500'e kadar alttaki parantezi tekrarla
{
digitalWrite(13, HIGH); // ledi yak
int val = 0;   // val değerini sıfıra ayarla
for(int j=0; j<=5; j++)//  j yi tanımla. Sıfıra ayarla. 6 kez aşağıdakini yap. 
{                  
val = analogRead(j);  // j değerini oku ve val değişkenine ata
if(val >= mx)      // val , max. değerden büyük veya eşitse 
mx = val;     // val değerini max. değere ata
if(val <= mn)    // min. değerden küçük veya eşitse
mn = val;   // val değerini min. değere ata
}
delay(1);  // 1 milisaniye bekle
}

Yukarıdaki kodda QTR sensörünün kalibrasyonunu yapmış. J aslında QTR ‘deki IR alıcı-verici sayısı. (6 tane). Bunu analogread yaptığına göre QTR 8A kullanmış. Sizde QTR 8C varsa siz digitalRead kullanmalısınız.

mid = ((mx + mn)/2);  //Orta seviyeyi bu şekilde hesaplatma yoluna gitmiş
digitalWrite(13, LOW);   // 13. ledi söndirmüş. Demek ki kalibrasyonun bittiğini böyle anlıyoruz.

right.write(90);  // tekrar seevoları 90 dereceye getirmiş. 
left.write(90);
}

Artık tanımlama ve giriş kısmı bitti. Döngülere geçelim:

void loop()
{
int s0 = 0;  // s0 sensör değişkenini tanımlamış ve bunu sıfıra eşitlemiş.
int s1 = 0;
int s2 = 0;
int s3 = 0;
int s4 = 0;
int s5 = 0;

s0 = analogRead(0);//Signal pin 1 on the board  // Sıfırı analog olarak oku s0'a ata.
s1 = analogRead(1);//Signal pin 2 on the board
s2 = analogRead(2);//Signal pin 3 on the board
s3 = analogRead(3);//Signal pin 4 on the board
s4 = analogRead(4);//Signal pin 5 on the board
s5 = analogRead(5);//Signal pin 6 on the board

Burada neden (0) gibi ifadeler kullandığını anlamadım.

Serial.print("Mid: ");  // Serial monitöre Mid: yaz. Karşısına mid değerini ekle. Boşluk bırak. 
Serial.print(mid); 
Serial.print(" ");
Serial.print(s0);  //s0 değerini ekle boşluk bırak
Serial.print(" ");
Serial.print(s1); 
Serial.print(" ");
Serial.print(s2); 
Serial.print(" ");
Serial.print(s3); 
Serial.print(" ");
Serial.print(s4); 
Serial.print(" ");
Serial.print(s5); 
Serial.print(" ");
Serial.println();

Yukarıdakinin çıktısı şöyle birşey olacak:

Mid: 300 120 340

right.write(180);//Move forward
left.write(0);//Move forward

delay(1);

Yukarıdaki kodda öncelikle çizgi izleyenin ileri gitmesi sağlanmış. Çünkü bir çizgi izleyen için ileri gitmek esastır. Sonrasında 1 msn’lik kısa bir gecikme konulmuş ve sonraki satırlarda da sensörlerden alınan değerler hesaplanara, if yapısı ile birlikte sola veya sağa dönmesi sağlanacak.

if((((s0+s1+s2)/3)>(((s3+s4+s5)/3)+240)))//Move right
{
right.write(130);//180
left.write(90);//90
Serial.print(" RIGHT");
delay(abs((((s5+s4+s3)/3)-((s0+s1+s2)/3))/2));
}

if((((s0+s1+s2)/3)<(((s3+s4+s5)/3)-240)))//Move left
{
right.write(40);//90
left.write(0);//0
Serial.print(" LEFT");
delay(abs((((s5+s4+s3)/3)-((s0+s1+s2)/3))/2));
}

if((s0 > mid)&&(s5 > mid))//Stop if all the sensors give low 
{                         //reflectance values
right.write(90);
left.write(90);
Serial.print(" STOP");

Yukarıdaki kodlarda if dallanması içinde, sağa dönmesi için gereken koşullar verilmiş. Ardından da sola dönmesi için gereken koşullar verilmiş. En sondaki if dallanması içinde de, hiçbir sensör çizgiyi algılamazsa robotun durması amaçlanmış.

Açıkçası çizgi izleyen robot yapımında servo motor kullanmak hiç iyi bir fikir değil.  Aracın yönlenmesini önden servolarla yapmak yerine, arka tekerleklerin diferansiyel sistemle kumanda edilmesi çok daha kullanışlı.

if((s0 > mid)&&(s5 > mid))//Stop if all the sensors give low 
{                         //reflectance values
right.write(90);
left.write(90);
Serial.print(" STOP");

for(int k=0; k<50; k++)
{
digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);
}
delay(5000);
}

 

Buraya bir gecikme koymuş. 10 sn kadar. Sonrasında tekrar kod void loop’dan başlayacak. Sanırım araç çizgiden çıktıktan sonra, kişi tarafından tekrar yola konulması için 10 sn zaman tanınmış. Bunu neden sadece delay(10000) diyerek yapmamış acaba?

Buraya kadar.

Not: Bu analizi yapmamdaki amaç kod yazma mantığını bu şekilde daha iyi kavrayacağımı düşünmem. Yoksa bu konuda uzman olduğum gibi bir izlenim oluşturmak istemiyorum. Yanlış olduğunu düşündüğünüz yerler varsa, yorum kısmından bilgilendirme yaparsanız memnun olurum.

CEVAP VER

Lütfen yorumunuzu giriniz!
Lütfen isminizi buraya giriniz