HC-SR04 ultrasonıc sönsör hata önlemi

Başlatan Denizccan, 27 Mayıs 2015, 20:54:14

Denizccan

İyi günler arkadaşlar.

Yaptığım projede 5 adet hc-sr04 ses sensörü kullanmaktayım. Sensörler bir oyuncak araç üzerinde takılı ve araç hareket halindeyken veya çapraz konumlara geldiğinde sensörlerden doğal olarak veri alamıyorum bunun sebebini giden ses sinyalinin geri dönememesi ve sonsuz döngüde takılı kalma olarak düşündüm.

Bunlara bir çözüm yolu üretmem lazım ve ben çözüm olarak ikinci bir timer kullanarak ses geri dönmediği taktirde timer belli bir oranın üzerine çıksın ve sonsuz döngüden programımı çıkarsın mesafe değerini 20cm olarak atasın ben ekrandan 20 gördüğümde sensörde sorun olduğunu anlayayım şeklinde düşündüm.

Buradaki sonsuz döngü ise trig ucunu aktif yaptığımda ses sinyali üretiliyor echo pini lojik 1 oluyor ses sinyali tekrar geldiğinde echo pini lojik 0 oluyor. Programda
while(input(ECHO))
{}
diyerek echo 0 olana kadar sonsuz döngü vardı ben bunu
while((!(input(ECHO4))) || (TMR0CNTR>500) )
{}
şeklinde değiştirerek ses geri gelmese bile timer0 dan dolayı döngüden cıksın olarak değiştirdim. Yaptığım denemelerde sensörde halen takılma oluyor acaba nerede hata yaptım söyleyebilirseniz çok sevinirim.

ilk program normal olarak kullandığım çalışan hali, ikinci ise değiştirdiğim çalışmayan hali.

Çalışan program

#include <18f4431.h> 
#fuses HS,NOPWMPIN,HPOL_HIGH,LPOL_HIGH,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD                                                         
#use delay (clock=20000000)       
#include <boost_lcd.c>                 



   #define trig1 pin_A0  
   #define echo1 pin_A1
   int16 zaman1=0;
   float mesafe1=0;
   
   
   
   void olcum1() // sensör1 okundu mesafe1 olarak atandı
   {
   output_high(trig1);            
   delay_us(15);              
   output_low(trig1);   
   while(!(input(ECHO1)))           
   {}   
   set_timer1(0);             
   while(input(ECHO1))           
   {} 
   zaman1=get_timer1();           
   mesafe1=(zaman1)/(290) ;        
   }
 

   void main ()
   {
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); // sensor ıcın tımer ayarı 
   lcd_init();                              //ekran temızlendı 

   
   while(1)     
   {
   olcum1();
   delay_ms(10);
   printf(lcd_putc, "\f MESAFE:%03.1f",mesafe1);
   delay_ms(100);
   }
   }


Çalışmayan program

#include <18f4431.h> 
#fuses HS,NOPWMPIN,HPOL_HIGH,LPOL_HIGH,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD                                                         
#use delay (clock=20000000)       
#include <boost_lcd.c>                 



   #define trig1 pin_A0  
   #define echo1 pin_A1
   int16 zaman1=0;
   float mesafe1=0;
   
   
   void olcum1() // sensör5 okundu mesafe5 olarak atandı
   {
   output_high(trig1);            
   delay_us(15);              
   output_low(trig1);
   while(!(input(ECHO1)))           
   {}   
   set_timer1(0);
   bit_set(T0CON,7);  //tımer 0 baslatıldı
   TMR0CNTR=0;        // tımer0 sayacı 0'landı
   while((input(ECHO1)) || (TMR0CNTR>500) ) 
   {}
   if(TMR0CNTR>500)
   {
   mesafe1=20;
   }
   if(TMR0CNTR<=500)
   {
   zaman1=get_timer1();           
   mesafe1=(zaman1)/(290) ;
   bit_clear(T0CON,7);   //tımer0 kapatıldı
   TMR0CNTR=0;           //tımer0 sayacı sıfırlandı
   } 
   }
 

   void main ()
   {
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); // sensor ıcın tımer ayarı 
   lcd_init();                              //ekran temızlendı 
   T0CON=0b00000111; // tımer0 ayarı prescaler 256 en fazla 65536 sayıyor
   bit_set(T0CON,7);  //tımer 0 baslatıldı
   TMR0CNTR=0;        //tımer0 sayacı 0'landı

   
   while(1)     
   {
   olcum1();
   delay_ms(10);
   printf(lcd_putc, "\f MESAFE:%03.1f",mesafe1);
   delay_ms(100);
   }
   }

selimkoc

while döngüsü içinde us bazında bekleme ve sayaç koy sayaç değeri belirli bir değeri aştığında döngüden çıksın. (bu süre sesin hızının 4 m yi aştığı süre olmalı)

Denizccan

Hocam söylediğiniz gibi denemeler yaptım programı aşağıda verdiğim gibi değiştirdim. Süre kısmını sizin dediğiniz gibi ayarlamaya çalışmadım ben max 75cm ölçüm yapmaktayım kafama göre birkaç değer atadım ama sonuç alamadım. Şu şekilde düşündüm süreyi düşük tutuğumdan dolayı belirli bir cm değeri aştıktan sonra bana mesafeyi hep 2cm olarak vermesi lazım. Aşağıda yazdıgım programda sensörler 34cm geçtikten sonra değişik değerler veriyor.
217,216,215 gibi değerler çıkıyor ekranda ama mantıken 2cm göstermesi lazım.

       void olcum5() // sensör5 okundu mesafe5 olarak atandı
   {
   output_high(trig5);            
   delay_us(15);              
   output_low(trig5);
   while(!(input(ECHO5)))           
   {}   
   set_timer1(0);
   sayac=0; 
   while((input(ECHO5)) || (sayac>500) )
   {
   delay_us(2);
   sayac=sayac+1;
   }
   if(sayac>499)
   {
   output_low(ECHO5);
   mesafe5=2;
   }
   if(sayac<=499)
   {
   zaman5=get_timer1();           
   mesafe5=(zaman5)/(290) ;
   output_low(echo5);
   }
   }

trgtylcnky

#3
timer > 500 demişsin < 500 demen gerekiyordu sanırım. Ayrıca || değil && olmalı bence.

mesaj birleştirme:: Mayıs 28, 2015, 17:02:28

Bu sensörde aynı sorunu biz de yaşamıştık. Siz programda döngüden çıksanız bile sensör hala takılı kalıyor, daha sonra gönderdiğiniz trigger sinyallerini almıyor. Onun için biz ölçümden sonra beslemeyi kesip geri açacak transistörlü bir sistem yapmıştık.

Denizccan

Hocam cevap verdiğiniz için teşekkür ederim öncelikle

while((input(ECHO5)) || (sayac>500) )


Şuan sıkıntım (input(ECHO5)) kısmı herzaman gerçekleşmiyor. Karşıdaki cisim çapraz konumda ise ses sinyalim geri gelmiyor. Araya sizin söylediğiniz gibi && (ve) operatörü koyarsam iki şartında sağlanması gerekli. Ben ise ||(veya) operatörü koyarak ilk şart sağlanmazsa ikinci şarttan dolayı döngüden çıkmasını sağlamak istedim. > yerine söylediğiniz gibi < işareti koyarsam döngü 1 kere gerçekleşecek ve hemen çıkacak oda olmaz.

trgtylcnky

Bence yanlış düşünüyorsun. Sorun sinyalin gelmemesi değil, ECHO5'in sürekli 1 konumunda kalması. Çünkü sinyal geldiğinde zaten ECHO5 0'a inecek ve 1 olduğu süre bize zaklığı verecek. Ayrıca, sayacı saymaya başlıyorsun, yani ilk başta 0. Bu durumda işlemin sayac>500 kısmı zaten 0 oluyor ilk başta yani 500'e kadar sonucu sadece ECHO5 etkileyecek. Ancak belli bir süre geçtikten sonra 500'ü geçerse bu sefer ECHO5 tamamen önemini kaybedecek çünkü zaten diğer taraf hep 1 olduğu için sonsuz döngüye girmiş olacak.

Zaten istediğin durum şu: Eğer ECHO5 1 konumundaysa ve sayaç belli bir değeri henüz geçmemişse sayacı arttır. Çünkü sen ECHO5'in 1 olduğu süreyi sayıyorsun. İki durumdan biri 0 ise zaten saymayı bırakman lazım. ECHO5 0 ise saymayı bırakman lazım çünkü sinyal zaten kesilmiş. sayac > 500 ise de saymayı bırakman lazım çünkü sayma limitine ulaşılmış. İstersen kullandığımız sensör kodunu atabilirim ama biz xc ile yazdık ve sensörün beslemesini gerektiğinde açıp kapatacak bir transistör kullandık.

Denizccan

trgtylcnky hocam

yorumunuz ışığında yanlış düşündüğümün farkına vardım kodu son olarak aşağıda belirttiğim şekilde değiştirdim ve şuan bu şekilde kullanıyorum bayağı deneme yaptım ses geri gelmese bile çalışıyor ama bir sıkıntı var benim istediğim bir hata olursa bana mesafeyi 2cm göstermesiydi bu yazdığım programda 218 gibi bir değer veriyor o değer nerden geliyor bir türlü bulamadım bende o değeri kabul ederek programın akışını değiştirdim.
Sizin bahsettiğiniz programıda gönderebilirseniz çok mutlu olurum ilgilendiğiniz için tekrar teşekkür ederim.

void olcum55() // sensör5 korumalı bır skılde okundu mesafe5 olarak atandı
   {
   koruma=1;
   output_high(trig5);            
   delay_us(15);              
   output_low(trig5);   
   while(!(input(ECHO5)))           
   {}   
   set_timer1(0);
   koruma=1;
   while(input(ECHO5) && koruma<2500)           
   {
   delay_us(2);
   koruma=koruma+1;
   }
   if(koruma<=2500)
   {
   zaman5=get_timer1();           
   mesafe5=(zaman5)/(290) ;
   }
   
   if(koruma>2500)
   {
   output_low(echo5);
   mesafe5=2;
   }
   
   }

trgtylcnky

Muhtemelen bahsettiğiniz koruma'nın asla 2500'den büyük olmamasından kaynaklanıyor. Alabileceği en yüksek değer 2500 çünkü 2500 olduğu zaman döngüden çıkmış oluyor. koruma>=2500 derseniz istediğiniz olabilir.

Bizim kod aşağıda. Sonsuz döngüye girmesini engellemek için yine Timer1'in aldığı değeri kullandık (TMR1H<8 yani Timer1'in en yüksek 8 biti 00001000'dan küçük yani Timer1 4096'dan küçük). Bir de biz sonucu cm'ye çevirmedik uS olarak bıraktık. Prescaleri de yanlış seçmişiz 4 uS'de bir sayıyor.

int sonic_oku_kutu(){

	T1CON = 0x20;
   	TMR1H = 0;                
   	TMR1L = 0;

    int counter=0;
    sonar_ac_kutu=1;  //sensör beslemesi açıldı
    __delay_ms(1);
    trig_kutu=1;  
    __delay_us(15);
    trig_kutu=0;
	 
	
    while(!echo_kutu) continue;         
    TMR1ON = 1;  
	while(echo_kutu && TMR1H<8)
	{
	  }         
	TMR1ON = 0; 
	counter = ((TMR1H<<8)+TMR1L);               

	sonar_ac_kutu=0;  //sensör beslemesi kapatıldı
	return counter*4;  //yanlış seçilen prescaler hatasını düzeltmek için
}

exjra

Yaşadığınız problem daha önce yaptığım deneylere göre algoritmanızdan değil sensörden kaynaklanıyor. Piyasada 2 çeşit HC-SR04 marka ultrasonik sensör bulunuyor. İkisini yan yana getirince birkaç görsel fark var göze çarpan. Aynı komponentleri kullanan ancak pcb çizimi farklı iki devre. Problemsiz kullanılan, dört köşesinde de vida deliği bulunan ve üzerindeki entegrede Rx piezosundan sinyal gelmediğinde gömülü algoritmayı resetleyen bir prosedür bulunan versiyon. Diğer problemli olan sensör ise çapraz iki köşesinde vida deliği bulunan ve Rx den sinyal almadığında kilitlenen versiyon. Problemi çözmenin yolu gömülü entegre içerisindeki algoritmayı resetlemek. Bunun için entegreyi inceleyip varsa reset (RST) pin'ini kullanmak gerek veya daha kolayı sensörün beslemesini bir anahtar üzerinden verip kendi algoritmanızda her okumadan önce enerjiyi kapatıp açmaktır (kilitlenme hali mi yoksa o anki mesafe bilgisi mi ayırt edemezsiniz mecburen her okumadan önce reset gerekir). P tip mosfet ile beslemeyi anahtarlayabilirsiniz. NPN tip bir transistör ile GND de anahtarlanabilir ancak tavsiye etmem.

burç tankal

İki gün önce ben de 4 yön mesafe tayini için sr04 sensörü kullanarak bir devre yaptım. ara sıra takıldığını gördüğümde bakmadığım yer kalmadı. sonra farkettim ki çıkan ses geri gelmeyince while döngüsünde sonsuz beklemeye giriyor. Aklıma gelen ilk çözüm watch dog timer kullanmak oldu. Hiç başka timer'lar ile uğraşmaya gerek yok. bekçi köpeğini 1/128 gibi bir ön bölücü ile kullanırsan yarım saniyede bir pici resetler. while komutunun hemen altında köpeği tekmelersin,   _asm clrwdt _endasm her bir başa dönüşte tekmelediğin için reset atamaz. ama program takıldığın anda reset gerçekleşir. En kolay ve kısa yolu budur bence.

Denizccan

exjra hocam sensörleri o kadar araştırmama rağmen sizin söylediğiniz bilgiyi hiçbir yerde okumamıştım şaşırdım doğrusu. ilk verdiğim sipariş 4 delikli olanlardan gelmişti, sonradan verdiğim siparişte ise 2 delikli olanlardan gelmişti ve iki delikli olanlardan çalışırken ince bir ses geliyordu bende bir düşünmüştüm neden delik yapısı değişti ve ses geliyor diye ama görünüş  aynı olduğundan ve uzaklık verisi aldığımdan dolayı aldırış etmemiştim. ilk işim iki ayrı devre kurarak iki sensörü karşılaştırcam.

burç tankal hocam daha önce watch dog timer kullanmadım, az bir bilgiye sahibim o konuda. Serdar hocamın ccs kitabından hatırladığım kadarıyla PIC donanımsal yada yazılımsal takılmalarda kaldığında reset atmamıza yaradığını hatırlıyorum sadece herhangi bir takılma anında yani benim yaşadığım durumda program kaldığı yerden devam edermi yoksa en baştan mı başlar bilmiyorum doğrusu.

Ben sensörleri kullanarak kendi kendine park yapabilen bir oyuncak araç tasarladım bitirme projesi olarak. Projemi bitirdim ve okula teslim ettim 2 gün önce. Şimdi watch dog timer programda kaldığı yerden başladığını varsayarsak tekrar sensör okuma yapmaya çalışacak ama benim aracım engele çapraz konumda durduğundan istediği kadar tekrardan ölçüm yapmaya çalışsa bile yapamayacak bulunduğu konumdan dolayı. Ama benim mutlaka bir uzaklık verisi alıp ona göre aracı hareket ettirmem gerektiğinden watch dog timer kullanmak sorunumu çözmeyecek kanısındayım. Ben son yazdığım kodu kullanarak bitirdim projeyi. Araç okuma yapamadığı taktirde 218 sayısını alıyordum o sayıyı alıncada aracı küçük adımlarla hareket ettirerek konumu değiştirip çaprazlıktan kurtularak aracın işlem yapmasına imkan sağladım.Ama sizin söylediğiniz şeklide hemen deneyeceğim bu vesile ile watch dog timer konusu hakkında bilgi sahibi olurum cevap verdiğiniz için teşekkür ederim.

burç tankal

Hayır olur mu öyle şey, wdt resetleme işlemi gerçekleştiğinde program baştan başlatılır ve ilgili bayrak çekilerek kullanıcı bilgilendirir. Siz programın başında bu bayrağı sorgulayarak wdt reset gerçekleşip gerçekleşmediğini de tespit edebilirsiniz. Kullanımı da çok kolaydır. wdt açın, prescaler oranını belirleyin.daha sonra taşma oluşmadan önce sayacı sıfırlayın. program beklemeye girdiğinde, takıldığında, herhangi bir şekilde sayaç sıfırlama noktasına ulaşmadığında bekçi köpeğimiz programı resetleyerek en baştan başlatacaktır. Bu bekçi köpeği o kadar kullanışlıdır ki osilatör devrenizde bir sıkıntı oluşup pic'e puls gönderemese bile wdt kendi osilatörü ile saymaya devam ederek reset işlemini gerçekleştirip devrenizi kurtarmaya çalışır. Sizin devrenizde ise az önce bahsettiğim gibi herhangi bir sayma işlemi yapmadan sadece wdt bayrağını sorgulayıp aracınızı küçük hareketler ile kurtarabilirdiniz.Bayrak çekili ise sinyal geri gelmedi, o halde 2 cm sola git gibi bir algoritma ile yapılabilirdi.  ileriki projeler için aklınızın bir köşesinde bulunsun.

uzaylivolkan

Bendeki  sensör de de aynı sıkıntı vardı. Sensör takılma yapıyor. Sensörü resetlemesseniz  tekrar mesafe bilgisi alamıyorsunuz.Sensörüm arızalıdır diye düşünmüştüm, demek ki üretimi ilgili bir sıkıntı var.

burç tankal

Evet, modülün yapması gerek işi, yazılım ile bizim yapmamız gerekiyor. Ancak bahsettiğim gibi sorunun çözümü çok basit.

baran123

Soru : 2 tane bu sensörden olsa birini normal birini dikey koysak.Bunları motor üzerine sabitleyip ikisinide belirli hızda döndürsek(aynı hızda) 3 boyutlu sonar yapabilir miyiz. ? :D

mesaj birleştirme:: 16 Haziran 2015, 20:48:15

Tabi matematiksel işlemler ile 3 boyutlu bir şekil tespit etmeye yarar mı bu modüller ?