CCS-C Encoder okuma ve seri iletişim

PICF16877'de CCP portu sanıyorum 2 adet var, ben 3 adet motor için bu dediklerinizi bir pic16f877 üzerinde yapabilir miyim? Yoksa compare modunu program içinde halledip
(yani if (pals=x) { motor = 0 ); } gibi yazıp sadece giriş çıkış pinlerini kullansam olur mu ?
tek pikten yazılım emulasyonu ile yapmanız da mümkün. Ancak CCP 2 adet olduğu için 3. pwm çıkışını emule etmeniz biraz zor olur. Çok zaruri değil ise 24 serisi picler işinizi daha kolay görür. 2den fazla pwm modülü olan mculara da bakabilirsiniz.

puls sayma işini portb durum değişikliği kesmesine ait flagini (bayrağını) kontrol ederek kesmesiz de kullanabilirsiniz. 3 takodan gelen uçları, voltajlarını ve sinyal formlarını 5V, kare dalga haline getirerek b4-b7 arası bacaklara bağlayabilirsiniz. Sinyal seviyesindeki durum değişikliklerinde hangi bacaktaki değişti ise (önceki değeri ile kıyaslayarak) ilgili takoya ait sayacı bir arttırabilirsiniz. Daha sonra da puls değerlerine ve nihayet hedef puls değerlerine ulaşıp ulaşmadığınıza bakabilirsiniz.

Ben bir adet motor için bir adet mcu kullanacağınızı düşünerek compare modundan bahsetmiştim. Üçünü bir arada kullanacaksanız yazılım emulasyonu ile yapın.

Bu arada size hız gerekli olabilir. Özellikle daire çizdirme işini mcuya yükleyecekseniz. Yüksek MIPS değerli olan mcular size avantaj sağlar.

Örneğinizde kullandığınız değişkenleri ne amaçla kullandığınızı bilmediğim için tam anlayamadım. Siz aklınızdan geçen mantığı yazılıma dökün. Hatalar için yardımcı oluruz inşaallah.
 
Sorununuz kesmelerle ilgili değil. Gelen bilgiyi alma ile ilgili. Kesme rutininde gets() fonksiyonu ile değil getc() fonksiyonu ile bilgileri birer birer alıp ana programa döneceksiniz.Yalnız her aldığınız bilgiyi öyle saklayacaksınız ki, gelen bilgi tamam olduğunda (değişken boyutta bilgi ise atıyorum \n karakteri geldiğinde) sakladığınız bilgilerden orjinal bilgiyi elde etmelisiniz. eğer gelen bilgiler sabit sayıda ise (atıyorum 2 bayt ise) ilk gelen bilgiyi aldığınızda bilgi sayacı 0 ise 1 yapın, ikinci gelende (bilgi sayacı 0 dan farklı olduğu için) bu sayacı +1 yapın. Tabi bu arada gelen bilgileri bir dizi içerisine (indisi sayaçla gösterin) saklayın. Toplam gelecek bayt sayısına ulaştığınızda sayacı sıfırlayın. Dizideki bilgileri işleyin. Birer birer bayt okuma işleminde kesmeye gidip gelme zamanı size göre çok çok kısadır (bana göre çok uzun sayılır).

Anladım hocam, yani gets yerine getc kullanırsan kesme içinde daha az zaman geçer diyorsununuz ve böylece kesmeyi disable etmeye gerek kalmaz.

Daha çok tercih ettiğinizi söylediğiniz kesmesiz gelen veriyi yakalamayıda deneyeceğim.
 
puls sayma işini portb durum değişikliği kesmesine ait flagini (bayrağını) kontrol ederek kesmesiz de kullanabilirsiniz. 3 takodan gelen uçları, voltajlarını ve sinyal formlarını 5V, kare dalga haline getirerek b4-b7 arası bacaklara bağlayabilirsiniz. Sinyal seviyesindeki durum değişikliklerinde hangi bacaktaki değişti ise (önceki değeri ile kıyaslayarak) ilgili takoya ait sayacı bir arttırabilirsiniz. Daha sonra da puls değerlerine ve nihayet hedef puls değerlerine ulaşıp ulaşmadığınıza bakabilirsiniz.

Tam olarak yapmam istediğim algoritma bu, fakat elinizde flagin durumunun değişip değişmediğini kontrol eden kod parçası varmıdır ? Uğraştım ama yapamadım.

Yani şudur anladığım kadarıyla ;
Enkoderlerin palslarını pic'in b4-b7 uçlarına bağlıyorum. Ve enkoder pals saymaya başladığında benim sayacımda çalışıyor ?
 
Yani şudur anladığım kadarıyla ;
Enkoderlerin palslarını pic'in b4-b7 uçlarına bağlıyorum. Ve enkoder pals saymaya başladığında benim sayacımda çalışıyor ?
Burada donanımsal bir sayaç yok ve siz her üç puls kanalı için 3 ayrı sayacı yazılımla oluşturacaksınız. Flag için datasheete bakın. Yani portb kesmesi hangi interrupt ile aktifleniyor ise o kesmeye ait flag interrupt ayarlanmış olsa da olmasa da portb deki durum değişikliğinde set eder (datashetten bakabilirsiniz, şu an bakamıyorum o nedenle söyleyemiyorum). Puls kanallarını tek tek kontrol ederseniz bayrak kendiliğinden sıfırlanmaz (değişimi bulduktan sonra kendiniz sıfırlayacaksınız) veya portu okutursanız ve okuttuğunuz portb bilgisi üzerinde çalışırsanız bayrak otomatik olarak sıfırlanır.
 
Evet yazılımla oluşturacağım doğrudur, fakat datasheette ;

"
bit 0 RBIF: RB Port Change Interrupt Flag bit
1 = At least one of the RB7:RB4 pins changed state; a mismatch condition will continue to set the bit. Reading PORTB will end the mismatch condition and allow the bit to be cleared(must be cleared in software).
0 = None of the RB7:RB4 pins have changed state

böyle bir ifade var yani ;

port B 4,5,6,7 içinden en az birinin durumunda değişiklik olsa 1 veriyor. Bu durumda ayrı ayrı sayma yapamayacağım anlamına mı gelir ,enkoderlerden gelen sinyali programım sayma yapacak ama hangisini birinci motordan gelen sinyali mi, ikinciyi mi? hangi enkoder sinyalini saydığımı nasıl anlayacağım ?
 
port B 4,5,6,7 içinden en az birinin durumunda değişiklik olsa 1 veriyor. Bu durumda ayrı ayrı sayma yapamayacağım anlamına mı gelir ,enkoderlerden gelen sinyali programım sayma yapacak ama hangisini birinci motordan gelen sinyali mi, ikinciyi mi? hangi enkoder sinyalini saydığımı nasıl anlayacağım ?
Öncelikle bir hatamı düzelteyim. Portb yi okumakla otomatik olarak bayrak sıfırlanıyor diye yazmıştım. Hatalı olmuş. Portb yi okumakla yeni bir durum değişimi tespit edilebilir hale geliyor. Yoksa portu okutmazsanız durum değişikliklerini daha tespit edemez mcu. Yanlış hatırlamıyorsam CCS de otomatik sıfırlanıyordu.

Siz portb yi okuduktan sonra <4:7> bitlerinden hangisinin durumunun değiştiğini tespit edeceksiniz,ondan sonra o bite karşılık gelen bacağa bağladığınız encoderdan puls geldiğini veya bir sonraki seferde puls geleceğini anlayacaksınız. Yeni bir puls atıyorum b6 bacağından geldi ise, atıyorum mot2_enc_cnt++; diyeceksiniz. Bu sizin ikinci motor takosundan gelen pulsları saymanıza yardımcı olacak. Aynı şekilde diğer bitlerde de aynı anda puls geldiğini anlamış iseniz o encoderların da sayaçlarını bir arttıracaksınız. Daha sonra referans sayılara ulaşıp ulaşmadığınızı kontrol edeceksiniz.
 
Önceden yapmış olduğum programı ekledim aşağıya ama doğru çalışmıyor ,proteusta devreyi denediğimde palse göre sayım yapmadığını gördüm. (proteusta osiloskoptan baktım ) Ve ,aynı referans değerini vermeme rağmen 3 motor da aynı anda durmuyor. Aralarında küçük zaman farkları oluşuyor. Bunun nedeni nedir ?
Bu ınterrupt flagini okuma ve sıfırlama ile ilgili kod konusunda yardımcı olabilir misiniz , internette bulamadım bununla ilgili bilgi. Teşekkürler

PIC C Compiler'de hazırladığım saydırıcı program ;

Kod:
#include<16f877.h>
#fuses xt,nowdt,noprotect,nobrownout,nolvp,noput,nowrt,nodebug,nocpd
#use delay(clock=4000000)
#use fast_io(b)
#use fast_io(a)
#use fast_io(e)

#define enc1 pin_b4 //1.MOTOR ENKODER GİRİŞİ
#define enc2 pin_b5 //2.MOTOR ENKODER GİRİŞİ
#define enc3 pin_b7 //3.MOTOR ENKODER GİRİŞİ


#define motor1yon1 pin_a0 //MOTOR 1 L298 çıkışı + yöne
#define motor1yon2 pin_a1 //MOTOR 1 L298 çıkışı - yöne
 
#define motor2yon1 pin_a2 //MOTOR 2 L298 çıkışı + yöne
#define motor2yon2 pin_a3 //MOTOR 2 L298 çıkışı - yöne

#define motor3yon1 pin_e0 //MOTOR 3 L298 çıkışı + yöne
#define motor3yon2 pin_e1 //MOTOR 3 L298 çıkışı - yöne

char t=10;
int16 say1=0,say2=0,say3=0;  // say1,say2,say3 sayaç parametrelerim

void main()
{   
   set_tris_b(0xB0);     
   set_tris_a(0x00);
   set_tris_e(0x00); 
   
   output_high(motor1yon1);
   output_low(motor1yon2);
   
   output_high(motor2yon1);
   output_low(motor2yon2);
   
   output_high(motor3yon1);
   output_low(motor3yon2);
   
while(1)
{
if (input(enc1))  //1 nolu enkoder
{
delay_ms(t);
say1++;

  if (say1==500){
      output_low(motor1yon1);
      output_low(motor1yon2);
  } }
if (input(enc2))  //2 nolu enkoder
{
delay_ms(t);
say2++;
  if (say2==500){
      output_low(motor2yon1);
      output_low(motor2yon2);
  } }
if (input(enc3))  //3 nolu enkoder
{
delay_ms(t);
say3++;
  if (say3==500){
      output_low(motor3yon1);
      output_low(motor3yon2);
  }

}
}
}
 
Sürekli bacak durumunu okuyup ona göre işlem yapmayacaksınız. while döngüsünde rbif 1 oldu mu diye bakacaksınız. Eğer 1 olduysa, bu durumda portb yi okutup tek tek bacakların durumunu, bir önceki durumla karşılaştıracak, bir öncekinde 1 olup şimdi sıfıra inenleri dikkate almayacak, önceki sıfır olupta şimdi 1 olanların sayaçlarını bir arttıracaksınız. rbif yi de sıfırlayacaksınız. Sonra sayaçlarınızı referans değerleri ile karşılaştıracaksınız.

Programınızı ve isis simulasyonunu gönderebilirseniz birlikte bakabiliriz. Yalnız size hemen cevap veremeyebilirim. Müsait olduğumda da zaten gerekli yardımı yaparım.
 
ze_tr hocam selamlar.

Tavsiye ettiğiniz şekilde gelen karakterleri tek tek okutmayı deniyorum, rda kesmesinde bunu başardım ancak kesme kullanmadığımda isiste doğru sonuçlar alamıyorum.

Kod:
#int_rda   // RX ucuna veri gelince meydane gelen kesme
void serihaberlesme_kesmesi() {   
 
 girdi=getch();
 rakam_say++;
  
 if(strlen(s1)==0)
  s1[0]=girdi;
 else if(strlen(s2)==0)
  s2[0]=girdi;
 else if(strlen(s3)==0)
  s3[0]=girdi;
 
 if(girdi=='\r' || rakam_say==3){
   strcat(s1,s2);
   strcat(s1,s3);
     
   git=atol(s1);
   delay_ms(1);
      
   //printf("\n\rRakam: %Ld \n\r", git);

   s1[0]="";
   s1[1]="";
   s1[2]="";
   s1[3]="";
         
   s2[0]="";
   s2[1]="";
   s2[2]="";
   s2[3]="";
         
   s3[0]="";
   s3[1]="";
   s3[2]="";
   s3[3]="";
   
   rakam_say=0;}
}

Bu kullanımda Enter'a basıldığında (isis'de Enter'i '\n' şeklinde algılamıyor, bu yüzden '\r' kullandım) yada girilen değer 3 basamaklı olduğunda git değişkenine doğru değer ataıyor.

Ancak ben bu kod obeğini örneğin oku() diye bir yordama taşıyıp ana döngüde

Kod:
if(input(pin_c7))
 oku();

şeklinde c7 pinine bilgi geldiğinde okuma yapmak istediğimde kod doğru çalışmıyor.

Bunun sebebi ne olabilir hocam?
 
Porta gelen bilgi c7 kontrol edilerek anlaşılmaz. Porta gelen bilgi receive buffer interrupt flag (rbif) 1 olunca anlaşılır. zaten kesmesi aktif ise rbif kesmeyi tetikler. siz if(rbif) oku(); yapacaksınız. rbif yi getenv(bit....) ile tanımlayabilirsiniz. Pardon, sizin tanımlamanıza ve kullanmanıza gerek yok. KbHit() fonksiyonu zaten doğrudan ona bakıyor. Yani KbHit() diye çağırdığınız kod rbif nin ta kendisidir. if(KbHit()) oku(); yazmanız gerekir.

portb durum değişimi için yanlışlıkla rbif diye yazmışım. onun flagi farklı.

seri porttan okuttuğunuz şey nedir? Ya da seri porta ne gönderiyorsunuz? Sayı ise kaç baytlık sayı?

Edit: aynı başlıkta iki farklı konu olunca bazı anlattığım şeyler karışabilir. siz sizinle ilgili olanlarını alın.
 
Son düzenleme:

Forum istatistikleri

Konular
129,845
Mesajlar
930,719
Kullanıcılar
452,697
Son üye
ozgurmaker

Yeni konular

Geri
Üst