İki dalga arasındaki Faz Farkını Ölçmek

Başlatan kostebek, 10 Mayıs 2008, 14:21:03

kostebek

Merhaba arkadaşlar. Okulda hocam iki tane dalga arasındaki faz farkını ölçen bir uygulama yapmamızı istedi. Mesela şebekedeki gerilim ve akım arasındaki faz farkını ölçüp Endüktif ya da Kapasitif yük çektiğimize dair bilgi vercem.

Şimdi merak ettiğim konu mantığı. Mesela proteusta bir simülasyon olutrum aralarında 10ms olan iki tane dalga oluşturdum. Sonra aklıma Timer1 i Counter olarak kullanmak geldi.

Kesme geldiğinde yani Signal1 de lojik değişiklik olduğunda kesme gelsin. Kesme alt programında Timer saymaya başlasın sonra .......


İşte sonrası hakkında hiçbir fikrim yok :) Yani nasıl durduracaz ?


mcan

2 kesme kullan.programın başında 1. kesme aktif 2. kesme pasif olsun.birinci kesmeyi yükselen kenarda aktif olacak şekilde ayarla.
1. kesme geldiğinde zamanlayıcıyı başlat,1. kesmeyi pasifleştir.2 ci kesmeyi yükselen kenarda aktif olacak şekilde kur.
2. kesme geldiğinde zamanlayıcıyı oku.kesmeleri pasife al.zamanlayıcıdaki değer yarım periyottan büyükse.tüm periyottan zamanlayıcı değerini çıkar bir "a" değişkenine ata,bir "b" değişkenine bir işaret koy. eğer küçükse işlem yapma "a" değişkenine direk ata.kesme bayraklarını sil.zamanlayıcıyı sıfırla .1.kesmeyi aktif et . ana döngüdede kesme içinde değerini atadığın "a"değişkenini b değişenindeki işareti göz önünde bulundurarak değerlendir.....

çalışacağına garanti veremem.bir fikir olsun diye yazdım.

M_B

merhaba arkadas

http://www.biltek.tubitak.gov.tr/gelisim/elektronik/index.htm
sitesindeki 2007 projelerınde olan kasım projesını bır ıncele
burdan bır seyler cıkarabılırsın.

Kolay gelsen.
M_B
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

kostebek

Merhaba arkadaşlar cevaplarınız için teşekkür ederim.

Ben programı yazdım .Ama T1=get_timer1(); ile nedense Timer!in içindeki değeri alamıyorum gibime geliyor.

Sizce sorun nerede

//###########################
/*

*/
//###########################

#include <16F877.H>
#device *=16
#fuses XT,NOWDT,NOPROTECT,NOLVP     // Configuration register'ın ayarlanması için
#use delay(clock=20000000)          // kristal frekansı 20 Mhz
//#priority RTCC, TIMER1              //PORTB kesmesinin önemi daha fazla
#include <lcd.c>                    //LCD Sürücü dosyası

int sayac,f; //Timer 1 den fazla taştı mı diye kontrol ediliyor
float durum;
float sure,T1,derece;
//durum0=ilk kesme
//durum1=ikinci kesme
#int_timer1
void Sayici_Kes()
      {
      //fazlar arası değişiklik sırasında
      //birden fazla kesme gelirse
      //onları sayıyoruz
      sayac++;
      }
      
#int_rb
void Deg_Kes()
      {
            if(durum==0){
            //gerilim kesmesi geldi
            set_timer1(123); //Timer1'e 0 yükleyip başlat
            durum=1; //yeni gelecek durum artık 1
            }
            if(durum==1)
            //akim kesmesi geldi
            {

            //timer içini al
            T1 = get_timer1();
            sure = (T1*1.6)*1000 + sayac*104.8576;
            derece = 360*sure/20; //dalgaların 50Hz lik formları için
           //printf(lcd_putc,"\fSure=%f \nT1=%f", sure,T1);
           //delay_ms(1);
            //bu süreye kadar kaç kere kesme gelmmiş
            //ne kadar süre geçmiş     
            // 20 ms   ---> 360
            // sure ms ---> X
            //milisaniye olarak karşılık
            //hesap edildi 
            durum=2;
            }
            if(durum==2)
            {
            printf(lcd_putc,"\fSure=%fms\nDerece=%f", sure,T1);
            delay_ms(100);
            durum=0;
            sayac=0;
            }
               
      }
      

 void main()
   {
   lcd_init();
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);        // 20 Mhz clock ve T1_DIV_BY_8 modunda, Timer1 her 1.6us'de artar ve 104.8576ms'de taşar
   enable_interrupts(INT_TIMER1);
   //Gerilim bilgisi PortB ye bağlanıyor.
   //Kesme oluştuğunda Timer1 saymaya başlıyor
   //İkinci kesme geldiğinde 
   //süre hesap ediliyor
   enable_interrupts(INT_RB);   // 4, 5, 6 veya 7. bitin değişmesi kesme oluşturur.
   enable_interrupts(GLOBAL);
   set_timer1(0);
   durum=0;
   sayac=0;
   f=50;
   
   
   while(1)
   {

   }  
   }


Bu arada proteus design dosyasını değiştirdim.

RA0 RA2 pinie bağlı bacaklar RA5 RA6 yaptım

iyonosfer

Kodunu tam oalrka incelemedim ama bariz hatalar var,
* Kristal frekansı 20Mhz için XT değil HS fuse kullanmalısın.
* T1, Durum adlı değişkenleri float tanımlaman gereksiz.
* kesme içindeki if blocklarında hata var , durum = 0 olduğunda durumu = 1 yapıyorsun ama hemen altında da 1 mi diye bakıyorsun. Bu yapı yerine switch case kullansan daha iyi olur.

switch(Durum) 
{
case 0: sunu_bunu_yap();
            break;
case 1: bunu_sunu_yap();
            break;
case 2: bisey_yapma();
            break;
}

gibi
Blog Sayfam: www.teknobakis.com

kostebek

Alıntı yapılan: "iyonosfer"Kodunu tam oalrka incelemedim ama bariz hatalar var,
* Kristal frekansı 20Mhz için XT değil HS fuse kullanmalısın.
* T1, Durum adlı değişkenleri float tanımlaman gereksiz.
* kesme içindeki if blocklarında hata var , durum = 0 olduğunda durumu = 1 yapıyorsun ama hemen altında da 1 mi diye bakıyorsun. Bu yapı yerine switch case kullansan daha iyi olur.

switch(Durum) 
{
case 0: sunu_bunu_yap();
            break;
case 1: bunu_sunu_yap();
            break;
case 2: bisey_yapma();
            break;
}

gibi

Normalde asm. ile yazdığım için pek alışık değilim. Bu hatalar ondandır :) Durum değişkenini sonradan değiştirdim şu şekilde çalışıyor.

//###########################
/*
Erhan HARMANKAYA
Eren EGE
Çağdaş TOPÇU
Faz-Farkı Ölçer
*/
//###########################

#include <16F877.H>
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP     // Configuration register'ın ayarlanması için
#use delay(clock=20000000)          // kristal frekansı 20 Mhz
//#priority RTCC, TIMER1              //PORTB kesmesinin önemi daha fazla
#include <lcd.c>                    //LCD Sürücü dosyası

int sayac=0;
int f=50; //Timer 1 den fazla taştı mı diye kontrol ediliyor
int durum=0;
int16 T1;
float sure,derece;
//durum0=ilk kesme
//durum1=ikinci kesme
#int_timer1
void Sayici_Kes()
      {
      //fazlar arası değişiklik sırasında
      //birden fazla kesme gelirse
      //onları sayıyoruz
      sayac++;
      set_timer1(0);
      }
      
#int_rb
void Deg_Kes()
      {
            if(durum==0){
            //gerilim kesmesi geldi
            set_timer1(0); //Timer1'e 0 yükleyip başlat
  
            }
            if(durum==1)
            //akim kesmesi geldi
            {

            //timer içini al
            T1 = get_timer1();
            sure = (T1*0.2)*1000 + sayac*13.1072;
            derece = 360*sure/20; //dalgaların 50Hz lik formları için
           //printf(lcd_putc,"\fSure=%f \nT1=%f", sure,T1);
           //delay_ms(1);
            //bu süreye kadar kaç kere kesme gelmmiş
            //ne kadar süre geçmiş     
            // 20 ms   ---> 360
            // sure ms ---> X
            //milisaniye olarak karşılık
            //hesap edildi 
            }
            if(durum==2)
            {
            printf(lcd_putc,"\fSure=%fms\nT1=%Lu", sure,T1);
            delay_ms(10);
            durum=0;
            sayac=0;
//!            disable_interrupts(INT_RB);
//!            disable_interrupts(INT_TIMER1);
//!            disable_interrupts(GLOBAL);
            }
             durum++;  
      }
      

 void main()
   {
   lcd_init();
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);        // 20 Mhz clock ve T1_DIV_BY_1 modunda, Timer1 her 0.2us'de artar ve 13.1072ms'de taşar
   enable_interrupts(INT_TIMER1);
   //Gerilim bilgisi PortB ye bağlanıyor.
   //Kesme oluştuğunda Timer1 saymaya başlıyor
   //İkinci kesme geldiğinde 
   //süre hesap ediliyor
   enable_interrupts(INT_RB);   // 4, 5, 6 veya 7. bitin değişmesi kesme oluşturur.
   enable_interrupts(GLOBAL);
   set_timer1(5);

  while(1)
  {
  //bekle
  }
   }


Son olarak bu gibi kullandım ama LCD de sürekli değişen zamanlar görüyorum. Sanırım kesmelerden olsa gerek. Bu yüzden düşen kenar ya da yükselan kenar tetiklemesi olayını nasıl yapabilirim.

ise

2. fazda genlik ve fonksiyon sabit ise sin(x) gibi . karşılaştırılacak fazın aşağıdan yukarıya 0 olması beklenir ve diğer fazın yükselen mi düşenmi voltaj olduğuna ve voltajına bakılarak açısı çıkar.  misal  ölçülen değer 155 volt ise   155=310.sinx   asinx =1/2   yani 30 derece bulunur.

kostebek

Alıntı yapılan: "ise"2. fazda genlik ve fonksiyon sabit ise sin(x) gibi . karşılaştırılacak fazın aşağıdan yukarıya 0 olması beklenir ve diğer fazın yükselen mi düşenmi voltaj olduğuna ve voltajına bakılarak açısı çıkar.  misal  ölçülen değer 155 volt ise   155=310.sinx   asinx =1/2   yani 30 derece bulunur.

pardon ama anlayamadım tam olarak ?

ise

sin30 = sin150  , sin210 = sin330   gibi yani senin sadece 0 noktasına bakıp fazın ilerdemi kalıyor geridemi kalıyor anlaman pek mümkün değil  onun için yükselenmi  düşenmi olduğuna bakman lazım  sin 0 = sin180   yani 0 noktası  bu noktadan sonra ölçüm yapılır pekala biz hangi noktadayız  sin0  mı sin 180 mi  bunu anlamak için fazın yükselenmi düşenmi olduğuna bakıyoruz. ondan sonra diğer fazda aynı şekilde düşenmi yükselenmi olduğunu bakılıyor  faz ilerdemi geridemi ortaya çıkıyor( bu yöntem harmonik sistemler için geçerli değil)

kostebek

ise teşekkürler. Güzel yöntemmiş. Ama ben değişik bir özellik daha buldum. Dışardan gelen kesmeleri ancak Yükselen kenarda aktif olarak şekilde yaptığımda sıfır'a göre neredeyim bulabiliyorum.

Son olarak şöyle bir kod yazdım. Teorik olarak gayet güzel çalışıyor. Ama neden proteusta ben faz farkını değiştirsem bile LCD de yazan süre değişmiyor ?

Kodu buraya yapıştırıyorum. Proteus dosyası ve kodlarıyla beraber de Rapidshare'e koyuyorum.

//###########################
/*

*/
//###########################
#include <16F877.H>
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP     // Configuration register'ın ayarlanması için
#use delay(clock=20000000)          // kristal frekansı 20 Mhz
//#priority RTCC, TIMER1              //PORTB kesmesinin önemi daha fazla
#include <lcd.c>                    //LCD Sürücü dosyası

int sayac=0;
int f=50; //Timer 1 den fazla taştı mı diye kontrol ediliyor
int durum=0;
int16 T1;
float sure,derece;
//durum0=ilk kesme
//durum1=ikinci kesme
#int_rtcc
void Sayici_Kes()
      {
      //fazlar arası değişiklik sırasında
      //birden fazla kesme gelirse
      //onları sayıyoruz
      sayac++;
      set_timer0(0);
      }
      
#int_rb
void Deg_Kes()
      {
      
            if(durum==0){
            //gerilim kesmesi geldi
            set_timer0(0); //Timer1'e 0 yükleyip başlat
  
            }
            if(durum==1)
            //akim kesmesi geldi
            {

            //timer içini al
            //delay_us(10);
            T1 = get_timer0();
            sure = (T1*0.2) + sayac*51;
            derece = 360*sure/20; //dalgaların 50Hz lik formları için
            //disable_interrupts(INT_RB);
            disable_interrupts(INT_TIMER1);
            printf(lcd_putc,"\fSure=%fus\nT1=%Lu Durum=1", sure,T1);
            delay_ms(10);
            //disable_interrupts(GLOBAL);
           //printf(lcd_putc,"\fSure=%f \nT1=%f", sure,T1);
           //delay_ms(1);
            //bu süreye kadar kaç kere kesme gelmmiş
            //ne kadar süre geçmiş     
            // 20 ms   ---> 360
            // sure ms ---> X
            //milisaniye olarak karşılık
            //hesap edildi 
            }
            if(durum==2)
            {
            printf(lcd_putc,"\fSure=%fus\nT1=%Lu Durum=2", sure,T1);
            delay_ms(10);
            durum=0;
            sayac=0;

            }
             durum++;  
      }
      

 void main()
   {
   lcd_init();
   //setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);        // 20 Mhz clock ve T1_DIV_BY_1 modunda, Timer1 her 0.2us'de artar ve 13.1072ms'de taşar
   setup_timer_0 (RTCC_DIV_1);    //yükselen kenar tetiklemeli HER ARTIŞ 0.2 us 0.2x255 = 52 us de taşar
   enable_interrupts(INT_RTCC);
   //Gerilim bilgisi PortB ye bağlanıyor.
   //Kesme oluştuğunda Timer1 saymaya başlıyor
   //İkinci kesme geldiğinde 
   //süre hesap ediliyor

   enable_interrupts(INT_RB);   // 4, 5, 6 veya 7. bitin değişmesi kesme oluşturur.
   ext_int_edge(H_TO_L); 
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   set_timer1(5);

  while(1)
  {
  //bekle
  }
   }




http://rapidshare.com/files/114291069/FazFarkiOlcer.rar.html


ykazova

merhaba linkteki dosyayı tekrar paylaşırmısınız ?

xoom

Alıntı yapılan: ykazova - 15 Haziran 2013, 06:16:16
merhaba linkteki dosyayı tekrar paylaşırmısınız ?
12 Mayıs 2008, 09:15:20

Sizce istediğiniz şey biraz ütopya değil mi? ayrıca tüm dosyaları son mesajında vermiş..  :o



said.ylcn

Alıntı yapılan: kostebek - 12 Mayıs 2008, 09:15:20
ise teşekkürler. Güzel yöntemmiş. Ama ben değişik bir özellik daha buldum. Dışardan gelen kesmeleri ancak Yükselen kenarda aktif olarak şekilde yaptığımda sıfır'a göre neredeyim bulabiliyorum.

Son olarak şöyle bir kod yazdım. Teorik olarak gayet güzel çalışıyor. Ama neden proteusta ben faz farkını değiştirsem bile LCD de yazan süre değişmiyor ?

Kodu buraya yapıştırıyorum. Proteus dosyası ve kodlarıyla beraber de Rapidshare'e koyuyorum.

//###########################
/*

*/
//###########################
#include <16F877.H>
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP     // Configuration register'ın ayarlanması için
#use delay(clock=20000000)          // kristal frekansı 20 Mhz
//#priority RTCC, TIMER1              //PORTB kesmesinin önemi daha fazla
#include <lcd.c>                    //LCD Sürücü dosyası

int sayac=0;
int f=50; //Timer 1 den fazla taştı mı diye kontrol ediliyor
int durum=0;
int16 T1;
float sure,derece;
//durum0=ilk kesme
//durum1=ikinci kesme
#int_rtcc
void Sayici_Kes()
      {
      //fazlar arası değişiklik sırasında
      //birden fazla kesme gelirse
      //onları sayıyoruz
      sayac++;
      set_timer0(0);
      }
      
#int_rb
void Deg_Kes()
      {
      
            if(durum==0){
            //gerilim kesmesi geldi
            set_timer0(0); //Timer1'e 0 yükleyip başlat
  
            }
            if(durum==1)
            //akim kesmesi geldi
            {

            //timer içini al
            //delay_us(10);
            T1 = get_timer0();
            sure = (T1*0.2) + sayac*51;
            derece = 360*sure/20; //dalgaların 50Hz lik formları için
            //disable_interrupts(INT_RB);
            disable_interrupts(INT_TIMER1);
            printf(lcd_putc,"\fSure=%fus\nT1=%Lu Durum=1", sure,T1);
            delay_ms(10);
            //disable_interrupts(GLOBAL);
           //printf(lcd_putc,"\fSure=%f \nT1=%f", sure,T1);
           //delay_ms(1);
            //bu süreye kadar kaç kere kesme gelmmiş
            //ne kadar süre geçmiş     
            // 20 ms   ---> 360
            // sure ms ---> X
            //milisaniye olarak karşılık
            //hesap edildi 
            }
            if(durum==2)
            {
            printf(lcd_putc,"\fSure=%fus\nT1=%Lu Durum=2", sure,T1);
            delay_ms(10);
            durum=0;
            sayac=0;

            }
             durum++;  
      }
      

 void main()
   {
   lcd_init();
   //setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);        // 20 Mhz clock ve T1_DIV_BY_1 modunda, Timer1 her 0.2us'de artar ve 13.1072ms'de taşar
   setup_timer_0 (RTCC_DIV_1);    //yükselen kenar tetiklemeli HER ARTIŞ 0.2 us 0.2x255 = 52 us de taşar
   enable_interrupts(INT_RTCC);
   //Gerilim bilgisi PortB ye bağlanıyor.
   //Kesme oluştuğunda Timer1 saymaya başlıyor
   //İkinci kesme geldiğinde 
   //süre hesap ediliyor

   enable_interrupts(INT_RB);   // 4, 5, 6 veya 7. bitin değişmesi kesme oluşturur.
   ext_int_edge(H_TO_L); 
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   set_timer1(5);

  while(1)
  {
  //bekle
  }
   }




http://rapidshare.com/files/114291069/FazFarkiOlcer.rar.html

(Resim gizlendi görmek için tıklayın.)

konu üzerinden faz zaman geçmiş ama şansımı denemek istiyorum :) timer da bende çok sıkıntı yaşadım. Revize ettiğiniz düzenlenmiş kod var mı yada sorunu nasıl çözdüğünüz hakkında bilgi verebilirmisiniz. lcd de durum 0 a geri dönemediği için süre değişmiyor. Düzeltemedim bir türlü.