Haberler:

Eposta uyarılarını yanıtlamayınız ( ! ) https://bit.ly/2J7yi0d

Ana Menü

Duty Cycle Ölçümü

Başlatan yldzelektronik, 02 Eylül 2013, 10:07:23

yldzelektronik

Selamlar.

Static olarak tanımladığım 32 bit değişken nedense 65535 den daha büyük bir değer almıyor.

Değişkeninin içeriğini 0xFFFFFFFF yapmama rağmen yine de en yüksek değeri 16bit sayının aldığı değer olabiliyor.Hal böyle olunca hesap amaçlı kullandığım formül doğru işlemiyor.

Bu arada proteus üzerinde simülasyon yapıyorum.Burada debug sırasında hatayı görünce kartta denemek istemedim.

static int32 w = 0xffffffff, T = 0;


mesaj birleştirme:: 02 Eylül 2013, 11:02:05

Şimdi bir test yaptım ve seri porttan w yi gönderdiğimde max değere ulaştığını gördüm.Ancak neden işlem yaparken değişkenin içeriğini göremiyorum?
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

mufitsozen

Alıntı yapılan: yldzelektronik - 02 Eylül 2013, 10:07:23
Selamlar.

Static olarak tanımladığım 32 bit değişken nedense 65535 den daha büyük bir değer almıyor.

Değişkeninin içeriğini 0xFFFFFFFF yapmama rağmen yine de en yüksek değeri 16bit sayının aldığı değer olabiliyor.Hal böyle olunca hesap amaçlı kullandığım formül doğru işlemiyor.

Bu arada proteus üzerinde simülasyon yapıyorum.Burada debug sırasında hatayı görünce kartta denemek istemedim.

static int32 w = 0xffffffff, T = 0;


formul satir(lar)ini gorebilirmiyiz?
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

sadogan

#2
Proteustandır. benzer bir sorun bende yaşamıştım.
Ama mana veremediğim bir durum vardı. Programı 24F16ka102 için yazınca proteus 32 bit işlemlerde
saçmalıyordu 18f45k22 için yazdığımda hata yapmıyordu.
sizin işlemci nedir.

yldzelektronik

#3
Pic16f1825.Garip gerçekten seri porttan basınca lu ile 32bit değer geliyor ancak değişken değeri 16bit max değeri oluyor.

mesaj birleştirme:: 02 Eylül 2013, 11:06:51

Alıntı yapılan: mufitsozen - 02 Eylül 2013, 11:02:45
formul satir(lar)ini gorebilirmiyiz?

Geç fark ettim kusura bakmayın.

//t1,t2,t3 uint16 w uint32 duty float olarak tanımlı           
 w = (t2 - t1) * 8;
 T = (t3 - t1) * 8;
duty = (float)(w *100) / 200;


Şuanda bu şekilde.Çok bir iş yok şimdilik.Düzeltebilsem diğer kısımları da ekleyeceğim.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

sadogan

w = (t2 - t1) * 8;

t1,t2 16 bit işlem sonrası 16 biti taştığı durumlarda bahsetiğiniz sonuç ortaya çıkar.
w = (int32)(t2 - t1) * 8;

şeklinde tape casting yaparak denermisin

yldzelektronik

Alıntı yapılan: sadogan - 02 Eylül 2013, 11:34:33
w = (t2 - t1) * 8;

t1,t2 16 bit işlem sonrası 16 biti taştığı durumlarda bahsetiğiniz sonuç ortaya çıkar.
w = (int32)(t2 - t1) * 8;

şeklinde tape casting yaparak denermisin

Siz yazmadan evvel denedim ve terminalden aldığım değer olması gereken değere döndü ancak halen değişken içeriklerini gözlerken normal değeri gözleyemiyorum.Şimdi kart üzerinde test edeceğim.Ancak halen anlamadım neden isisin böyle bir şey yaptığını.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

mufitsozen

sayin @yldzelektronik,  c dilinde expression soldan saga dogru islenir.

sizin ilk kullandiginiz t2 degiskeni 16 bit oldugu icin butun islem 16bit yapilip sonra w icin 32 bite promote ediliyor. Bu yuzden en sola 32bit cast koyunca butun islem 32 bit yapiliyor.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

yldzelektronik

Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

yldzelektronik

#8
Pic16f1825 kullanarak 5 hzlik bir sinyalin duty cycle oranını ölçmeye çalışıyorum.CCP interrupt ile yapıyorum ancak aldığım ölçümlerden sadece ilk ölçümler doğru oluyor.

Mantık olarak

Yükselen kenarda kesme üretiliyor.
Timer1 kuruluyor.
Düşen kenarda timer1 0'lanıyor..
Tekrar yükselen kenarda bir kesme üretiliyor.
Tmr1 değeri alınıyor (t1).
Düşen kenarda kesme üretiliyor.
Timer1 değeri alınıyor (t2).
Yükselen kenarda bir kesme üretiliyor.
Timer1 değeri alınıyor (t3).
W(high süresi) = t2 - t1
T (period) = t3 - t1
Duty = w/T
Microchipin dökümanında duty cycle için w/T diyor.Ancak sonuç hatalı çıkıyor.Ben de periodum sabit olduğundan ;
duty = (float)((w *50) / 100) / 1000;
şeklinde hesapladım.Ancak aldığım ölçümler hatalı çıkabiliyor.Sabit ölçüm alabilmek istiyorum.Nerede hata yapıyor olabilirim yada neyi atlıyor olabilirim?

//Kesme fonksiyonu aşağıda.
static char flag = 0, flag1 = 0;
static unsigned int16 t1 = 0, t2 = 0, t3 = 0;
static unsigned int32 w = 0, T = 0;
float duty = 0.0000;

#int_CCP1
void  CCP1_isr(void) 
{
      disable_interrupts(INT_CCP1);      
      flag++;
      if(flag == 1){
            setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
            setup_ccp1(CCP_CAPTURE_FE);
      }
      else if(flag == 2){
            setup_ccp1(CCP_CAPTURE_RE);
            set_timer1(0);
      }
      else if(flag == 3){
            t1 = get_timer1();
            setup_ccp1(CCP_CAPTURE_FE);
            flag1 = 0;
      }
      else if(flag == 4){
            t2 = get_timer1();
            setup_ccp1(CCP_CAPTURE_RE);
      }
      else if(flag == 5){
            t3 = get_timer1();
            flag = 2;
            flag1 = 1;
            set_timer1(0);
      }
      enable_interrupts(INT_CCP1);
}
//main döngüde şuan için yalnızca duty formülüm var.
      if(flag1){
            //disable_interrupts(INT_CCP1);
            w = (unsigned int32)(t2 - t1) * 8;
            T = (unsigned int32)(t3 - t1) * 8;
            duty = (float)((w *50) / 100) / 1000;
            printf("Duty:%f\n\r",(float)duty);
            printf("---------\n\r");
            //enable_interrupts(INT_CCP1);
      }


Döküman linki:
Sayfa 13 (TIP #4 Measuring Duty Cycle)
http://ww1.microchip.com/downloads/en/devicedoc/41214a.pdf
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

cicjoe

Hocam w integer tanimli ise hata burda olabilir: duty = (float)((w *50) / 100) / 1000;
int / int = int seklinde sonuc verir. sonucu float'a cast etmeniz ile virgulden sonrasini kaybedersiniz..
Bunun yerine soyle yazabilirsiniz: duty = ((w *50f) / 100f) / 1000f;

sadogan

Alıntı yapılan: yldzelektronik - 02 Eylül 2013, 18:41:17
Pic16f1825 kullanarak 5 hzlik bir sinyalin duty cycle oranını ölçmeye çalışıyorum.CCP interrupt ile yapıyorum ancak aldığım ölçümlerden sadece ilk ölçümler doğru oluyor.

Mantık olarak

Yükselen kenarda kesme üretiliyor.
Timer1 kuruluyor.
Düşen kenarda timer1 0'lanıyor..
Tekrar yükselen kenarda bir kesme üretiliyor.
Tmr1 değeri alınıyor (t1).
Düşen kenarda kesme üretiliyor.
Timer1 değeri alınıyor (t2).
Yükselen kenarda bir kesme üretiliyor.
Timer1 değeri alınıyor (t3).
W(high süresi) = t2 - t1
T (period) = t3 - t1
Duty = w/T
Microchipin dökümanında duty cycle için w/T diyor.Ancak sonuç hatalı çıkıyor.Ben de periodum sabit olduğundan ;
duty = (float)((w *50) / 100) / 1000;
şeklinde hesapladım.Ancak aldığım ölçümler hatalı çıkabiliyor.Sabit ölçüm alabilmek istiyorum.Nerede hata yapıyor olabilirim yada neyi atlıyor olabilirim?

//Kesme fonksiyonu aşağıda.
static char flag = 0, flag1 = 0;
static unsigned int16 t1 = 0, t2 = 0, t3 = 0;
static unsigned int32 w = 0, T = 0;
float duty = 0.0000;

#int_CCP1
void  CCP1_isr(void) 
{
      disable_interrupts(INT_CCP1);      
      flag++;
      if(flag == 1){
            setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
            setup_ccp1(CCP_CAPTURE_FE);
      }
      else if(flag == 2){
            setup_ccp1(CCP_CAPTURE_RE);
            set_timer1(0);
      }
      else if(flag == 3){
            t1 = get_timer1();
            setup_ccp1(CCP_CAPTURE_FE);
            flag1 = 0;
      }
      else if(flag == 4){
            t2 = get_timer1();
            setup_ccp1(CCP_CAPTURE_RE);
      }
      else if(flag == 5){
            t3 = get_timer1();
            flag = 2;
            flag1 = 1;
            set_timer1(0);
      }
      enable_interrupts(INT_CCP1);
}
//main döngüde şuan için yalnızca duty formülüm var.
      if(flag1){
            //disable_interrupts(INT_CCP1);
            w = (unsigned int32)(t2 - t1) * 8;
            T = (unsigned int32)(t3 - t1) * 8;
            duty = (float)((w *50) / 100) / 1000;
            printf("Duty:%f\n\r",(float)duty);
            printf("---------\n\r");
            //enable_interrupts(INT_CCP1);
      }


Döküman linki:
Sayfa 13 (TIP #4 Measuring Duty Cycle)
http://ww1.microchip.com/downloads/en/devicedoc/41214a.pdf



5 Hz lik pwh in 1 peyodu 200 ms tmr1 16 bit olduğundan 0xFFFF kadar saycak.
tmr1 saat frekansınız 1mhz olsa (bunu 4 mhz kristal ve tmr1 önbölucu 1 varsaydım)
65535 den sonra tmr1 de taşma meydana gelecek. Bu yapıda 65535 us den büyük
darbeleri bu yapıyla ölçmek mümkün deyil. Tmr1 kesmesini aktif edip taşma varmı ve kaç kez tasmış
kontrol edilmesi lazım.

Tmr1 yapılandırması ve osc frekansını vermiş olsaydınız daha net cevap olabilirdi.

yldzelektronik

Timer1 yapılandırması kesme fonksiyonunda belirtmiştim :) ancak tekrar belirtmek gerekirse;

//Timer1 yapılandırması
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);

//Osc yapılandırması (dahili kristal)
#use delay(int=4000000)
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

yldzelektronik

Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.