Bu yazıyı herkes okusun

Bu yazıyı herkes okusun - Perspektif
Klasman dışı - İçimizdeki Savaşlar

15 Mayıs 2015 Cuma

PID Control Line Follower Robot


Line Follower robot adından da anlaşılabileceği gibi bir zemin üzerinde oluşturulmuş çizgi şeklindeki yolu otonom (öz denetimli) olarak izleyen robotlardır. Bu amaçla kullanılabilecek sensörlerin kontrastı yani koyu ve açık renk ayrımı yapabilmesi nedeniyle siyah zemin üstünde beyaz çizgi yada beyaz zemin üzerinde siyah çizgi bulunan yollar bu robotlar için tercih edilir.





Çalışma Prensibi




Robotun çalışma prensibi, çizgiyi ortadaki algılayıcıda tutarak ilerlemesine dayanmaktadır. Robot kısa aralıklarla algılayıcının durumunu kontrol ederek çizgiye göre konumunu belirler. Bunun için tasarım fikrine bağlı olarak belli sayıda ve belli aralıklarla ve yerleşim şekli ile çizgi algılama sensörleri kullanılır ve motorlar buradan gelen bilgilere göre kontrol edilir.Robot ilerlerken, çizgi robotun sağ tarafına gelirse, 3 nolu algılayıcı çizgiyi görecektir. Böylece robot çizginin sol tarafında olduğunu anlayacak ve programı içinde belirtilen sağa dönüş komutunu uygulayacaktır.Dönme işlemi, ortadaki algılayıcının çizgiyi tekrar görmesine kadar devam eder. Bu algılayıcı çizgiyi gördüğünde, robot tekrar düz hareket etmeye başlar.

Eğer, çizgi robotun sol tarafına gelirse, aynı işlemler bu taraf için tekrarlanır ve böylelikle çizgi izleme işlemi yerine getirilir.

Motor ve Sürücü

Robotlarımızda genellikle 6-12V’ luk elektrik motoru(DC motor) kullanıyoruz. Hız gerektiren projelerde(çizgi izleyen robot) genelde yüksek devirli düşük torklu motor kullanılır, tork gerektiren projelerde(sumo robot, mini sumo robot gibi) ise düşük devirli yüksek torklu motor kullanılır. Bu motorlarda çekilen akım motorun boyutlarına ve özelliklerine göre değişir. Örnek verecek olursak bir motor boşta dönerken 30mA akım çeker, yükte ise bu 700mA çekebilir veya daha fazla. Örneğin sumo robotlarda kullanılan çoğu motor zorlanma anında 10 A kadar akım çekebilir. Motorları sürmek için çok akım gerekir, ancak biz motorları kontrol etmek için Arduino kullandığımız için, Arduino çıkışlarına maksimum 25mA ve 5V verebildiği için direkt Arduino çıkışıyla motor süremeyiz. İşte bu yüzden Arduino dan gelen düşük gerilim ve akımı kuvvetlendirmek için motor sürücü devreleri kullanıyoruz. Kullanım amacına göre tek yönde ve sabit hızda sürme devreleri olduğu gibi çift yönde ve değişken hızda motor sürmemizi sağlayan devre topolojileri de vardır.


Arduino ile motor sürmek için, Arduino dan gelen sinyali güçlendirip motorlara iletmemiz gerekir. Bunu yapmak için de transistör ve türevleri(FET-JFET-MOSFET) ve motor sürücü entegreleri kullanıyoruz. Eğer tek bir transistör kullanırsak, motoru sadece tek yönde çalıştırabiliyoruz. Motoru 2 yöne de döndürmek istersek, 4 adet transistörle yukarıdaki resimde gösterilen “H köprüsü” kurup motorları sürebiliriz. Motor sürücü entegrelerinin içinde genellikle 2 adet H köprüsü vardır ve böylece tek bir motor sürücü entegresiyle 2 adet motoru birbirinden bağımsız ve iki yönlü sürebiliriz.

Çalışma kapsamında L298N sürücüsünü kapsayan Zumo motor shield kullanacağız:




Bu entegre de toplam 15 adet bacak bulunmaktadır. Bunlardan IN1, IN2, OUT1, OUT2, ENA, SENSA A köprüsü için, IN3, IN4, OUT3, OUT4, ENB, SENSB B köprüsü içindir.

IN1,IN2(5,7): Bu bacaklar A köprüsü için olan girişlerdir. +5 volt ile çalışır.
Eğer IN1’e 5V, IN2’ye 0V verince motor ileri dönerse, tam tersini verdiğimizde geri dönecektir. Her iki bacağa da aynı değeri verirsek (0V-0V veya 5V-5V) motor dönmez.
IN3,IN4(10,12): Bu bacaklar B köprüsü için olan girişlerdir. A köprüsüyle aynı şekilde çalışır.
OUT1,OUT2(2,3):A köprüsü için çıkış bacaklarıdır. Bu çıkışları motorun iki ucuna bağlanacaktır. Motorların herhangi bir zorlanma durumunda oluşacak olan ters akımın entegreye zarar vermemesi için çıkışlar ile motor arasına ikişer adet diyot bağlanmalıdır. Bu diyotların birisinin yönü topraktan çıkışa doğru, diğeri de çıkıştan VS’ ye doğru olmalıdır.
OUT3,OUT4(13,14): B köprüsü için çıkış bacaklarıdır. A köprüsüyle aynı şekilde çalışır.
ENA,ENB(6,11): A ve B köprülerini etkinleştirmek için bu bacaklara +5 volt bağlamak gerekmektedir. Eğer bu uçlara mikrodenetleyiciden PWM sinyali verilirse motorun hızı kontrol edilebilir.
SENSA,SENSB(1,15): A ve B köprülerinin çalışması için bu bacaklar toprağa çekilmelidir. Bu bacaklarla toprak arasına bağlayacağımız 0,47 Ohm/2 W değerinde direnç ile çıkış akımını kontrol edebiliriz, fakat direnç bağlamadan da çalışır.
VS(4): Çıkışlardan kaç volt almak istiyorsak bu bacağı o voltaja bağlıyoruz. En fazla 46 volt verebiliriz, biz genelde 12 volt kullanıyoruz. Ayrıca DC üzerindeki küçük salınımları yok etmek için bu bacakla toprak arasına 100nF’ lık kondansatör bağlanmalıdır.
VSS(9): Bu bacak, L298’ in çalışması için +5 volta bağlanmalıdır. Yine küçük salınımları yok etmek için VSS ile toprak arasına 100nF’lık kondansatör bağlanmalıdır.

GND(8): Bu bacak, L298’ in çalışması için toprağa bağlanmalıdır.

Siz de ayrıca motor sürücü yapmak isterseniz yukarıdaki diagramı kullanarak yapabilirsiniz.

Robotta kullanılan mikro DC metal motorlar (tork ve rpm için farklı değerler kullanılabilir)




Motorlar için link

http://www.robotistan.com/751-Micro-Metal-Gearmotor-HP-with-Extended-Motor-Shaft-400-Rpm-Arkadan-Mil-Cikisi-6V-400-Rpm-Yuksek-Guclu-Mikro-Metal-Motor,PR-2726.html


Motor Shield ve şase için link

http://www.robotistan.com/Zumo-Arduino-Temelli-Paletli-Mini-Sumo-Robot-Kiti,PR-2050.html






Sensör




Çizgiyi algılamak için kızılötesi led ve optik olarak iletime geçen bir transistör barındıran sensörler kullanılmaktadır. Kızılötesi ledden yansıyan ışınlar siyah zeminden az beyaz zeminden çok yansıdığı için sensör içindeki elektronik anahtar(transistör) yansıyan bu ışına göre iletime veya kesime giderek bize çizgi hakkında bilgi vermektedir. Buradan gelen bilgi mikrodenetleyici ile değerlendirilerek motorların kontrolü sağlanmakta ve robot yönlendirilmektedir.
Bahsedilen amaçla kullanılan bazı sensörler şunlardır: QRD1114, CNY70, SFH9241, QTR-8A
Çizgi izleyen robotta kullanılan sensörler genellikle 3mm lik bir yükseklikten çizgiyi algılayabilmektedir. Robot mekaniği tasarlanırken bu konuya da dikkat edilmelidir. Buna ek olarak, kullanılacak sensör sayısı, sensörler arasındaki mesafe ve sensörlerin yerleşim şekli de robotun
tasarımında önemli konulardır. Çizgi kalınlığı 2cm olduğu için sensörler arasında genelde 2cm aralık bırakılır. Çok yakın şekilde yerleştirilmiş sensörlerin gönderdiği sinyaller birbirini etkileyecektir.

Robotta kullanılan kontrast sensor array




Sensörlerin Robot ile Entegrasyonu






Şaseyi sensörü ve motorları entegre etmek için gerekli link

https://www.pololu.com/docs/pdf/0J57/zumo_shield_for_arduino.pdf


Programlama

#include <QTRSensors.h>
#include <ZumoReflectanceSensorArray.h>
#include <ZumoMotors.h>
#include <Pushbutton.h>
ZumoReflectanceSensorArray reflectanceSensors;
ZumoMotors motors;
Pushbutton button(ZUMO_BUTTON);
int lastError = 0;
const int MAX_SPEED = 400;
void setup(){ reflectanceSensors.init();
Serial.begin(9600);
button.waitForButton();
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
delay(1000);
int i;
for(i = 0; i < 80; i++) 
 { if ((i > 10 && i <= 30) || (i > 50 && i <= 70)) 
 motors.setSpeeds(-200, 200);
 else motors.setSpeeds(200, -200);
 reflectanceSensors.calibrate(); 
 delay(20);
} 
 motors.setSpeeds(0,0);
 digitalWrite(13, LOW);
 button.waitForButton();}

void loop()
{ unsigned int sensors[6];
 int position = reflectanceSensors.readLine(sensors);
 int error = 2500 - position ;
 int speedDifference = error / 4 + 6 * (error - lastError);
 lastError = error;
 int m1Speed = MAX_SPEED + speedDifference;
 int m2Speed = MAX_SPEED - speedDifference;
 if (m1Speed < 0) m1Speed = 0;
 if (m2Speed < 0) m2Speed = 0; 
 if (m1Speed > MAX_SPEED) m1Speed = MAX_SPEED; 
 if (m2Speed > MAX_SPEED) m2Speed = MAX_SPEED; 
 /* int sensor_0=digitalRead(5 ); 
 int sensor_1=analogRead(A2); 
 int sensor_2=analogRead(A0); 
 int sensor_3=digitalRead(11); 
 int sensor_4=analogRead(A3); 
 int sensor_5=digitalRead(4); 
 Serial.print(sensor_0); 
 Serial.print(" "); 
 Serial.print(sensor_1); 
 Serial.print(" "); 
 Serial.print(sensor_2); 
 Serial.print(" "); 
 Serial.print(sensor_3); 
 Serial.print(" "); 
 Serial.print(sensor_4); 
 Serial.print(" "); 
 Serial.print(sensor_5); 
 Serial.print(" error= "); 
 Serial.print(error); 
 Serial.print(" position= "); 
 Serial.print(position); 
 Serial.print(" speedDifference= "); 
 Serial.print(speedDifference); 
 Serial.print(" sol_motor= "); 
 Serial.print(m1Speed); 
 Serial.print(" sag_motor= "); 
 Serial.println(m2Speed); */


 motors.setSpeeds(m1Speed, m2Speed);


}



Not: Gerekli kütüphaneleri arduino library kısmına atmayı unutmayın!

Anahtar Kelimeler

PID,  Control,  Arduino, LineFollower, Robot


3 Mayıs 2015 Pazar

Arduino - NRF24 ile Kablosuz Haberleşme


Bugünkü yazımda 2.4 GHz (2.400 – 2.4835GHz) frekansında yayın yapan NRF24 haberleşme modülünü inceleyeceğim. Son zamanlarda farklı sistemlerin birbiri ile haberleştirilmesi, karşılıklı veri aktarımı ve senkron çalışma üzerine birçok çalışma mevcut. Bu çalışmaların birçoğunda xbee modülleri kullanılırken ucuz haberleşme sistemleri de üretilmiştir. Bunlardan biri olan NRF24L01 2.4 GHz frekans bandında 1Mhz çözünürlükte 126 farklı kanaldan yayın yapar. Alıcı (receiver) ve verici (transmitter) olmak üzere 2 farklı modülden oluşan NRF24 ucuz olması açısından birçok çalışmada kullanılır. NRF24 radio modülü SPI (serial peripheral interface) kütüphanesi ile kullanılır ve veri iletimi seri haberleşme ile yapar. Haberleşme hızı saniyede 2 Mb’ tır (2Mbps).


NRF24 radio modülleri alıcı ve verici olarak kullanılabilir. Modüllerin hangisinin alıcı hangisinin verici olduğu mikroişlemciye yazılan kod ile ilgili. Burda yapmaya çalıştığımız ise 2 arduino kartı birbiri ile haberleştirilecek ve senkron şekilde ilgili pinlere bağlı ledler yakılıp söndürülecek.Gerisi artık sizin neleri haberleştireceğinize kalmış diyebilirim.


NRF24 modülü alıcı olarak kullanıldığı durumda veri aktarım hızı 2Mbps iken 12.3 mA , verici olarak kullanıldığında 11.3 mA akım çekmektedir. Multireceiver olarak kullanılabilir ve 6 farklı vericiden 6 farklı adres ile bir modül veri alışverişinde bulunabilir.




Adresler datasheete göre şöyle de gösterilmiştir:




Pin açıklamaları ( yani ben öyle bağladım )

NF24L01

ARDUINO UNO


Chip Enable- Modülün alıcı yada verici olarak kullanılmasını ayarladığımız pin.

CE (CS)

9


SPI chip select

CSN

10


SPI clock

SCK

13


SPI slave data input

MOSI

11


SPI slave data output

MISO

12


Besleme (+1.9V – 3.6V DC)

VCC

3.3V


Besleme ground

GND

GND 


Ve de kodlar;

Verici tarafın kaynak kodu:

///// verici kısımdan gönderşlen ledin yanıp yanmadığının bilgisi karşı tarafa iletilir

#include <SPI.h> // kütüphaneler eklendi

#include <RF24.h>

#define LED 5 // 5. pine led bağlanmıştır

#define RF_CS 9 // RF24 üzerindeki CS pininin (bazı modellerde CE diye yazılmaktadır) arduino ya takıldığı pin numarası verilmiştir

#define RF_CSN 10 // RF24 üzerindeki CSN pininin arduino ya takıldığı pin numarası verilmiştir

RF24 radio(RF_CS, RF_CSN); // RF24 türünde radio isimli değişken tanımlandı

const uint64_t pipes[2] = { 0xe7e7e7e7e7LL, 0xc2c2c2c2c2LL }; // paralel veri yolu adresleri

boolean durum =false;

void setup() {

Serial.begin(9600); // seri haberleşme hızı

pinMode(LED, OUTPUT);

radio.begin(); // rf24 haberleşmesi başlatıldı

radio.openWritingPipe(pipes[0]); // modülün verici olarak kullanılması için gerekli olan data yolu adresini haberleşmeye açar. Yani 0xe7e7e7e7e7LL adresi veriyi gönderen kısım.

//Bunu karşı taraf 0xc2c2c2c2c2LL adresi ile alır

radio.openReadingPipe(1, pipes[1]); // modülün alıcı olarak kullanılması için gerekli olan data yolu adresini haberleşmeye açar. Yani 0xc2c2c2c2c2LL adresi veriyi alan kısım.

//Yani veri karşıdaki 0xe7e7e7e7e7LL adresinden alınır

radio.startListening(); // radio modüllerinden veri gelinip gelinmediğini kontrol eetmektedir.

radio.printDetails();

}


void loop() {

unsigned long time = millis(); // programın çalışma süresinin tutulduğu değişken

// belli bir sürede modüllerin birbiri ile haberleşmediği durumlarda uyarı vermesi için kullanılacaktır

uint8_t on[1],off[1];

on[0]=1;

off[0]=0;

radio.stopListening();

if(!durum)

{

digitalWrite(LED,HIGH); // led yandığında karşı tarafın ledi sonecek

radio.write( &on,sizeof(on));

durum= true;

}

else

{

digitalWrite(LED,LOW);

radio.write( &off,sizeof(off));

durum=false;

}

radio.startListening();

delay(1000);

}

Alıcı tarafın kaynak kodu:

/// verici tarafından gelen data bilgisi alıcı tarafından alındığında;verici tarafındaki led durumuna göre yandığında kapatılacak söndüğünde açılacak

#include <SPI.h>

#include <RF24.h>

#define led 3

#define RF_CS 9

#define RF_CSN 10

RF24 radio(RF_CS, RF_CSN);

const uint64_t pipes[2] = { 0xe7e7e7e7e7LL, 0xc2c2c2c2c2LL }; // paralel veri yolu adresleri

bool done = false;

void setup() {

Serial.begin(9600);

pinMode(led, OUTPUT);

radio.begin();

radio.openWritingPipe(pipes[1]);

radio.openReadingPipe(1, pipes[0]);

radio.startListening();

radio.printDetails();

}

void loop() {

if (radio.available()) {

char rx_data[1]; // gelen verinin dizi sayısı 1. Çünkü ya 0 gelecek yada 1 gelecek

radio.read( &rx_data, 1 );

if(rx_data[0]==1)

{

Serial.print("Sonsun: ");

Serial.println(rx_data[0]);

digitalWrite(led,LOW);

}

if(rx_data[0]==0)

{

digitalWrite(led,HIGH);
Serial.print("Yansin: ");
}

}

}