2 Temmuz 2014 Çarşamba

PWM Motor Hız Kontrol Ve RPM Sayıcı Projesi.


  Ş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ı
 
 MikroC kodu;

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;

void interrupt(){
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