Buton kontrollu sonsuz donguler.

Başlatan makinahmet, 13 Ocak 2013, 01:33:11

makinahmet

Merhaba.Herkese iyi akşamlar.
Ben bir butonla ledleri çeşitli şekilde yakıp sondüren bi program yazmak istedim.
Butona birinci kez basılınca (ikinci kez basılana dek) sürekli olarak belli şekilde yanıp sönecekler.
Butona ikinci kez basılınca (üçüncü kez basılıncaya dek) sürekli olarak belli şekilde yanıp sönecekler.
üçüncü defa basıldığında sürekli yanacak.(bunda problem yok zaten  :) )
Fakat birinci kez butona basıldığında while döngüsüne giriyor ve butona ikinci defa basıldığında döngüden çıkmıyor(çünkü döngü sonuz.)
Butona her basıldığında bu sonsuz döngüleri sonlandırmanın bir yolu varmıdır acaba?

Yazdığım kodlar bunlar.


#define led1 output_high(pin_b0)
#define led2 output_high(pin_b1)
#define led3 output_high(pin_b2)
#define led4 output_high(pin_b3)
#define bekle50  delay_ms(50)
#define bekle100 delay_ms(100)
#define bekle250 delay_ms(250)
#define b_portu_cikis set_tris_b(0x00)
#define a_portu_giris set_tris_a(0x01)
#define led_hepsi_off output_b(0x00)
#define buton_basildi input(pin_a0)

int btsyc=0;
void main()
{

a_portu_giris;
b_portu_cikis;
led_hepsi_off;


while(1)
{
  if(buton_basildi)
  {
  btsyc++;
  while(buton_basildi);

     if(btsyc == 1)  //butona 1 kez basildi
     {
     while(btsyc = 1){
     led1;
     bekle100;
     led_hepsi_off;   
     
     led2;
     bekle100;
     led_hepsi_off;
   
     led3;
     bekle100;
     led_hepsi_off;
     }
     }
     
     if(btsyc == 2) //butona ikinci kez basildi
     {
     while(1)
     {
     led1;
     led2;
     led3;
     bekle250;
     led_hepsi_off;
     bekle250;
     }
     }
     
     if(btsyc == 3) //butona ucuncu kez basildi
     {
     led1;
     led2;
     led3;
     
     btsyc = 0; //butona basildi ve sayac sifirlandi while ile basa donduk
     }
  }
}
}

İyi çalışmalar.
DC, STEP, SERVO MOTOR -> www.sinematronik.com

mehmet

Yanıp-sönme olaylarını fonksiyon olarak
yap ve ana döngü içinde if ya da switch ile
basılan tuşa göre fonsiyona dallanma yaptır.

Saygılar...

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

codabas

do
{
     ledleri kontrol eden yazılım 1
     .
     .
     .
     .
}while(!input(pin_a1)); /* pin_a1'deki butona basılıncaya kadar dön. "BUTONA BASILINCA DÖNGÜDEN ÇIKAR.

do
{
     ledleri kontrol eden yazılım 2
     .
     .
     .
     .
}while(!input(pin_a1));


birde bunu dene bakalım...
Sakarya End. Meslek Lisesi Robot Klübü robotizm.net

makinahmet

@sayın cadabas bey Verdiğiniz öneri için çok teşekkür ederim. Dediğin gibi yazdım ama olmadı. Buton basılı tutulduğu zaman sürekli ledlerin yanıp sonme biçimi değişiyor  :)

@sayın mehmet bey sizede çok teşekkür ederim. Pic programlamaya yeni başladığım için daha fonksiyonlara geçmedim. Daha önceden php proğramlama ile uğraşıyordum.O yüzden ilk önce kontrol deyimlerini iyice öğrenmek istiyorum. Ancak fonksiyonlarında nasıl yazıldığına bakınca şöyle bi kod yazdım.

#define led1 output_high(pin_b0)
#define led2 output_high(pin_b1)
#define led3 output_high(pin_b2)
#define led4 output_high(pin_b3)
#define bekle50  delay_ms(50)
#define bekle100 delay_ms(100)
#define bekle250 delay_ms(250)
#define b_portu_cikis set_tris_b(0x00)
#define a_portu_giris set_tris_a(0x01)
#define led_hepsi_off output_b(0x00)
#define buton_basildi input(pin_a0)


int btsyc=0;

void dongu1(void)
{
while(btsyc=1)
 {
     led1;
     bekle100;
     led_hepsi_off;    
     
     led2;
     bekle100;
     led_hepsi_off; 
    
     led3;
     bekle100;
     led_hepsi_off; 
 }
}

void dongu2(void)
{
while(1)
 { 
     led1;
     led2;
     led3;
     bekle250;
     led_hepsi_off;
     bekle250;
 }
}

void dongu3(void)
{
while(1)
 { 
     led1;
     led2;
     led3;
 }
} 

void main()
{
a_portu_giris;
b_portu_cikis;
led_hepsi_off; 
 
while(1)
 {
   btsyc++; 
   while(buton_basildi);
   if(btsyc == 1)
   {
   dongu1();
   }
   if(btsyc == 2)
   {
   dongu2();
   }
   if(btsyc == 3)
   {
   dongu3();
   btsyc = 0;
   }   

 }


}


ancak bu kodda ilk fonsiyona -dongu1- girip fonksiyondan çıkmıyor :) yani main fonksiyonundan önce fonksiyonu işletiyor.diğer fonksiyonlarıda main için yazınca undefined identifier hatası veriyor.
DC, STEP, SERVO MOTOR -> www.sinematronik.com

codabas

butona basılı tutulduğunda ledlerin yanma biçimi değişiyorsa bu durum çok normal çünkü size verdiğim örnekte bu durumu göz önünde bulundurmadım. butonu bırakmanı bekleyen satırı eklemeniz durumunda sorun çözülür.
.
.
.
.
.
}while(!input(pin_a1));

while(input(pin_a1)); bu satırı eklemeniz durumunda program butonun bırakılmasını bekler.
do
{
Sakarya End. Meslek Lisesi Robot Klübü robotizm.net

makinahmet

@sayın codebase. Dediğiniz şekilde siz demeden denedim. Aslında bir çok koşul yapısını denedim.Döngü içi döngü kurdum.Ancak sizin dediğiniz yolla isiste olmayınca breadboardda kurmayı denedim devreyi. yazdığım proğramla isiste hiç bir led tepki vermezken. Board üzerinde kurduğum devrede ledled sürekli yanıyor :D Kodları kontrol ettim, bağlantıları kontrol ettim. Herşey yolunda gibi görünüyor. Belkide saat geç vakit diye farketmiyorda olabilirim. Yarın tekrar baştan yapacağım. Bu tür olumsuzluklar aslında iyi oluyor. Proğram yazarken hem hızlanıyorsunuz hemde syntax kurallarına  alışkınlık ediniyorsunuz  :)

Yeni yazdığım kod şu şekilde.
#define led1 output_high(pin_b0)
#define led2 output_high(pin_b1)
#define led3 output_high(pin_b2)
#define led4 output_high(pin_b3)
#define bekle50  delay_ms(50)
#define bekle100 delay_ms(100)
#define bekle250 delay_ms(250)
#define b_portu_cikis set_tris_b(0x00)
#define a_portu_giris set_tris_a(0x01)
#define led_hepsi_off output_b(0x00)
#define buton_basildi input(pin_a0)

void main()
{
a_portu_giris;
b_portu_cikis;
led_hepsi_off;

if(buton_basildi)
{
while(1){
do
{
led1;
bekle50;
led_hepsi_off;
bekle50;

led2;
bekle50;
led_hepsi_off;
bekle50;

led3;
bekle50;
led_hepsi_off;
bekle50;
}while(!buton_basildi);

while(buton_basildi);
do
{
led1;
led2;
led3;
bekle50;
led_hepsi_off;
bekle50;
}while(!buton_basildi);

while(buton_basildi);
do
{
led1;
led2;
led3;
}while(!buton_basildi);
}//while parantezi
}//if parantezi
}//main fonk parantezi


Hayırlı geceler. İyi çalışmalar.
DC, STEP, SERVO MOTOR -> www.sinematronik.com

makinahmet

#6
Evet dün akşam dediğim gibi bugün tekrar devreyi baştan kurdum ve kodları denedim. Dediğim gibi yine olumusuz sonuç aldım.Ancak yeni yazdığım kodla işin büyük bi kısmını hallettim gibi.

int btsyc=0;
void main()
{
a_portu_giris;
b_portu_cikis;
led_hepsi_off;


while(1)
{
if(buton_basildi){
btsyc++;
while(buton_basildi);
}
 if(btsyc == 1){
 led1;
 bekle50;
 led_hepsi_off;
 
 led2;
 bekle50;
 led_hepsi_off;

 led3;
 bekle50;
 led_hepsi_off;
 }
 
 if(btsyc == 2){
 led1;
 led2;
 led3;
 bekle50;
 led_hepsi_off;
 bekle50;
 }

 if(btsyc == 3){
 led1;
 led2;
 led3;
 }
 
 if(btsyc == 4){
 led_hepsi_off;
 btsyc=0;
 }

}//sonsuz while dongusu
}//main fonk parantezi


Ancak kod simulatör proğramda çalışırken, breadboard üzerinde hatalı çalışmakta  :o
board üzerinde:
Butona ilk basıldığında  if(btsyc==3) koşul ifadesi,
ikinci defa basıldığında  if(btsyc==1) koşul ifadesi,
üçüncü basıldığında ise if(btsyc==2) koşul ifadesi ve son olarakta;
dördüncü defa basıldığında if(btsyc == 4) koşul ifadesi çalışmakta.
Dikkat edilirse koddaki koşulların gerçekleşme koşulları ile board üzerinde meydana gelenler uyuşmamakta.Board bağlantılarına baktığımda ise herhengi bir problem görünmemekte.Ancak kodun doğru olduğunu düşündüğüm halde gerçekte koddaki gibi olayların olmaması kafamı karıştırmış durumda   ???

Bu arada sisteme enerji verildiği anda 3. koşul gerçekleşmekte. yani ledler hemen yanıyor.
DC, STEP, SERVO MOTOR -> www.sinematronik.com

mehmet

#7
Ana döngü içerisinde butona basıldığında
bir artacak değişken tanımla. Değişken
en fazla fonksiyon adedine ulaşınca
1 e eşitle ki birinci fonksiyona geri dönsün.
Örnek yazmaya çalısıyorum:
#include kısmı
#define tanımlamaları
.....
void f1(void)
{
   yak, söndür, bla bla;
}

void f2(void)
{
   yak, söndür, bla bla;
}

void f3(void)
{
   yak, söndür, bla bla;
}
....
....

int main(void)
{
   tanımlamalar ve başlanğıç değişkenleri;
   (fonksiyona dallandıracak değişken a olsun)
   unsigned int a = 1;//Eğer başlangıçta ilk fonksiyona gidecekse 1 değilse 0 yaparsın

   while(1)
   {
      if(butona basıldı mı) a += 1; basıldıysa a yı 1 artır
       //debounce kısmı buraya yazılacak
      if(a == max fonksiyon sayısıise) a = 1;
      switch(a)
      {
         case 1:
             f1();
             break;
         case 2:
             f2();
             break;
         case 3:
             f3();
             break;
         default:
              //mesela a 0 olduğunda burayı kullanacak yada boş kalabilir
         break;
       }
     }
}
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

makinahmet

@sayın mehmet bey.Çok teşekkür ederim. Dediğiniz gibi araştırdım ve sorunun debounce olduğunu gördüm. Mekaniksel butonlardan kaynaklanan bu hatayı kodlarla ve kondansatörlerle minimuma indirebiliyormuşuz.Butona her basıldığında farklı döngülere atlama sebebi, butona basıldığında tam olarak algılamamasıymış.Debounce olayının  kodlarla nasıl yazılacağı konusunda daha gelişme kaydedemedim. Ancak onuda araştıracağım tabi  :) Yeni bi kod yazdım ve buton kısmında araya bi kondansatör ekledim. Şimdi daha stabil  :) Bu arada fonksiyonlar ile çalışmanın pratikliği demekki sadece php diline özgü birşey değil.Sonuç olarak bu şekilde döngüyü elde etmiş olduk. Yardımlarınız için sayın CODEBAS bey ve Sayın MEHMET bey, teşekkür ederim.

Yazdığım kod ise şu
void dongu1(void)
{
     led1;
     bekle100;
     led_hepsi_off;    
     
     led2;
     bekle100;
     led_hepsi_off; 
    
     led3;
     bekle100;
     led_hepsi_off; 
}

void dongu2(void)
{
     led1;
     led2;
     led3;
     bekle100;
     led_hepsi_off;
     bekle100;
}

void dongu3(void)
{
     led1;
     led2;
     led3;
} 

int btsyc=0;
void main()
{
a_portu_giris;
b_portu_cikis;
led_hepsi_off; 
 
while(1)
 {
  if(buton_basildi)
  {
  //debounce engelleyecek kod
   btsyc++; 
   while(buton_basildi);
  }
  
   if(btsyc == 1)
   {
   dongu1();
   }
   if(btsyc == 2)
   {
   dongu2();
   }
   if(btsyc == 3)
   {
   dongu3();
   }   
   if(btsyc == 4)
   {
   led_hepsi_off;
   btsyc = 0;
   }
 }
}


İyi çalışmalar.Saygılar.
DC, STEP, SERVO MOTOR -> www.sinematronik.com

mehmet

Debounce için de;
if(butona basıldı mı) while(buton bırakıldı mı);
gibi bir satır ekleyebilirisin. Ya da basıldıktan
sonra belirli bir sayaç çalışır, belli sayıya yada
zamana (10ms,100ms gibi) ulaşıncaya
kadar beklenir. Sonra hala buton basılı haldeyse
butona basılmış sayılır. Değise butona basılmadı işlemi
yapılır.

Saygılar...

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

makinahmet

Hmm. Demekki debounce içinde "kontrol yapıları" veya belli bi zaman için "delay" kullanabiliyoruz. Bu konu hakkında pek türkçe kaynak yok ama bekleme süresininde 100ms olması uygun deniyor.Teşekkürler :)

İyi çalışmalar.
DC, STEP, SERVO MOTOR -> www.sinematronik.com

prtel08

Merhaba

Öncelikle ben PIC C ye yeni başladım. vermiş olduğunuz örneklere ekleme yaparak C öğrenmeye çalısıyorum.

Bu desteklerinizden dolayı önce bu siteye sonra siz değerli arkadaşlara  çok teşekkür ederim. Forma yeni üye oldum umarım ileride güzel projelerde paylaşmak nasip olur.

verdiğinizörneklerden yola çıkarak 1.Butona basılınca tanımladığım çıkışlar aktif olacak. İkinci butona bastığımda  Çıkışlar sıfırlanacak.

/****************************************************************************
Uygulama Adı:  DENEME 1
Programın Amacı: A0 BUTONA BASILDIĞINDA PORT B belirlediğim çıkışların yanması ve
A1 butonuna basıldığında tüm çıkışların sıfırlanması


*****************************************************************************/

#include <16f877.h>   //Kullanılacak denetliyicinin başlık dosyası tanıtılıyor.
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD //Denetliyicibi Konfigürasyon ayarları
#use delay(clock=4000000)  //Geçikme fonksiyonu için kullnılan osilatör frekansı belirtiliyor.

#use fast_io(b)       //Port yönlendirme komutları B port'u için geçerli

#define button1 pin_A0
#define button2 pin_A1



   int btsyc=0,ark=10,sure=50,sure1=100;      //delay değişkeni tanımlanıyor
   
   

/*********************ANA PROGRAM FONKSİYONU***********************/
 

void dongu1 (void)
{

output_high(pin_b0);
output_low(pin_b2);

}

void dongu2 (void)
{

output_low(pin_b0);
output_high(pin_b1);
}

void dongu3 (void)
{

output_low(pin_b0);
output_low(pin_b1);
output_high(pin_b2);
}




void main ()
{

   setup_psp (PSP_DISABLED);           //PSP birimi devre dışı
   setup_spi (SPI_SS_DISABLED);        //SPI birimi devre dışı
   setup_timer_1 (T1_DISABLED);        //T1 birimi devre dışı
   setup_timer_2 (T2_DISABLED,0,1);    //T2 birimi devre dışı
   setup_adc_ports(NO_ANALOGS);        //ANALOG giriş yok
   setup_adc(ADC_OFF);                 //ADC birimi devre dışı
   setup_CCP1(CCP_OFF);                //CCP1 birimi devre dışı
   setup_CCP2(CCP_OFF);                //CCP2 birimi devre dışı
   
   set_tris_A(0b00000011);          // RA0 giriş olacak
   set_tris_B(0x00);                // B portu çıkışolarak ayarlandı. 
   output_b(0x00);                  // Port B sıfırla
   
  
  while(1)                           // Etiket tanımlanır.
   {
   if (input(button1))               // buton1 basıldımı A0
    {
  btsyc++;                // sayacı 1 arttır
     while (input(button1));        // button1 bırakılana kadar bekle
     }
  
      if(btsyc==1)                  // Sayaç 1 e eşitmi?
      {
      delay_ms(sure1);
    dongu1();                       //dongu 1 çağır.
     }
    
      else                          //sayaç 1' eşit değilse 
      
      if(input(button2))            // Buton1 basıldı mı?
      {
      
      while (input(button2));       // buton2 bırakılana kadar bekle
    
      btsyc=0;                      // sayacı sıfırla
      output_b(0x00);               // port b sıfırla
      }
     
   if(btsyc==2)
   {
   delay_ms(sure1);
   dongu2();
   }
   else 
      
      if(input(button2))
      {
      while (input(button2));
      delay_ms(ark);
      btsyc=0;
      output_b(0x00);
      
      }
   
   if(btsyc==3)
   {
   delay_ms(ark);
   dongu3();
   }
 
 
  if(btsyc==4)
   btsyc=1; 
   delay_ms(ark);
   
   
   }
}





makinahmet

@prtel08 Merhabalar.
benim yazdığım komutlardaki temel hatam şuydu. Delay_ms() fonksiyonu devreye girdiğinde pic hiç bir iş yapmıyor. Ben ise delay ms süresi içersinde iken butona basarak komut değiştirmeye çalışıyordum. Oysaki ben botona bassam bile bu komutun süresinin bitmesi gerekiyormuş.Daha sonra kesme denen bi kavramla bunu hallettim :)

Bir alternatif olarak şöyle bir kodda yazılabilir.


while(1){


if(input(button1))    //buton 1 e basılırsa
{
btsycc ++;
while(button1);
if(btsycc == 1){bla bla}
if(btsycc == 2){bla bla}
if(btsycc == 3){bla bla}
}

if(input(button2))   //buton ikiye basılırsa
{
bla bla
}

}

Ne varsa ifle çözüyoz zaten  ;D switch case yapıları daha kısa zamanda yazılabilir halbuki.
iyi çalışmalar.
DC, STEP, SERVO MOTOR -> www.sinematronik.com

GRaFiT

Sorun çözüldü ise sıkıntı yok if olsun while olsun. Sonunda sonsuz döngüde takılıp kalmayalım da  8)
http://teknokoliker.com - Kişisel Web Sitem