Şimdiye kadar
yapmış olduğum çalışmalar aslın da hepsi bu yapacağım proje içindi. Fakat bu
projeyi yapmadan evvel ben merdivenleri tek tek çıkmayı tercih ettim. Bu
projeye başlamadan önce bu RPM nasıl hesaplanır diye düşünüyordum sonra yararlı
bir web site bulduktan sonra ben bunu yaparım dedim çünkü her şeyi tam anlayacağım
şekilde anlatılmış ama hemen bu RPM hesap yapmak yerine önce nasıl motor
sürülür, sonra ben bunu nasıl bir
mikrodenetleyici ile sürerim sonra nasıl RPM hesaplanıra geldim. Ve bu
çalışmamdan sonra nasıl olurda ben bu motor kontrol devresini bilgisayar ile
bağlantı kurarımın cevabı arayacağım. Ve
ondan sonra bir oyuncak araba yapıp nasıl GYRO ve ACCELEROMETER ile bunu
sürerimin cevabını arayacağım.
Bu çalışmamda
daha önceki çalışmalarım da yapmış olduğum yani
Fototransistör
ve Ir ledli uygulama, Pot
ile Motor kontrol , 18F4550
kullanarak motor kontrol bunlara ek olarak bazı ilaveler ekleyerek bir proje
hazırlayacağım. Bu proje süreceğim motorun ADC ile hızını ayarlayarak RPM yani
dakikadaki devir değerini ölçeceğim. Yine kullanacağım modüller 18f4550 içinde var
olan ADC , tek çıkışlı PWM ve ek olarak
daha önce kullanmadığım TMR0 dır. Sonra RPM değerini LCD ekranına yazacağım.
ADC modülünü motor hızını ayarlamak için kullanıyorum.
TMR0 modülünü ise Fototransistör
ve Ir ledli uygulama dan gelecek olan sinyal INT0 yani picin RB0 pinine gelecek ve
geldiğinde bize RPM(Rotation per Minute) hesaplatacak süreyi
belirleyecektir.
RPM HESAPALAMA
Bizim motorumuzun üstünde bir referans koyarak yani beyaz
şeridi sonra bunu bakacak olan sensörümüzü yerleştirerek biz TMR0 modülü ve Fototransistör
ve Ir led sayesinde motor bir tur attığındaki saniyeyi ölçeriz. Ve
saniye bizim T olur.
Frequency = 1/T Hz ve bu denklemden bize frekansı verir sonra
RPM
(Rotation per Minute) = Frequency x 60 frekansı bu denkleme koyarsak bize RPM
değerini verir.
Irled ve Fototransistöründen oluşan sensörü konumlandırma aşağıdaki gibi olmalıdır.
Motor üzerindeki siyah olan şey tekerlektir. Tekerlek tamamen siyah olup sadece bir kısmında düz bir beyaz olmalı ki ırleden çıkan sinyal beyaz çarpıp fototransistörün beyz ucuna bir tetikleme sinyali gitsin. Bu durum siyah olan kısım için geçerli değildir.
Devre Şeması |
RPM ölçmek için kullanılacak olan Irledli ve fototransistörlü devre şeması |
sbit LCD_RS at RC0_bit;
sbit LCD_EN at RC1_bit;
sbit LCD_D7 at RD3_bit;
sbit LCD_D6 at RD2_bit;
sbit LCD_D5 at RD1_bit;
sbit LCD_D4 at RD0_bit;
sbit LCD_RS_Direction at TRISC0_bit;
sbit LCD_EN_Direction at TRISC1_bit;
sbit LCD_D7_Direction at TRISD3_bit;
sbit LCD_D6_Direction at TRISD2_bit;
sbit LCD_D5_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD0_bit;
unsigned int adc_deg;
unsigned int duty_cycle;
char kelime[4]={0,0,0,0};
char kelime1[7]={0,0,0,0,0,0,0};
unsigned char i;
char txt1[] = "MUH HAKAN AYDIN";
char txt2[] = "RPM UYGULAMASI";
volatile unsigned int rpm_deger=0;
static unsigned char darbe_durumu=0;
unsigned int rpm_zaman_sayici;
if(INTCON.TMR0IF){
rpm_deger=0;
INTCON.TMR0IF=0; // Clear TIMER0 interrupt flag
}
/*Eger sensörden beyaz işaretden yansımayı alınca fototransistör anlık 1 olur olur ve INTCON.INT0IF=1 olarak
ilk önce zamanlayıcı sıfırlanır sonra tekrar 1 oluncaya kadaar geçen süreyi TMR0 sayar ve tekra INTCON.INT0IF=1 olunca ,
RPM hesaplamaya geçer*/
if (INTCON.INT0IF){ // Check for External INT0 Interrupt
switch(darbe_durumu) {
case 0: // First Low to High Pulse
TMR0H = 0; // Zero the high byte in TMR0H Buffer
TMR0L = 0; // Clear 16-bit TIMER0 Counter
darbe_durumu=1;
break;
case 1: // Second Low to High Pulse
rpm_zaman_sayici=TMR0L; // Get the first 8-bit TIMER0 Counter
rpm_zaman_sayici+=(TMR0H << 8); // Get the last 8-bit TIMER0 Counter
// RPM HESAPLA = 60 x (1/Periyot) periyot sensörün ilk beyzı gördüğü andan sonraki beyazı gördüğü ana geçtiği zaman
// RPM degeri = 60000 (1 / (0.032 ms x rpm_zaman_sayici))
rpm_deger =(60000.0 / (0.032 * rpm_zaman_sayici));
darbe_durumu=0;
}
INTCON.INT0IF = 0; // Clear INT0 interrupt flag
}
}
void init(){
// LCD AYARLARI//
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,1,txt1); // Write text in first row
Lcd_Out(2,1,txt2); // Write text in second row
delay_ms(750);
for(i=0;i<16;i++){
lcd_cmd(_lcd_shift_right);
delay_ms(500);
}
//ADC AYARLARI//
TRISA.RA0=1;
ADCON0=0b00000001; // ADC port channel 0 (AN0), Enable ADC
ADCON1=0b00001110; // Use Internal Voltage Reference (Vdd and Vss)
ADCON2=0b00101011; // Left justify result, 12 TAD, Select the FRC for 16 MHz
//ECCP MODUL AYARLARI TEK ÇIKIS İÇİN//
/*Tek çıkış pwm için 4.975Hzlik sinyal üretilip sinyalin 1 kalma oranıyla ADC ile ayarlanıp
motoru hızlandırıp veya yaşlatabiliriz*/
TRISC.RC2=0;
PORTC.RC2=0;
CCP1CON=0b00001100; // Single PWM mode; P1A, P1C active-high; P1B, P1D active-high
CCPR1L=0; // Start with zero Duty Cycle
// PWM Period = 4 x Tosc x (PR2 + 1) x TMR2 Prescale Value
// Tosc = 1/16 Mhz = 0.0000000625
// PWM Period = 4 x 0.0000000625 x 201 x 4 = 0.000201
// PWM Frequency = 1/PWM Period = 1/0.000201 = 4.975 kHz
T2CON=0b00000101; // Postscale: 1:1, Timer2=On, Prescale = 1:4
PR2=200; // Frequency: 4.975 kHz
TMR2=0; // Start with zero Counter
//TMR0 AYARLARI RPM İÇİN ZAMAN SAYACAK//
// Init TIMER0: Period: 4 x Tosc x Prescale for each counter
// Tosc = 1/16 Mhz = 0.0000000625
// TIMER0 Period: 4 x 0.0000000625 x 128 = 0.000032 Second = 0.032 ms
INTCON=0XC0;
T0CON = 0b10000110; // TIMER0 Enable, use 16-bit timer and prescale 1:128
TMR0H = 0; // Zero the high byte in TMR0H Buffer
TMR0L = 0; // Clear 16-bit TIMER0 Counter
INTCON.TMR0IE = 1; // Enable TIMER0 Overflow Interrupt
//INT KESME AYARI//
// Set the External Interrupt on INT0 (RC0) Port
INTCON.INT0IE = 1; // Enables the INT0 external interrupt
INTCON2.INTEDG0 = 1; // Interrupt on rising edge
TRISB.RB0=1;
PORTB.RB0=0;
Lcd_Cmd(_LCD_CLEAR); // Clear display
}
void main() {
init();
while(1){
lcd_out(1,1,"RPM:");
GO_DONE_BIT=1;
while(GO_DONE_BIT) continue;
adc_deg=ADRESH;
CCPR1L=adc_deg;// CCPR1L register içine ADC alınan değer eklenirve 4.975Hz frekansın 1 periyot içindeki 1 kalma oranı belirlenir
duty_cycle=(adc_deg/255.0) * 100.0;
bytetostr(duty_cycle,kelime);
lcd_out(2,1,"DUTY CYCLE");
lcd_out(2,12,kelime);
lcd_out(2,16,"%");
inttostr(rpm_deger,kelime1);
lcd_out(1,6,kelime1);
}
}
Kaynak
Hiç yorum yok:
Yorum Gönder