17 Temmuz 2014 Perşembe

EUSART DONANIM BIRIMI ILE RF MOTOR KONTROL



   Bu çalışmamdaki amacım iki ayrı devre oluşturarak bir kablosuz alıcı verici devresi yapmak. Bunun için daha önceki çalışmalarımda yaptığım motor kontrol devresini yapacağım. Yani alıcı kısımın da benim motorum olacak ve onu sürecek olan devre verici kısmında ise benim analog potuma bağlı olan ayrı bir devre. Yani analog pot hızı kontrol edecek.

 Kullanacağım alıcı verici çifti;

http://www.direnc.net/433MHZ-RF-ALICI-VERICI-KRISTALLI-TAKIM,PR-1580.html

 

Aslında alıcı ve verici sanki iki devre arasında bir kablo varmış gibi davranır alıcı ve verici modüllerinin yerine bir kablo ile bağlasanız da aynı  işi yapar. Ama amacımız kablosuz iletişim olduğunda buna gerek yok.


Ve devre şemam;
 
 
 
 
 Bu devremde alıcı ve verici kısmında birer tane mikrodenetliyici kullanıldı. Alıcı kısmında 18F4550 kullanıldı bu entegrenin sahip olduğu TIMER2, ECCP ve son olarak EUSART donanım birimleri kullanıldı. Bu son donanım birimin kullanılmasında ki amaç yukarıdaki en başta yer alan resimlerde alıcı ve verici çiftine data alışverişini yapması için kullanıldı. Verici kısmında 18f2550 kullanıldı
ve donanım birimi olarak da ADC ve EUSART donanım birimleri kullanıldı.

 MikroC programında yazılım yazılırken EUSART donanım biriminin hazır kod kullanılmadı onun yerine kendim yeninden inşa ettim herşeyi.

 Eusart modulu ASCII karaketer alır ve gönderir ve bu yüznden stringlerle iş yaparsınız bu önemli bir nokta. Örneğin; Siz vericinizden 255 sayısını göndereceksiniz diyelim bunu stringe çevirmelisiz yani "255" bunun gibi yoksa 255 gönderilmez alıcı doğru veri almaz. Alıcı da ise alına  bu string üzerinde bir işlem yapmak isterseniz eğer bu "255" stringini decimal sayıya çevirmelisiz. Yani  vericiniz "255"
datasını gönderdi ama bu string siz alıcı kısmında alınan bu data üzerine +10 sayısını ilave etmek istiyorsunuz direk "255"+10 diyemezsiniz yanlış bu. Bun yerine "255" alınan bu stringi decimal sayıya çevirip öyle eklersiniz  255+10 gibi.

 Bende bu çalışmamda bunun gibi yaptım verici kısmında potdan aldığı değeri yani decimal sayıyı stringe çevirip öyle alıcıya gönderdim orada onu decimal sayıya çevirip öyle işlem yaptım.



 /* UART MODULU YAPILANDIRILMASI */
     TXSTA=0;              //ILK ANDA SIFIR
     RCSTA=0;
     SPBRG=103;            //16 MHZ İÇİN 9600 BİT/SN hızında baundrate
     TXSTA=0X26;
     RCSTA=0X90;
     INTCON=0XC0;
     PIE1.RCIE=1;          //RSR DEN RCREG VERI AKTARILDIĞINDA KESME OLUŞSUN

 Yukarıdaki kodda, Euart donanım birimin yapılandırılması gösterilmiştir. Alıcı kısmında 16mhz kristal kullanılıp SPBRG register içine 103 yazılarak 9600 baud da ayarlanmıştır. Verici kısmında 20Mhz kristal kullanılıp SPBRG=129 yazılmıştır önemli olan nokta her ikisinde de 9600 baud olmalıdır. Yani saniye 9600 bit gönderilir ve alınır. 


void interrupt(){
  if(PIR1.RCIF){
     if(RCSTA.FERR || RCSTA.OERR){// Eğer karakter almada FIFO register ile sorun oluşursa
              RCSTA.CREN=0;       // normal duruma getirmek için bunları yap
              delay_us(1);
              RCSTA.CREN=0;
              PIR1.RCIF=0;
     }
            RxBuffer=RCREG;     // Vericinden alınan karakteri kopyala
            control=1;
            PIR1.RCIF=0;
  }
}

Yukarıda olan kesme kodunda eğer veri yani string geldiyse kesme olur veri ilk stringi RxBuffer içine yazılır.


Alıcı kısmın MikroC kodu;

#define SIFRE_1 0x41
#define SIFRE_2 0x42
sbit LCD_RS at RB1_bit;
sbit LCD_EN at RB2_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 TRISB1_bit;
sbit LCD_EN_Direction at TRISB2_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 char RxBuffer,control=0;
void interrupt(){
  if(PIR1.RCIF){
     if(RCSTA.FERR || RCSTA.OERR){// Eğer karakter almada FIFO register ile sorun oluşursa
              RCSTA.CREN=0;       // normal duruma getirmek için bunları yap
              delay_us(1);
              RCSTA.CREN=0;
              PIR1.RCIF=0;
     }
            RxBuffer=RCREG;     // Vericinden alınan karakteri kopyala
            control=1;
            PIR1.RCIF=0;
  }
}
void init(){
   /* UART MODULU YAPILANDIRILMASI */
     TXSTA=0;              //ILK ANDA SIFIR
     RCSTA=0;
     SPBRG=103;            //16 MHZ İÇİN 9600 BİT/SN hızında baundrate
     TXSTA=0X26;
     RCSTA=0X90;
     INTCON=0XC0;
     PIE1.RCIE=1;          //RSR DEN RCREG VERI AKTARILDIĞINDA KESME OLUŞSUN
     // LCD AYARLARI//
    Lcd_Init();                        // Initialize LCD
    Lcd_Cmd(_LCD_CLEAR);               // Clear display
    Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
     //ADC AYARLARI//
     ADCON1 |=0X0F;
     CMCON  |=7;
     /* 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;  // FULL-BRIDGE CIKISLARI ICIN  AYARLAMALAR
     PORTC.RC2=0;
     TRISD.RD5=0;
     TRISD.RD6=0;
     TRISD.RD7=0;
     PORTD.RD5=0;
     TRISD.RD6=0;
     TRISD.RD7=0;
     CCP1CON=0b01001100;  // Full Bridge Forward; P1A, P1C active-high; P1B, P1D active-high
     CCPR1L=0X00;            // 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
}
char KarakterAl();
void GonderKarakter(char harf);
void StringYaz(char *str);
unsigned short RF_Read();
char strtobyte(char *str);
char verim[]="   ";
char ham_verim[2];
char datam[2];
unsigned short say=0,i=0;
unsigned int duty_cycle;
char kelime1[4];
char toplam;
void main() {
  init();
  while(1){
     say=0;
     do{
       verim[say]=RF_Read();
       say++;
     }while(say<3);
     ham_verim[i]=strtobyte(&verim[0]);
     i++;
     if(i>=3){
       Lcd_Cmd(_LCD_CLEAR);               // Clear display
        if(ham_verim[0]==3){
              CCPR1L = 0;
              duty_cycle=0;
              lcd_out(1,1," MOTOR DURDU !       ");
        }else{
            if(ham_verim[0]==2){
              while(!(P1M1_BIT==0&&P1M0_BIT==1)){
              Lcd_Cmd(_LCD_CLEAR);
                 P1M1_BIT=0;    // MOTOR'A SAGA CEVİRDI
                 P1M0_BIT=1;
              }
                 lcd_out(2,1," SAGA %         ");
                 CCPR1L=ham_verim[2];
                 duty_cycle=(ham_verim[2]/250.0) * 100.0;
                 bytetostr(duty_cycle,kelime1);
                 lcd_out(2,9,kelime1);
            }
            if(ham_verim[0]==1){
              while(!(P1M1_BIT==1&&P1M0_BIT==1)){
              Lcd_Cmd(_LCD_CLEAR);
                 P1M1_BIT=1;    // MOTOR'A SAGA CEVİRDI
                 P1M0_BIT=1;
              }
                 lcd_out(2,1," SOLA %        ");
                 CCPR1L=ham_verim[1];
                 duty_cycle=(ham_verim[1]/250.0) * 100.0;
                 bytetostr(duty_cycle,kelime1);
                 lcd_out(2,9,kelime1);
             }
        }
        i=0;
     }
  }
}
unsigned short RF_Read(){ // Karşı tarafatan karakter almaya başla.
        char tmp,i,say=0;i=0;
    do{
        tmp=KarakterAl();
        switch(i){
          case 0: if(tmp==SIFRE_1){ datam[0]=tmp;i++;} break;
          case 1: if(tmp==SIFRE_2){ datam[1]=tmp;i++;}else i=0; break;
          case 2:  datam[2]=tmp;i++;break;   // asıl karakterim
          default:break;
        }
    }while(i<3);
    return tmp;
}
void StringYaz(char *str){
      char i=0;
      while(*(str+i)!=0){    //  0\ işareti geldiğindeçıkar bu kelimeden
        GonderKarakter(*(str+i));   // string içindeki karakterleri tek tek gönder
        i++;
      }
}
void GonderKarakter(char harf){
     if(!(TXSTA.TXEN)) TXSTA.TXEN=1;  //gönderme yetkisi verildimi ?
     while(!(PIR1.TXIF));  PIR1.TXIF=1;  // eğer TXREG deki veri TSR'ye gönderildimi.
     TXREG=harf;                        // gönderildiyse yeni karakter yükle.
}
char KarakterAl(){
     while(!control);
     control=0;
     return RxBuffer;
}
char strtobyte(char *str){  // Vericiden alınan string tipinde karakterleri byte çevirme. Eğer çevirme
                            //yapılmaz ise üzerinden işlemler yapamayız.
  char S,onlar,birler,sayi,yuzler;
      for(S=0;S<3;S++){
          if(*(str+S)==0x20) *(str+S)=0x30;  //bOŞLUĞU SIFIRA ÇEVİRME
      }
      yuzler=( *(str+0)-48)*100;
      onlar=( *(str+1)-48)*10;
      birler=( *(str+2)-48);
      sayi=yuzler+onlar+birler;
      if(sayi>255) sayi=255;        // bir byte 255 değerini tutbilir bunu aşmasın diye sınırladık.
  return sayi;
}


Verici kısmın MikroC kodu;

#define SIFRE_1 0x41
#define SIFRE_2 0x42
void init(){
     /* ADC AYARLARI */
     ADCON0=0b00000011;
     ADCON1=0b00001110;
    
     TXSTA=0;              //ILK ANDA SIFIR
     RCSTA=0;
     SPBRG=129;            //16 MHZ İÇİN 9600 BİT/SN hızında baundrate
     TXSTA=0X26;
     RCSTA=0X90;

   TRISB.RB6=0;
   TRISB.RB7=0;
   TRISB.RB5=0;
   PORTB.RB6=0;
   PORTB.RB7=0;
   PORTB.RB5=1;
}
void data_gonder(char *veri);
void GonderKarakter(char harf);
void StringYaz(char *str);
unsigned int x_axis_ham;     // analogdan alınan sinyal
unsigned char x_axis;
char ham_veri[3];   // 3 bytelık verileri tutsun diye biz dizi oluşturuldu.
void main() {
     init();
     while(1){
                  x_axis_ham=ADC_read(0);
             if  ((x_axis_ham>=501)  & (x_axis_ham<=529)){  //EĞER ANALOG POT TAM ORTADAYSA
                  PORTB.RB6=0;
                  PORTB.RB7=0;
                 
                  ham_veri[0]=3; /* MOTOR DURDUR BILGISI*/
                  ham_veri[1]=0;
                  ham_veri[2]=0;
                  data_gonder(&ham_veri[0]);
            }else{
                  if (x_axis_ham<500){
                        PORTB.RB6=1;   /* SOLA DONECEK SINYALİ*/
                        PORTB.RB7=0;
                     while(x_axis_ham<=500){
                         x_axis_ham=ADC_read(0);
                         x_axis =(500-x_axis_ham)/2 ;
                         ham_veri[0]=1; /*P1M1_BIT=1, P1M0_BIT=1; sola karşı taraf için*/
                         ham_veri[1]=x_axis;
                         ham_veri[2]=0;
                         data_gonder(&ham_veri[0]);
                      }
                   }
                 if (x_axis_ham>530){
                         PORTB.RB6=0;    /* SAGA DONECEK SINYALİ*/
                         PORTB.RB7=1;
                       while(x_axis_ham>530){
                         x_axis_ham=ADC_read(0);
                         x_axis=(x_axis_ham-530)/2;
                         ham_veri[0]=2; /*P1M1_BIT=0, P1M0_BIT=1; saga*/
                         ham_veri[1]=0;
                         ham_veri[2]=x_axis;
                         data_gonder(&ham_veri[0]);
                      }
                 }
                    
            }
                    

     }
}
void data_gonder(char *veri){  //ham_veri deki değeleri gönderir
           char say,kelime[4];
           say=0;
           delay_ms(300);
               do{                                                           //0 1 2
                  bytetostr(*(veri+say),kelime);// kelime  ( _ _ _)
                  StringYaz(&kelime[0]);
                  say++;
               }while(say<3);
}
void StringYaz(char *str){
      char i=0;
      while(*(str+i)!=0){    //  0\ işareti geldiğindeçıkar bu kelimeden
         GonderKarakter(SIFRE_1);// starT1 byte
         GonderKarakter(SIFRE_2);// starT2 byte   //0 1 2
         GonderKarakter(*(str+i));   // string içindeki karakterleri tek tek gönder
        i++;
      }
}
void GonderKarakter(char harf){
     if(!(TXSTA.TXEN)) TXSTA.TXEN=1;  //gönderme yetkisi verildimi ?
     while(!(PIR1.TXIF));  PIR1.TXIF=1;  // eğer TXREG deki veri TSR'ye gönderildimi.
     TXREG=harf;                        // gönderildiyse yeni karakter yükle.
}

Kaynaklar

1) Altaş yayıncılık Pıc Programlama Teknikleri ve PIC16F877A
2) Altaş yayıncılık MıkroC ile PIC 18f4550 Programlama



Hiç yorum yok:

Yorum Gönder