PIC ten PIC e Radyo Frekans ile Veri Aktarımı [ÇÖZÜLDÜ]

Başlatan PIC16F, 01 Eylül 2016, 16:54:33

PIC16F

Elimde 2 adet PIC16F628A var.

Yapmak istediğim şey; 433 mhz'lik RX ve TX kullanarak iki pic arası bağlantıyı sağlamak. Bir pic'ten veri gönderilecek ve diğer pic bu veriyi alıp veriye göre led'i yakacak veya söndürecek.

Ancak başaramadım. İnternette de çok araştırdım ancak çözüm bulamıyorum.

Programlama dili olarak Mikro C kullanıyorum.

Proteus olmadığı için elle çizdim : http://i.stack.imgur.com/qw5Cy.jpg (Not : TX pini 8 olacaktı yanlış yazmışım.)
Kullandığım transmitter ve receiver : http://rayshobby.net/cart/433-rf

Kodlar...

Verici :



void main() {

     trisb = 1;
     portb = 0;
     cmcon = 7;

     UART1_Init(9600);
     delay_ms(1000);

     while(1){
              UART1_Write_Text('a');
              delay_ms(1000);
              UART1_Write_Text('b');
              delay_ms(1000);
     }

}




Alıcı :



void main() {

     trisb = 1;
     trisa = 0;
     portb = 0;
     porta = 0;
     cmcon = 7;

     UART1_Init(9600);
     delay_ms(100);
     while(1){

              if(UART1_Data_Ready()){
                     if(UART1_Read() == 'a') porta.b1 = 1;
                     if(UART1_Read() == 'b') porta.b1 = 0;
              }

     }

}




Düzenleme


Sorun çözüldü; teşekkürler...
Meğerse transmitter a anten bağlamak gerekiyormuş.
Transmitter ın sağ üst köşesinde bir delik var.
Oraya bir jumper kablo soktum; çalıştı.
O deliğe parmağımla dokununca da aynı etkiyi yapıyor.
Fakat uzak mesafe için anten gerekiyor...
Fakat dip dibeyken parmak ucu ya da bakır tel, kablo vb. yeterli.

Şu kodlar güzel çalışıyor (https://mikrodunya.wordpress.com/2011/11/08/udea-nin-rf-veri-iletimi-alanindaki-kucuk-devleri-atx-34-nrx-34/ adresinden alıntıdır):
Alıcı:
char az,i=0, msg[6];
void main()
{
UART1_Init(2400);
trisb.f0=0;
portb.f0=1;
delay_ms(100);

while(1)
         {
          if(UART1_Data_Ready())
          {
           msg[i]=UART1_Read();
           if(msg[0]=='y' || msg[0] == 's')//Eğer msg[0] 'y' veya 's' ise i değişkeninin 1 arttır.
                                           {
                                            i++;
                                           }
          }
          if(i==3)
                  {
                   if(msg[0]=='y' && msg[1]=='a' && msg[2]=='n' )portb.f0=1;  //Senkron için gönderilen sıfır veya 255 aranmaz....
                   if(msg[0]=='s' && msg[1]=='o' && msg[2]=='n' )portb.f0=0;
                   i=0;
                   msg[0]=0;

                  }
         }
}


Verici:
char pre[15]={'U','U','U','U','U',255,255,255,255,255,0,0,0,0,0};
char yak[3]={'y','a','n'};  //Senkron için en az bir byte sıfır gönder kesinlikle.....
char son[3]={'s','o','n'};
char i=0,j=0;

void kurulum()
{
UART1_Init(2400);
trisb.f0=1;
Delay_100ms();

}

void main()
{
kurulum();
while(1)
       {
         if(portb.f0)
         {
          for(i=0;i<15;i++)
                           {
                            UART1_Write(pre[i]);
                           }
          for(j=0;j<10;j++)                   //garanti olması açısından 10 kez gönderiliyor veriler...
          {
                          for(i=0;i<3;i++)
                          {
                           while(!UART1_Tx_Idle());
                           UART1_Write(yak[i]);
                          }
          }
         }

          //*************************************************************
         if(!portb.f0)
         {
          for(i=0;i<15;i++)
                           {
                            UART1_Write(pre[i]);
                           }
          for(j=0;j<10;j++)
          {
                         for(i=0;i<3;i++)
                         {
                          while(!UART1_Tx_Idle());
                          UART1_Write(son[i]);
                         }
          }
         }
       }
}



oguztkn

Alıcı tarafında 'a' diye sorgulamışsın ama haberleşmede karakterler ASCII olarak gönderiliyor olabilir  alıcı tarafında 'a' değilde 170 mi diye sorgula bakalım çalışacak mı?   (a karakterinin ascii karşılığı 170)

ete

PORTB.1 pini RX pini olup bu pinin giriş olarak atanması gerekir. Sen ise PORTB.0 pinini giriş olarak atamışsın her iki programda.
TRISB=1 demek TRISB registerine desimal olarak 1 değerini vermek anlamına gelirki bunun binary karşılığı TRISB=%00000001 şeklindedir.
Bu hatanın düzeltilmesi için binary olarak TRISB=%00000010 vermen yada desimal olarak TRISB=2 vermen gerekir.

Ete

PIC16F

Alıntı yapılan: ete - 01 Eylül 2016, 20:09:10
PORTB.1 pini RX pini olup bu pinin giriş olarak atanması gerekir. Sen ise PORTB.0 pinini giriş olarak atamışsın her iki programda.
TRISB=1 demek TRISB registerine desimal olarak 1 değerini vermek anlamına gelirki bunun binary karşılığı TRISB=%00000001 şeklindedir.
Bu hatanın düzeltilmesi için binary olarak TRISB=%00000010 vermen yada desimal olarak TRISB=2 vermen gerekir.

Ete

Hocam,
Önce RX kodunda trisb = 2 yaptım işe yaramadı. Ardından TX kodunda da trisb=2 yaptım o da işe yaramadı.

PIC16F

Alıntı yapılan: OgUz - 01 Eylül 2016, 18:21:27
Alıcı tarafında 'a' diye sorgulamışsın ama haberleşmede karakterler ASCII olarak gönderiliyor olabilir  alıcı tarafında 'a' değilde 170 mi diye sorgula bakalım çalışacak mı?   (a karakterinin ascii karşılığı 170)

ASCII karşılığını denedim, işe yaramadı.

PIC16F

#5
Ledi yakmayı başardım fakat bu sefer de benim istediğim şekilde yanmıyor...
Bahsettiğim sorun sanırım pilin düşük güçte olmasından kaynaklanıyordu.
Başka pillerle çalışıyorum şu an.

Yeni receiver kodu:
char x;
void main() {

     trisb = 0xFF;
     trisa = 0;
     trisa.b5 = 1; //MCLR pini için
     cmcon = 7;
     porta = 0;
     porta.b5 = 1;

     UART1_Init(9600);
     delay_ms(100);

     while(1){

              if(UART1_Data_Ready()){

                  x = UART1_Read();

                  if (x == 'a') porta.b1 = 1;
                  if (x == 'b') porta.b1 = 0;

              }

     }

}


Yeni transmitter kodu:
void main() {

     trisb = 0xFF;
     trisa = 0;
     trisa.b5 = 1; //MCLR
     porta = 0;
     porta.b5 = 1; //MCLR

     cmcon = 7;

     UART1_Init(9600);
     delay_ms(100);


     while(1){
              UART1_Write_Text("a");
              delay_ms(1000);
              UART1_Write_Text("b");
              delay_ms(1000);

     }

}


Bu kodlara göre ledin 1 saniye yanıp, 1 saniye sönmesi gerekiyor.
Fakat öyle olmadı; daha çok receiver a bağlı kablolarla oynadıkça led yanıp/sönmeye başladı.
Bazen de durup dururken bunu yapıyor...
Fakat transmitter devresi kapalı da olsa, receiver devresindeki led kendi kendine yanıp sönüyor.
Belirli bir yanıp sönme şekli yok, kafasına göre...

karacan451

#6
char x;
void main() {

     trisb = 0xFF;
     trisa = 0;
     trisa.b5 = 1; //MCLR pini için
     cmcon = 7;
     porta = 0;
     porta.b5 = 1;

     UART1_Init(9600);
     delay_ms(100);

     while(1){

              if(UART1_Data_Ready()){

                  x = UART1_Read();

                  if (x == 'a')
                  porta.b1 = 1;
                  else
                  porta.b1 = 0;

         
}

     }

}



Ben daha önceden micro c uğraşmıştım. Açıkçası bu programı beğenmedim. Çünkü kullanılan kodlar açık kaynaklı değil ve şöyle kod yazdğımda

if (buton=1) porta.b1 = 1;
if (buton=0) porta.b1 = 0;

ledler kararsız çalışmaya başladı.Bu olaydan sonrası micro c kullanmadım.

http://s9.dosya.tc/server/d69hax/MikroC_ve_PIC18F4550.rar.html


ete

Bir konuyu iyi öğrenmen gerekiyor.
Haberleşmede veri yollama (TX) pini çıkış olarak ayarlanır ve o pinden veriyi dış ortama yollarsın.
Dış ortamdan gelen veriyi alan (RX) pini ise giriş olarak ayarlanır. Bu giriş çıkışları ayarlayan register TRIS registerleridir.
USART modül yani donanımsal seri port standart pinleri PORTB de olduğu için sen PORTB yi kullanıyorsun. PORTB.1 senin RX pinin ve bu pin giriş olarak ayarlanmalı. PORTB.2 pini ise senin TX pinin olup buda çıkış olarak ayarlanmalıdır. TRISB registeri bu giriş çıkışları ayarlayacağına göre, Çıkış olarak ayarlanacak pin bit karşılığı 0(sıfır) olmalı, giriş olarak ayarlanacak pinin bit karşılığı ise 1 olmalıdır. Bu durumda son programlarına bakarsan TRISB=0XFF demişsin. Bu bütün B portunun giriş olarak ayarlanması anlamına geliyorki bu durumda senin alıcı sistemin çalışmayacak demektir.
Doğru değer her zamanki gibi TRISB=2 şeklinde olacaktır.

Ete

PIC16F

#8
Alıntı yapılan: ete - 02 Eylül 2016, 12:12:07
Bir konuyu iyi öğrenmen gerekiyor.
Haberleşmede veri yollama (TX) pini çıkış olarak ayarlanır ve o pinden veriyi dış ortama yollarsın.
Dış ortamdan gelen veriyi alan (RX) pini ise giriş olarak ayarlanır. Bu giriş çıkışları ayarlayan register TRIS registerleridir.
USART modül yani donanımsal seri port standart pinleri PORTB de olduğu için sen PORTB yi kullanıyorsun. PORTB.1 senin RX pinin ve bu pin giriş olarak ayarlanmalı. PORTB.2 pini ise senin TX pinin olup buda çıkış olarak ayarlanmalıdır. TRISB registeri bu giriş çıkışları ayarlayacağına göre, Çıkış olarak ayarlanacak pin bit karşılığı 0(sıfır) olmalı, giriş olarak ayarlanacak pinin bit karşılığı ise 1 olmalıdır. Bu durumda son programlarına bakarsan TRISB=0XFF demişsin. Bu bütün B portunun giriş olarak ayarlanması anlamına geliyorki bu durumda senin alıcı sistemin çalışmayacak demektir.
Doğru değer her zamanki gibi TRISB=2 şeklinde olacaktır.

Ete

Receiver ve transmitter picleri birbirinden bağımsız iki devre olarak çalışıyor (rf modüllerle).
Bu durumda receiver pic inin RX pinini giriş,
transmitter pic inin TX pinini çıkış olarak ayarlayacağım.

Yoksa her ikisini de trisb = 2 mi yapmalıyım ?

receiver ı trisb = 2, transmitter ı trisb = 0 yapıp denedim yine olmadı.
En son yazdığım sonucun aynısını aldım...


Alıntı yapılan: karacan451 - 02 Eylül 2016, 11:44:09
char x;
void main() {

     trisb = 0xFF;
     trisa = 0;
     trisa.b5 = 1; //MCLR pini için
     cmcon = 7;
     porta = 0;
     porta.b5 = 1;

     UART1_Init(9600);
     delay_ms(100);

     while(1){

              if(UART1_Data_Ready()){

                  x = UART1_Read();

                  if (x == 'a')
                  porta.b1 = 1;
                  else
                  porta.b1 = 0;

         
}

     }

}



Ben daha önceden micro c uğraşmıştım. Açıkçası bu programı beğenmedim. Çünkü kullanılan kodlar açık kaynaklı değil ve şöyle kod yazdğımda

if (buton=1) porta.b1 = 1;
if (buton=0) porta.b1 = 0;

ledler kararsız çalışmaya başladı.Bu olaydan sonrası micro c kullanmadım.

http://s9.dosya.tc/server/d69hax/MikroC_ve_PIC18F4550.rar.html

Bahsettiğiniz "kararsız" çalışma olayının aynısını şu an yaşıyorum ve transmitter devre dışı bile olsa yine led yanıp sönebiliyor...
Havadaki verileri mi yakalıyor diyeceğim, o da mantıklı gelmiyor...
Etrafta başka 433 mhz transmitter olmasa gerek.

ete

Verdiğim bilgi pin bazındadır. Dolayısıyla her iki programda da trisb=2 verilmelidir.
Ete projelerinde örnek proje var RF-_Termometre  iki pic arasında usart kullanarak sıcaklık aktarımı yapar. Kolaylıkla butonlu sisteme çevrilebilir. Ama ne yazıkki mikroC ile uğrsşıyorsun.
Ete

PIC16F

#10
trisb=2 verdim.

Şimdi durumu tam olarak özetleyeyim:
Receiver çalışıyor.
Fakat transmitter kapalı iken de çalışıyor.
Havadan geçen diğer 433MHz sinyallerle karışıp receiver a veri gittiğinden şüpheleniyorum...

Transmitter devredeyken, aşağı yukarı 1 saniye aralıklarla led yanıp sönüyor.
Fakat kararsız çalışıyor.
Bazen 500 ms aralıkla yanıp sönüyor.
Bazen 2 saniye aralıkla.
Bazen 1 saniye vb. vb...

Ha bir de her iki devreyi de kapatıp 10-15 dk bekledim.
Her ikisini de tekrar çalıştırınca led 1-2 dakika sonra yanıp sönmeye başladı.

Manchester kodlama kullanırsam bu karışıklığı giderebilir miyim ?
Cevap evetse; bu kodlamayı nasıl kullanırım ?

ete

Veri denilen şey bir rakamsal değerdir ama bitlerden oluşur. Aynı bitleri Reciverin çıkışıda parazit olarak üretir ve Usart'ı kandırabilir. Bu nedenle veri yi bir paket şeklinde oluşturmak gerekir.
Şayet vericiden bir "a" bilgisi yollayacak isem bunun önüne bildiğim bir işaretçi eklerim. Mesela "ETE" gibi.
Bu durumda senin veri şöyle gözükür ETEa, b gönderirkende benzer şekilde ETEb gönderilir.
ALıcıya da şöyle talimat veririm Önce ETE bekle bulursan peşinden gelen tek byte'ı al. Değilse bir şey alıpda yanlış alarm verme. Bu durumda ETE ardından a veya b bilgisi gelirse alıcı bilgi alıp program da bunu değerlendirir.
Senin programında güya a veya b bekleniyor ama ne gelirse değerlendiriliyor. Tabiiki bir de ideal olanı USART kesmesi kullanmaktır. Programından bu işi o derleyici nasıl yapıyor anlayamıyorum maalesef.

Manchester kodlama belki sorununu çözer ama emin değilim. Zahmetli bir iştir. Bu sitede bir örnek yayınlamış idim. Hatta algoritma çalışması yapmıştık.
Aşağıdaki linki inceleyiver.
http://etepic.com/index.php/topic,1776.msg17919.html#msg17919
Ete

PIC16F

#12
USART fonksiyonu mikroc  ile kullanılabiliyor mu ?

Düzenleme:
Şu kodları kullandım fakat çalışmadı:
Receiver:
char *mesaj;
char x;
int sayac= 0;

char *KOD = "MIKROCETE_";

void main() {
   TRISB = 2;
   TRISA = 0;
   PORTA = 0;

   while (1){
         if (UART1_Data_Ready()){
            porta.b0 = 1;
            x = UART1_Read();
            mesaj += x;
            if (sayac == 1){
               if (x == 'a') porta.b1 = 1;
               if (x == 'b') porta.b1 = 0;
            }
            if (strcmp(mesaj, KOD) == 0){
               sayac=1;
            } else if (!strstr(KOD, mesaj)){
              mesaj = "";
            }
           
           
           
         } else porta.b0 = 0;
   }

}


Transmitter:
void main() {
     TRISB = 2;

     TRISA = 0;
     TRISA.B4 = 1; //buton için
     TRISA.B7 = 1; //buton için
     PORTA = 0;
     
     while (1){
           if (porta.b4 == 1){ //buton kontrolü
              porta.b0 = 1; //kontrol Ledi
              porta.b1 = 0; //kontrol Ledi
              UART1_Write(0x55);  //uyandırma kodları on
              UART1_Write(0x55);
              UART1_Write(0x55);
              UART1_Write(0x55);
              UART1_Write(0x55);
              UART1_Write(0x00);
              UART1_Write(0x00);
              UART1_Write(0x00);
              UART1_Write(0x00);
              UART1_Write(0x00);
              UART1_Write(0xFF);
              UART1_Write(0xFF);
              UART1_Write(0xFF);
              UART1_Write(0xFF);
              UART1_Write(0xFF);  ////uyandırma kodları off
              UART1_Write_Text("MIKROCETE_a");
           } else porta.b0 = 0;
           
           if (porta.b7 == 1){ //buton kontrolü
              porta.b1 = 1;
              porta.b0 = 0;

              UART1_Write(0x55);  //uyandırma kodları on
              UART1_Write(0x55);
              UART1_Write(0x55);
              UART1_Write(0x55);
              UART1_Write(0x55);
              UART1_Write(0x00);
              UART1_Write(0x00);
              UART1_Write(0x00);
              UART1_Write(0x00);
              UART1_Write(0x00);
              UART1_Write(0xFF);
              UART1_Write(0xFF);
              UART1_Write(0xFF);
              UART1_Write(0xFF);
              UART1_Write(0xFF);  ////uyandırma kodları off
              UART1_Write_Text("MIKROCETE_b");
           } else porta.b1 = 0;
     }
}


ete

Mikro-C bilsem anlardım ama maalesef bilemiyorum.
Ete

karacan451


İşlemcinin sigorta ayarlarını yaptın mı micro c programında. Belki de sigorta ayarlardan kaynaklanıyordur. Devreyi simülasyon programda dene.

Powered by EzPortal