RPM hesaplaması

Başlatan bulut_01, 07 Mayıs 2017, 03:01:27

bulut_01

iyi geceler pic proje ailesi dc motor enkoderdan aldıgım puls sayısına göre rpm bulmak istiyorum algoritmamda eksiklikler var saniyedeki frekans bulmaya calıştım basarısız oldum RPM ölçmem için kodda neler eklemem gerek yardımcı olursanız sevinirim.

#include <18F87K22.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NOBROWNOUT               //No brownout reset
#use delay(clock=16000000)
#use fast_io(b)


int16 konum=0,kk=0,pulse=0,freq=0;
int8  yon=0,eskia=0,eskib=0,yenia=0,yenib=0,duty=150;

#INT_RB
void  RB_isr(void) 
{
    
    yenia=input(pin_b6);                             // enkoder
     yenib=input(pin_b7);  
       yon=eskia^yenib;
     kk=kk+(2*yon)-1 ; 
     konum=kk/4;
     eskia=yenia;
     eskib=yenib;

}


#int_timer0  
void TIMER0_isr() 
{
set_timer0(0);
pulse++;

if(yenia>0){                                   //saniyedeki frekans
freq++;}

if(pulse==244){

disable_interrupts(INT_RTCC);}

}

void main(){ 

setup_ccp1(CCP_PWM | CCP_USE_TIMER1_AND_TIMER2); 
setup_timer_2(T2_DIV_BY_16, 2000,1); 
setup_oscillator(OSC_16MHZ ); 

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);

set_tris_a(0b00000000);
set_tris_b(0b11000000);
set_tris_c(0b00000000);
set_tris_d(0b00000000);
set_tris_e(0b00000000);
set_tris_f(0b00000000);
set_tris_g(0b00000000);
set_tris_h(0b00000000);
set_tris_j(0b00000000);

output_a(0x00);
output_b(0x00);
output_c(0x00);
output_d(0x00);
output_e(0x00);
output_f(0x00);
output_g(0x00);
output_h(0x00);
output_j(0x00);

while(true){ 
set_pwm1_duty(duty); 

}
}
YENİLMEZ..

mehmet

Mesela; 1sn süreyle pals okuyun;
bunu dakikadaki pals sayısına çevirin...
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

bulut_01

Mehmet hocam bunu kod yazarak gösterebilirmisiniz 2 gündür kafayı yicem saçma sapan degerler çıkıyor sim. Proteus yapıyorum
YENİLMEZ..

mehmet

#3
Ben CCS C bilmiyorum, sadece fikir vermeye
çalışıyorum. Muhtemelen bu şekilde olabilir;
#INT_RB
void  RB_isr(void) 
{
    sayac++;
}

#int_timer1
void TIMER1_isr() 
{
  Anlikdevir = (sayac / 2) * 60;
  sayac = 0;
}


Kesme zamanına göre timer kesmesi içindeki
hesaplamayı yeninden yapmanız gerekecek.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

bulut_01

Hocam rb kesmesinin içinde sayac değişkeni kullanmışınız  timer da ise sayac01 kullanmışınız burda bir yanlışlık yok mu rb kesmesinn içindeki değişkenle timer içindeki aynı olması gerekmiyor mu?
YENİLMEZ..

mehmet

Aynı olacak, düzeltiyorum...
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

emin.kiran

Ccs kullanmadim ama int0 interruptundan gelen pulslari 200ms boyunca say. Sureyi timerlardan biri ile yap timer interruptu sonunda degeri baska bir degiskene al sonucu 300 ile crprsan dakikadaki devir sayisini elde edebilirsin. Eger kynakla ilgili sorunun yoksa encoder bilgisi cok yogun degilse 1000ms de alabilirsin sureyi o vakit 60 ile carparsin kolay gelsin

bulut_01

@mehmet hocam öncelikle yardımlarınız için tsk ederim kodda biraz değişiklik yaparak anlık rpm ye yaklastım lakin düşük devirlerde çok hatalı ölcüm yapıyor 100 rpm altında düzgün ölçüm yapmıyor ayrıca anlık rpm debug ederken motor 100 rpm sabit dönerken anlık rpm 100 bazen 150 oluyor kafasına göre takılıyor burayıda nasıl aşacagımı işin içinden çıkamadım timer1 değilde timer0 kullanmamdan dolayı mı bu hatayla karşılasıyorum ccp kullanmak mı lazım sizce ?

#include <18F87K22.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NOBROWNOUT               //No brownout reset
#use delay(clock=16000000)
#use fast_io(b)



int32 RPM=0;
int16 konum=0,kk=0,puls=0,pulse=0;
int8  yon=0,eskia=0,eskib=0,yenia=0,yenib=0,duty=150;

#INT_RB
void  RB_isr(void) 
{
    
    yenia=input(pin_b6);                             // enkoder
     yenib=input(pin_b7);  
       yon=eskia^yenib;
     kk=kk+(2*yon)-1 ; 
     konum=kk/4;
     eskia=yenia;
     eskib=yenib;
     
     puls++;
    
   }

#int_timer0  
void TIMER0_isr() 
{

rpm = (puls / 1.5) * 60;
  puls = 0;

}

void main(){ 

setup_ccp1(CCP_PWM | CCP_USE_TIMER1_AND_TIMER2); 
setup_timer_2(T2_DIV_BY_16, 2000,1); 
setup_oscillator(OSC_16MHZ ); 

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);

set_tris_a(0b00000000);
set_tris_b(0b11000000);
set_tris_c(0b00000000);
set_tris_d(0b00000000);
set_tris_e(0b00000000);
set_tris_f(0b00000000);
set_tris_g(0b00000000);
set_tris_h(0b00000000);
set_tris_j(0b00000000);

output_a(0x00);
output_b(0x00);
output_c(0x00);
output_d(0x00);
output_e(0x00);
output_f(0x00);
output_g(0x00);
output_h(0x00);
output_j(0x00);

while(true){ 
set_pwm1_duty(duty);

}
}
YENİLMEZ..

mehmet

Düşük devirlerde istenilen pals
gelmeden sayaç sıfırlanıyor.
Ya bir devirde birkaç sinyal almak,
ya da timer kesme zamanını uzatmak
çözüm olabilir.
Eğer bir pals 50d/d veriyorsa;
bir kesmede 2 pals 100d/d yapar. 
Eğer tam kesme zamanına yakın bir
pals daha gelirse 150d/d olur.
Bu nedenle birim zamanda çok pals
almaya çalışmak hassasiyeti artıracaktır.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

bulut_01

Hocam sıfırlama olayı her 1 sn bir yapsak ölçümde hatamı olur yada pals sayısını x carpıp işlem yaparken yine o sayıya mı bölmek lazım net bir çözüm için hangisi mantıklıdır sizce
YENİLMEZ..

mehmet

Burada istenilen birim zaman. Bu 1sn olur,
10sn olur. Size kalmış. Program akışınızda
sıkıntı olmazsa daha uzun aralık seçilebilir.
Birim zamanda çok örnek almak hata oranını
düşürecektir. İmkanınız varsa 1sn değil daha
uzun süre pals sayın. Ya da bir devirde çok pals
almanın yollarını arayın.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

E-x8

Örnek olması açısından başka bir denetleyicide kullandığım yöntemi yazayım sizde kendi cihazınıza göre bunu yapılandırın.

Program main :
if (pin1 == high && bekle == false)
{
   sayac++;
}


Timerx (1sn süre için):
bekle = true;
rpm = sayac * 60;
sayac = 0;
bekle = false;

Kullandığınız pinin kesmesi yoksa dediğim şekilde yapabilirsiniz. Pinin kesmesi varsa daha güzel olur. Ayrıca yazan arkadaşlara katılıyorum ne kadar uzun dinlerseniz o kadar daha hassas ölçümler yapılabilir.