Yukarıdaki resimde analog pot gözükmektedir. Yapısında iki adet pot bulunmaktadır. Bunlar ile hem x-ekseni hem de y-ekseninden bir gerilim alınarak ADC yardımıyla mikrodenetleyicimize iletilir. Alınan bu değerler işlenerek hangi eksende ne kadar derecelik hareket varsa servolarımıza iletilir ve servolar harekete geçirilir.
Devre şeması |
MikroC kodu;
#include "built_in.h" // hi(), lo(), komutlarını kullanmak için
# define servo1 PORTB.RB4 // servo motor çıkışı ayarlanır. PORTD.RD0
# define servo2 PORTB.RB5 // servo motor çıkışı ayarlanır. PORTD.RD1
char secilen_motor = 1, secilen_hiz = 1, secilen_poz = 0;
unsigned poz;
const int rc_poz_limit = 12500; // PWM maksimum limit = 2.5 ms x 8 = 20 ms
const int rc_poz_min = 2400; // PWM minimum limit = 1.5 ms
unsigned servo_pwm[2]={rc_poz_min,rc_poz_min};
unsigned short servo_say = 0;
bit servo1_on;
bit servo2_on;
bit bayrak;
unsigned rc_poz_interrupt = 53035; // TMR1 için ön değer
unsigned int adc_deg[2]; // ADC'den alınan verilerimi tutar.
void interrupt(){
if (pir1.tmr1if){ // tmr1 kesmesi oluştu
if (!bayrak){
if (servo_say == 0 && servo1_on) servo1 = 1;
if (servo_say == 1 && servo2_on) servo2 = 1;
rc_poz_interrupt = 65535 - servo_pwm[servo_say];
tmr1h = hi(rc_poz_interrupt);
tmr1l = lo(rc_poz_interrupt);
}
if (bayrak) {
if (servo_say == 0 && servo1_on) servo1 = 0;
if (servo_say == 1 && servo2_on) servo2 = 0;
rc_poz_interrupt = 65535 - rc_poz_limit + servo_pwm[servo_say];
tmr1h = hi(rc_poz_interrupt);
tmr1l = lo(rc_poz_interrupt);
if (++servo_say > 7) servo_say = 0;
}
bayrak = !bayrak;
pir1.TMR1IF = 0;
}
}
void init(){
TRISB=0X00;
PORTB=0X00;
delay_ms(300);
/*TIMER1 DONANIM BIRIMI KULLANILIYOR CUNKU SERVO MOTORUN NE KADAR SURE 1 KALCAK VE NE KADAR SURE 0 KALACAĞINI HESAPLAMAK ICIN BU DONANIM BIRIMINE IHTIYAC VARDIR*/
TMR1H = hi(rc_poz_interrupt); // TMR1 için ön değer yüklendi
TMR1L = lo(rc_poz_interrupt);
PIE1.TMR1IE = 1; // TMR1 kesmesi aktif edildi
T1CON.TMR1ON = 1; // TMR1 zamanlayıcısı çalıştırıldı
RCON.IPEN = 0; // Çevresel kesme maskelemeleri iptal edildi
INTCON.GIE = 1; // Kesmeler aktif edildi
INTCON.PEIE = 1;
/*ADC AYARLARI ICIN*/
TRISA.RA0=1;
TRISA.RA1=1;
ADCON0=0x09;
ADCON1=0b00001101; // Use Internal Voltage Reference (Vdd and Vss)
CMCON|=7;
bayrak = 0;
servo1_on = 1;
servo2_on = 1;
servo1 = 0; // bütün servoların ctrl pinlerine
servo2 = 0;
servo_pwm[0] = 2400; // bütün servoların başlangıç pozisyonları
servo_pwm[1] = 2400;
}
void servo_poz(unsigned secilen_motor, unsigned poz, unsigned short hiz){
unsigned short i;
while(servo_pwm[secilen_motor] < poz){
servo_pwm[secilen_motor]++;
for(i = 0; i < hiz; i++) delay_us(100);
}
while(servo_pwm[secilen_motor] > poz){
servo_pwm[secilen_motor]--;
for(i = 0; i < hiz; i++) delay_us(100);
}
}
void main() { // ana program
init(); // init() altprogramı çalıştırılıyor
delay_ms(500);
while(1){ // sonsuz döngü
secilen_motor=0;
while(secilen_motor<2){
adc_deg[0]=ADC_READ(0);
adc_deg[1]=ADC_READ(1);
delay_ms(100);
poz=(55,56*((adc_deg[secilen_motor]*45)/255))+2400;
servo_poz(secilen_motor, poz, secilen_hiz);
secilen_motor++;
}
}
}
SONUÇ
Hiç yorum yok:
Yorum Gönder