Ultrasonik sensör yardım

Başlatan bnmdmbrk, 30 Mayıs 2015, 11:33:25

bnmdmbrk

S.a. arkadaşlar. 3 ay oldu farklı farklı yollar denedim olmadı bir türlü. Programın son hali şöyle:

#include <16f877A.h>

#FUSES NOWDT, HS, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, WRT_50%

#use delay(clock=20000000)

#use fast_io(a)
#use fast_io(b)
#use fast_io(d)
#use fast_io(e) 

#include <lcd.h>

#DEFINE echo pin_b0
#DEFINE trig pin_b1

#byte T1CON = 0x10  // T1CON tanımlaması
#byte TMR1L = 0x0E  // TMR1L tanımlaması
#byte TMR1H = 0x0F  // TMR1L tanımlaması

unsigned int16 ham_sure=0;                //SAYICI DEĞERİ
unsigned int16 uzaklik=0;                 //UZAKLIK
unsigned int16 usure=0;                   //MİKROSANİYE CİNSİNDEN SÜRE
int1 hesapla=0;                           //1 ise hesapla, 0 ise ölçümü bekle

#int_ext
void  ext_kesmesi()
{
   if (input(echo)){     //eğer yükselen kenar geldiyse
      enable_interrupts(INT_TIMER1);      //tmr1'i aktifleştir
      set_timer1(0);                      //sayma işlemine 0'den basla
      ext_int_edge(H_TO_L);         //kesmeyi düşen kenara göre ayarla
   }
   else{                //eğer düşen kenarsa
      disable_interrupts(INT_TIMER1);     //timer1 kesmesi devredışı
      ham_sure=GET_TIMER1();        //timer1 in değerini al, ham_sure değişkenine ata
      clear_interrupt(INT_TIMER1);     //timer1'i sıfırla
      ext_int_edge(L_TO_H);         //kesmeyi yükselen kenara göre ayarla
      hesapla=1;                            //hesaplama biti aktif
   }
   clear_interrupt(int_ext);     //ext-kesmesini sıfırla
}

#int_timer1     //timer1 kesmesi oluşturuldu.
void  sure_asimi()   //süre aşımında uyarır. Teoride sensörden gelen sinyal timer'ı en fazla 55 binlere kadar saydırıyor.
{
   printf(lcd_putc,"\f Sure asimi \n Biraz bekle");
   delay_ms(1000);
   clear_interrupt(INT_TIMER1);           //timer-kesmesini sıfırla
   ext_int_edge(L_TO_H);         //kesmeyi yükselen kenara göre ayarla
}

void puls()
{
   if(!input(echo))
   {
      output_high(trig);
      delay_us(10);
      output_low(trig);
   }
}

void ayarlar()
{
   setup_timer_1(t1_internal | t1_div_by_8); //timer1 için setup ayarları yapılmaktadır.
   
   set_tris_a(0x01);
   output_a(0x00);
   set_tris_b(0x01);
   output_b(0x00);
   output_c(0x00);
   set_tris_d(0x00);
   output_d(0x00);
   set_tris_e(0x00);
   output_e(0x00);
   TMR1H = 0;
   TMR1L = 0;
   enable_interrupts(INT_EXT);       // INT_EXT kesmesini aktif yapar
   clear_interrupt(int_ext);
   ext_int_edge(L_TO_H);             // INT_EXT kesmesinin YÜKSELEN kenarda aktif olacağını belirtir
   enable_interrupts(GLOBAL);        // kesmelere izin verilir

lcd_init( );                     // LCD hazirlama islemi
lcd_send_byte(0, 0x0d);          // LCD Ekranda imlec yanip sonsun komutu.

}

void main()
{
   ayarlar();

   while(1)
   {
      puls();
      
      if(hesapla==1)
      {
                                                                                 usure=(ham_sure/10)*16;
      uzaklik=usure/58;              //uzaklığı bul    yol = zaman * hız = sayici * 34/1000 = sayici /58
      hesapla=0;
                                                                                 printf(lcd_putc,"\fus=%lu",usure);
                                                                                 printf(lcd_putc,"\ns=%lu",ham_sure);
                                                                                 printf(lcd_putc,"\ d=%lu",uzaklik);
      }
      
      if(uzaklik<15)
      {
         output_high(pin_c0);
      }else
      {
         output_low(pin_c0);
      }
      
      delay_ms(100);
   }
}


Devre ise şöyle :



Resimde s timerın saydığı değeri gösteriyor, us bu değerin kaç mikrosaniyeye karşılık geldiğini, d ise cm cinsinden uzunluk değerini.

Buradaki sorun ise timer1'in hep 63879 sayması. Pic'e sinyal doğru şekilde geliyor fakat pic timer ile bu zamanı doğru şekilde sayamıyor. Mesafeyi en sona kadar düşürdüğümde saydığı değer birden düşüyor. O da 4 cm olması gerekirken 36cm oluyor. (echo süreleri doğru şekilde geliyor).
İşin içinden bir türlü çıkamadım. Yardımlarınızı bekliyorum arkadaşlar.

ferdem

Vas. Timer1 başlatma-durdurma, timer1 tasma kesmesi enable-disable olaylarının ne zaman olacağını iyi ayırmalısınız. Bu ikisi birbirine karışmış gibi gördüm.
Kodunuzu MPLAB da adım adım debug edebilirsiniz, ben ettim hatalara göre düzenledim, şu anda timer1 de pulse genişliğine göre doğru değer görülüyor, bu haliyle bir deneyin.
Gördüm ki program çalıştığında timer1 çalışıyor, timer1 kesmesi bir defalık çalışıyor... Beklenmedik bir durum değil mi! Bu gibi durumları timer1 kesme rutini içinde led "toggle" yaptırıp tespit edebilirsiniz, adım adım gitmelisiniz. LCD kütüphane ile ilgili bir problem oldu, ilgili yerleri kendi denememde sildim. Kolay gelsin.
#include <16F877A.h>

#FUSES NOWDT, HS, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG

#use delay(clock=20000000)

#use fast_io(a)
#use fast_io(b)
#use fast_io(d)
#use fast_io(e)

#bit TMR1ON = 0x10.0 //timer 1 ON biti

//#include <lcd.h>

#DEFINE echo pin_b0
#DEFINE trig pin_b1

#byte T1CON = 0x10  // T1CON tanýmlamasý
#byte TMR1L = 0x0E  // TMR1L tanýmlamasý
#byte TMR1H = 0x0F  // TMR1L tanýmlamasý

unsigned int16 ham_sure=0;                //SAYICI DEÐERÝ
unsigned int16 uzaklik=0;                 //UZAKLIK
unsigned int16 usure=0;                   //MÝKROSANÝYE CÝNSÝNDEN SÜRE
int1 hesapla=0;                           //1 ise hesapla, 0 ise ölçümü bekle

#int_ext
void  ext_kesmesi()
{
   if (input(echo)){     //eðer yükselen kenar geldiyse
      enable_interrupts(INT_TIMER1);      //tmr1'i aktifleþtir, timer1 kesmesi aktiflesti!
      TMR1ON=1; //timer simdi saymaya baslayabilir
      set_timer1(0);                      //sayma iþlemine 0'den basla
      ext_int_edge(H_TO_L);         //kesmeyi düþen kenara göre ayarla
   }
   else{                //eðer düþen kenarsa
      disable_interrupts(INT_TIMER1);     //timer1 kesmesi devredýþý
      TMR1ON=0;
      ham_sure=GET_TIMER1();        //timer1 in deðerini al, ham_sure deðiþkenine ata
      set_timer1(0); 
      clear_interrupt(INT_TIMER1);     //timer1'i sýfýrla
      ext_int_edge(L_TO_H);         //kesmeyi yükselen kenara göre ayarla
      hesapla=1;                            //hesaplama biti aktif
   }
   clear_interrupt(int_ext);     //ext-kesmesini sýfýrla
}

#int_timer1     //timer1 kesmesi oluþturuldu.
void  sure_asimi()   //süre aþýmýnda uyarýr. Teoride sensörden gelen sinyal timer'ý en fazla 55 binlere kadar saydýrýyor.
{
   //printf(lcd_putc,"\f Sure asimi \n Biraz bekle");
  //Hooop!
    TMR1ON=0; //timer dursun
    set_timer1(0); //sifirlansin
   clear_interrupt(INT_TIMER1);           //timer-kesmesini sýfýrla
   ext_int_edge(L_TO_H);         //kesmeyi yükselen kenara göre ayarla, siradaki olcum icin
   output_toggle(pin_b2); //uyari
}

void puls()
{
   if(!input(echo))
   {
      output_high(trig);
      delay_us(10);
      output_low(trig);
   }
}

void ayarlar()
{
   setup_timer_1(t1_internal | t1_div_by_8); //timer1 için setup ayarlarý yapýlmaktadýr.
   
   TMR1ON=0;//timer kuruldu ama başlamasına gerek yok.
   set_tris_a(0x01);
   output_a(0x00);
   set_tris_b(0x01);
   output_b(0x00);
   output_c(0x00);
   set_tris_d(0x00);
   output_d(0x00);
   set_tris_e(0x00);
   output_e(0x00);
   TMR1H = 0;
   TMR1L = 0;
   enable_interrupts(INT_EXT);       // INT_EXT kesmesini aktif yapar
   clear_interrupt(int_ext);
   ext_int_edge(L_TO_H);             // INT_EXT kesmesinin YÜKSELEN kenarda aktif olacaðýný belirtir
   enable_interrupts(GLOBAL);        // kesmelere izin verilir

//lcd_init( );                     // LCD hazirlama islemi
//lcd_send_byte(0, 0x0d);          // LCD Ekranda imlec yanip sonsun komutu.

}

void main()
{
   ayarlar();

   while(1)
   {

      puls();
      
      if(hesapla==1)
      {
                                                                                 usure=(ham_sure/10)*16;
      uzaklik=usure/58;              //uzaklýðý bul    yol = zaman * hýz = sayici * 34/1000 = sayici /58
      hesapla=0;
                                                                              //   printf(lcd_putc,"\fus=%lu",usure);
                                                                           //      printf(lcd_putc,"\ns=%lu",ham_sure);
                                                                          //       printf(lcd_putc,"\ d=%lu",uzaklik);
      }
      
      if(uzaklik<15)
      {
         output_high(pin_c0);
      }else
      {
         output_low(pin_c0);
      }
      
      delay_ms(100);
   }
}

bnmdmbrk

Ellerin dert görmesin kardeşim. Debug nasıl edilir bilmiyorum hiç kullanmadım ama öğrenmek lazım :)