Robotlar dersi final projesi raporu.
Hazırlayan: Şadi Evren ŞEKER
Dersin Hocası: Coşkun Sönmez
Amaç:
Işık takibi yapan bir robot gerçeklemesi.
Bu projedeki amaç, ortamdaki ışığın yoğun olduğu alana doğru yönelen bir robotun gerçeklemesidir. Robot, ortamdaki ışık değerlerini inceleyip, ışığın yoğun olduğu yöne doğru yönelecektir.
Malzeme seçimi ve tasarımı
Eylemler:
Işık miktarının ölçülmesi
karar verilmesi
Dönme eylemi
Işık miktarının ölçülmesi için LDR (Light dependent resistor) kullanılmıştır. Ölçümler sonucunda bu direncin kullanılması için 22k lık bir direnç ile aşağıdaki şekilde bağlanmasına karar verilmiştir:
yukarıdaki şekilden de anlaşılacağı üzere LDR üzerindeki direnç verisi V gerilim farkı değerinin okunduğu değeri direk olarak etkilemektedir. Bu değeri İşlmecinin desteklediği ADC (analog to digital conventor) ‘a bağlayarak analog olarak okunan gerilim farkının dijital veriye çevrilmesi ve nihayetinde işlemcinin işlemesine imkan vermesi sağlanır.
İşlemci TolaLtd tarafından üretilen kit sayesinde kontrol edilmekte ve programlanabilmektedir. İşlemci ile adım motoru ve LDR devreleri arasındaki bağlantıyı kuran kit de yine bu kittir. PortA çıkışı adım motor kontrolü için, portB kontrolü ise LDR dirençlerinden değer okumak için ayrılmıştır.
işlemci üzerinde belirtilen şemada :
adc çıkışları olan PA1 kullanılmıştır.
Hareket emrinin verilmesi ve step motor kontrolü:
yukarıdaki şekilde gösterildiği üzere, board üzerinde bulunan portb bağlantısından alınan hat sayesinde, ve ULN2003A entegresi üzerinden adım motorun içerisindeki bobinlere çıkış sağlanmaktadır.
Bu uygulamada 4 bobinli ve 5 çıkışlı adım motor seçilmiştir. Adım motorun ortadaki değeri için 12V besleme girilmiş, diğer girişler (bobin girişleri) entegreden alınan ve dolayısıyla işlemciden gelen dijital sinyale göre beseleme almaktadırlar.
İşlemcinin kodlanması:
İşlemci kodunun tamamı eklerde verilmiştir ancak önemli olan ve kodun ana kısmını oluşturan döngü aşağıda detaylıca anlatılmıştır:
while (1) // kısır döngü
{
if (bay_motorzaman)
{
bay_motorzaman=0;
i=adc_data[0]-adc_data[1];
if (abs(i)>30) // ışık şiddetleri farkı 50 birimden fazla mı?
{
if (i>0) // sağda daha fazla ışık varsa
{
sagadon();
}
else
{
soladon(); // solda daha fazla ışık varsa
}
}
}
};
yukarıdaki döngü ana döngü olup sonsuza kadar dönemektedir. Her 1 ms da bir kaldırılan bay_motorzaman bayrağı kontrol edilmiş olup daha sonraki kaldırmalara imkan sağlamak için 0 yapılarak indirilir.
İki adet giriş değeri olarak kullanılan LDR’lerden gelen adc değerleri adc_data[0] ve adc_data[1] farkı alınarak, daha önceden belirlenmiş olan trash hold (eşik değer) ile karşılaştırılmaktadır.
Eşik değer bu uygulamadan 30 olarak alınmıştır ancak sistemin iyileştirilmesi için bu değer değiştirilebilir.
Sağ ve sol adc değerleri işlendikten sonra adc_data[0] yani sağdaki LDR değerinin büyük olması durumunda sağa dönme eylemi (fonksiyonu), adc_data[1] yani soldaki LDR değerinin büyük olması durumunda ise sola dönme eylemi icra edilmektedir.
Bu fonskiyonların detaylarında:
void sagadon (void)
{
bobinler>>=1;
if (bobinler&1)
{
bobinler|=0b00010000;
bobinler&=0b11111110;
}
PORTB=bobinler;
}
void soladon (void)
{
bobinler<<=1;
if (bobinler & 0b00100000)
{
bobinler|=0b00000010;
bobinler&=0b11011111;
}
PORTB=bobinler;
}
yukarıda görüldüğü üzere, bobinler değişkeninin üzerinde shift (kaydırma) işlemi uygulanmakta ve bu sayede motor dönme eylemi gerçekleştirilmektedir. Ancak dönme eylemi 4 bit (4 bobin) ile sınırlı olduğu için taşma durumlarının kontrol edilmesi gerekmektedir. Hemen altta bulunan if koşulları bu durum için düşünülmüştür. Buna göre sağa dönem eyleminde en sağ bitin 1 olma durumunda, en sağ bit 0 yapılıp 4 bitlik grubun en sol biti 1 yapılır.
Benzer şekilde sola dönme eyleminde de sol bitin taşması ihtimali kontrol edilip, 4 bitlik grubun en sağ biti 1 yapılmaktadır.
EK1 İşlemci Kodu:
/*****************************************************
tolAVR ile Işığa Dönen Step Motor
işlemci : ATmega16
saat frekansı : 16.0000 MHz
*****************************************************/
#include <mega16.h>
#include <math.h>
#include <stdio.h>
void sagadon (void);
void soladon (void);
unsigned int say1=0,sayac1son=20; // ms cinsinden sayaç
unsigned char bay_motorzaman=0;
// Timer 1 taşma kesmesi servis döngüsü
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
// Timer 1 değerini tekrar yükle
TCNT1H=0xFF; // 1ms
TCNT1L=0x05;
if (say1<sayac1son) say1++;
else
{
say1=0;
bay_motorzaman=1;
}
}
int adc_data[2];
#define ADC_VREF_TYPE 0x40
// ADC kesme servis döngüsü
// 2 giriş sırayla taranır, diziye yerleştirilir
interrupt [ADC_INT] void adc_isr(void)
{
register static unsigned char input_index=0;
// AD Dönüşüm sonucunu oku (10-bit)
adc_data[input_index]=ADCW;
// Sonraki ADC girişini seç
if (++input_index > 1)
input_index=0;
ADMUX=(ADC_VREF_TYPE & 0xff) + input_index ;
// AD Çevrim başlat (OR ile 1 yapar)
ADCSRA|=0x40;
}
char bobinler=0b00001100;
void main(void)
{
int i;
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0xFF;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;
// Timer/Counter 1 şartlama
// Saat Kaynağı: Sistem Saati
// Saat Değeri: 250,000 kHz
// Kip: Normal tepe=FFFFh
// Giriş yakalama inen Kenarda
// Timer 1 Taşma Kesmesi: Açık
TCCR1A=0x00;
TCCR1B=0x03;
TCNT1H=0xFF;
TCNT1L=0x05;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
MCUCR=0x00;
MCUCSR=0x00;
TIMSK=0x04;
// ADC şartlama :
// ADC Saat Frekansı: 125,000 kHz
// ADC Gerilim Referansı: AREF pini
// ADC Otomatik tetikleme kaynağı : yok
ADMUX= (ADC_VREF_TYPE & 0xff);
ADCSRA=0xCF;
#asm("sei")
PORTB=bobinler;
while (1) // kısır döngü
{
if (bay_motorzaman)
{
bay_motorzaman=0;
i=adc_data[0]-adc_data[1];
if (abs(i)>30) // ışık şiddetleri farkı 50 birimden fazla mı?
{
if (i>0) // sağda daha fazla ışık varsa
{
sagadon();
}
else
{
soladon(); // solda daha fazla ışık varsa
}
}
}
};
}
void sagadon (void)
{
bobinler>>=1;
if (bobinler&1)
{
bobinler|=0b00010000;
bobinler&=0b11111110;
}
PORTB=bobinler;
}
void soladon (void)
{
bobinler<<=1;
if (bobinler & 0b00100000)
{
bobinler|=0b00000010;
bobinler&=0b11011111;
}
PORTB=bobinler;
}