16 Aralık 2018, 14:37:19

Haberler:

Forum kuralları güncellendi LÜTFEN  okuyunuz:  https://bit.ly/2IjR3ME


GSM Modül Kullanım Hakkında

Başlatan saybatli, 10 Ekim 2018, 12:43:37

saybatli

Merhaba Arkadaşlar ;

Elimde 1 adet m66 quenchel modül bulunuyor. Bu modülü pic ile kullanmaya çalışıyorum. Picden gönderdiğim AT\r komutuna modül \r\nOK\r\n olarak cevap veriyor. Ama bu gelen bilgiyi picde işleyemiyorum. önde ve sonra gelen \r ve \n karakterlerini kaldırmak için bir fonksiyon var mı ?.

Ben strstr komut ile içinde geçen OK 'yi kelime bazlı bulmayı denedim ama çalışmadı.

Kullandığım komutlar

Kod Seç


void str_clear
(char *str)  
{
   
char separators[8];
   
char *ptr, *clean_str;
   
strcpy(separators," ,;.\"!?");      
   
clean_str=str;
   do
   {
      
ptr strpbrk(str,separators);  
      if(
ptr == str)                   
      {
         ++
str;                        
      }
      else if(
ptr == 0)                
      {
         while(*
str != 0)              
            *
clean_str++ = *str++;     
         if(*--
clean_str == ' ')       
            *
clean_str 0;            
         else
            *++
clean_str 0;          
      }
      else                             
      {
         while(
ptr != str)             
            *
clean_str++ = *str++;     
         *
clean_str++ = ' ';           
      }
   } while(
ptr != 0);                  
}
  

#int_rda   // RX ucuna veri gelince meydane gelen kesme
void serihaberlesme_kesmesi ()
{
 
output_high(PIN_C0); 
 
gets(gelen); 
 
str_clear(gelen);
 
output_low(PIN_C0); 
}



while(
TRUE)
     {
printf("AT\r");
             
             
char test[10] = "OK";
             
             
int ptrs;
             
ptrs =strstr(gelen,test);
             
lcd_gotoxy(1,1);
              
printf(lcd_putc,"\n%i",ptrs);
             if (
strstr(gelen,test))   
            {
            
gelen="";
             
printf(lcd_putc,"\fModul Aktif");
             
output_toggle(PIN_C1);
             
delay_ms(2000);
            }

}


OptimusPrime

Madem hepsinde \r\n karakterleri geliyor sende oldugu gibi kullan? Mesela

Kod Seç
#define OK "\r\nOK\r\n"

if (strcmp(strOK) == 0)
{

}
else
{





gibi


fide

http://fidenetgaraj.blogspot.com/2018/06/pic-mcuyu-internet-baglayalm.html yazısında bu konu hakkında bilgi var. Çözüm yolu değişik ama çalışan bir kod. İnceleyebilirsin.

Yazının ilgili yeri:

Kod Seç

#int_RDA3
void  RDA3_isr(void)
{
  
   const 
u16 max_gsm_rda_data=400/*Sayfa eğer bulunamazsa dönüş çıktısı uzun olur. Hepsi ile işlemciyi meşgul etme. Salla gitsin*/

   
char gsm_answer[max_gsm_rda_data];

   
char dummy_resp;
   
u8 char_base;

   
u32 temp_counter=0;
   
u16 data_counter;//=0;
  
 
gsm_interrupt=1;     //interrupt geldiğinde

  

   
data_counter=0;
   
temp_counter=0;
  
   for (
temp_counter=0;temp_counter<max_gsm_rda_data;temp_counter++)
   {
      
gsm_answer[temp_counter]=0;
  
   }
  
  
temp_counter=0;
  
   do{
      if(
kbhit(gsm_comm))
      {
        
         
dummy_resp=fgetc(gsm_comm);
      
        if(
data_counter<max_gsm_rda_data)
        {
             
gsm_answer[data_counter]=dummy_resp;
             
data_counter++;
              
        
        }
         
temp_counter=0;
      
    
      }
      
temp_counter++;
  
   }while (
temp_counter<15000);
  
   
gsm_answer[data_counter]='\0';
  
   
fprintf(Comm1,"\r\nGSM RDA :%s\r\n "gsm_answer);
  



Bu kısmın kullanımında açıklamam gereken bişeyler var.
Bu kısmı yazarken karşılaştığım en büyük zorluk belirli bir uzunluğa sahip olmayan ve belirli beir karakterle bitmeyen texti almaktı.
birkaçtane line feed gelebilir, enter gelebilir, gelen cevap bir harf de olabilir, 200 harf de.

Bunun için ben de başka bir mantık kurdum. Bir karakter geldiğinde önce aldığın diziyi boşalt, sonra 15000 defa dön. Sayı fazla gelebilir ama 20Mhz de çalışan bir işlemci 15000 döngüyü 2-3 msde alır. Bu arada karakter gelirse sayacı sıfırla ve 15000 daha dön. Bu döngü işi sadece toplam süreci 2-3 ms uzattığı için o zaman mantıklı geldi. Kullanımda da bir sıkıntı çıkmadı.

Burda önemli olan değişken gsm_interrupt=1; satırıdır. cevap_bekle() içinde hatırlarsanız timeout test ediliyordu. Bir komut için timeout süresi kadar beklemek akıllıca olmaz. timeout beklemezseniz de komutun cevap verip vermediğini bilemezsiniz. Ben de burada komutu gönderip timeout içindeki süreyi 10ms paketlere böldüm. 10ms bekle cevp var mı bak. eğer cevap varsa cevabı değerlendir. cevap yoksa timeout dolana kadar 10ms 10ms  bekle.
Beklemek size mantıklı gelmeyebilir  ama GSM bağlantısını yapamadıysanız GPRS'e bağlanamazsınız. GPRS bağlantınız henüz açılmadıysa Soket açamazsınız. Yani paşalar gibi beklemek zorundasınız.
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

saybatli

Alıntı yapılan: OptimusPrime - 10 Ekim 2018, 13:17:17Madem hepsinde \r\n karakterleri geliyor sende oldugu gibi kullan? Mesela

Kod Seç
#define OK "\r\nOK\r\n"

if (strcmp(strOK) == 0)
{

}
else
{





gibi


Malesef bu şekilde de çalışmıyor onuda denedim. Teşekkür ederim ilginiz için

Alıntı yapılan: fide - 10 Ekim 2018, 13:48:53http://fidenetgaraj.blogspot.com/2018/06/pic-mcuyu-internet-baglayalm.html yazısında bu konu hakkında bilgi var. Çözüm yolu değişik ama çalışan bir kod. İnceleyebilirsin.

Yazının ilgili yeri:

Kod Seç

#int_RDA3
void  RDA3_isr(void)
{
  
   const 
u16 max_gsm_rda_data=400/*Sayfa eğer bulunamazsa dönüş çıktısı uzun olur. Hepsi ile işlemciyi meşgul etme. Salla gitsin*/

   
char gsm_answer[max_gsm_rda_data];

   
char dummy_resp;
   
u8 char_base;

   
u32 temp_counter=0;
   
u16 data_counter;//=0;
  
 
gsm_interrupt=1;     //interrupt geldiğinde

  

   
data_counter=0;
   
temp_counter=0;
  
   for (
temp_counter=0;temp_counter<max_gsm_rda_data;temp_counter++)
   {
      
gsm_answer[temp_counter]=0;
  
   }
  
  
temp_counter=0;
  
   do{
      if(
kbhit(gsm_comm))
      {
        
         
dummy_resp=fgetc(gsm_comm);
      
        if(
data_counter<max_gsm_rda_data)
        {
             
gsm_answer[data_counter]=dummy_resp;
             
data_counter++;
              
        
        }
         
temp_counter=0;
      
    
      }
      
temp_counter++;
  
   }while (
temp_counter<15000);
  
   
gsm_answer[data_counter]='\0';
  
   
fprintf(Comm1,"\r\nGSM RDA :%s\r\n "gsm_answer);
  



Bu kısmın kullanımında açıklamam gereken bişeyler var.
Bu kısmı yazarken karşılaştığım en büyük zorluk belirli bir uzunluğa sahip olmayan ve belirli beir karakterle bitmeyen texti almaktı.
birkaçtane line feed gelebilir, enter gelebilir, gelen cevap bir harf de olabilir, 200 harf de.

Bunun için ben de başka bir mantık kurdum. Bir karakter geldiğinde önce aldığın diziyi boşalt, sonra 15000 defa dön. Sayı fazla gelebilir ama 20Mhz de çalışan bir işlemci 15000 döngüyü 2-3 msde alır. Bu arada karakter gelirse sayacı sıfırla ve 15000 daha dön. Bu döngü işi sadece toplam süreci 2-3 ms uzattığı için o zaman mantıklı geldi. Kullanımda da bir sıkıntı çıkmadı.

Burda önemli olan değişken gsm_interrupt=1; satırıdır. cevap_bekle() içinde hatırlarsanız timeout test ediliyordu. Bir komut için timeout süresi kadar beklemek akıllıca olmaz. timeout beklemezseniz de komutun cevap verip vermediğini bilemezsiniz. Ben de burada komutu gönderip timeout içindeki süreyi 10ms paketlere böldüm. 10ms bekle cevp var mı bak. eğer cevap varsa cevabı değerlendir. cevap yoksa timeout dolana kadar 10ms 10ms  bekle.
Beklemek size mantıklı gelmeyebilir  ama GSM bağlantısını yapamadıysanız GPRS'e bağlanamazsınız. GPRS bağlantınız henüz açılmadıysa Soket açamazsınız. Yani paşalar gibi beklemek zorundasınız.


Bunu akşam deneyeceğim. Teşekkür ederim ilginiz için

saybatli

Gelen string ifadeyi okuyabiliyorum ama karşılaştırmasını bir türlü yapamadım. \r ve \n karaktelerini nasıl yok sayabilirim. Gelen bilginin hem LCD göstermem gerekiyor hemde karşılaştırma yapmam lazım. Bir çok string işlemi denedim başarılı olamadım.

fide

A değişkenine stringin uzunluğunu al.
B değişkenini sıfırla.
C isminde string tanımla.
0 dan A değişkenine kadar bir döngü kur.
Döngü içinde seriport ifadesinin herbir karakterini teker teker test.
Eğer test değeri 32den büyükse C stringine bu karakteri ekle, 32 den küçükse ekleme.

Ensonda C değişkenini ascii 0 ile sonlandı.

Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

saybatli

Şimdi fark ettim hep gelen ifadenin ilk 2 karakterini alabiliyorum bütününü alamıyorum. Daha öncede nextion ekranları kullanırken de benzer bir sorun ile karşılaşmıştım. Ekrandan gönderdiğin verinin sadece 2 karakterini alabiliyordum. Onda şu şekilde çözmüştüm ekrandan veri gönderme den önce boşluk gönderip hemen peşine veriyi gönderince tamamını alabiliyordum.

GSM modülünde bunu yapamıyorum. Bana bu seri haberleşmede yardım edebilecek biri var mı? Şuan ki kodlar aşağıdaki gibi.

Kod Seç

#include <18LF46K22.h>
//#include <KBD.C>
//#include <math.h>
//#include <stdlib.h>
#include <string.h>


#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
//#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(int=4000000)
//#use STANDARD_IO( B )

char deger[10] = "EVET";
char gelen[16]; 
int8 sayac=0;
int giris;
int gsm_interrupt;
const 
int16 max_gsm_rda_data=400/*Sayfa eğer bulunamazsa dönüş çıktısı uzun olur. Hepsi ile işlemciyi meşgul etme. Salla gitsin*/

   
char gsm_answer[max_gsm_rda_data];


#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS,timeout=1000,stream=gsm_comm)


#define LCD_ENABLE_PIN PIN_C3
#define LCD_RS_PIN PIN_C1
#define LCD_RW_PIN PIN_C2

#define LCD_DATA4 PIN_D0
#define LCD_DATA5 PIN_D1
#define LCD_DATA6 PIN_D2
#define LCD_DATA7 PIN_D3

#define LCD_LED   PIN_A7

#include <lcd.c>

#define pwrkey   PIN_C0
#define role     PIN_A6
#define intcom   PIN_C4
#define giris1   PIN_D4
#define giris2   PIN_D5
#define giris3   PIN_C5
#define giris4   PIN_D6
#define giris5   PIN_D7
#define giris6   PIN_A5

#define buton1   PIN_B6 //yukari
#define buton2   PIN_B7 //asagi
#define buton3   PIN_A1 //sağ
#define buton4   PIN_A3 //sol
#define buton5   PIN_A2 //solalt
#define buton6   PIN_A1 //solust


#define L1   PIN_B0 //yukari
#define L2   PIN_B1 //asagi
#define L3   PIN_B3 //sağ
#define L4   PIN_B2 //sol
#define L5   PIN_B4 //solalt
#define L6   PIN_B5 //solust



void buffur_temizle(char *str)  
{
   
char separators[8];
   
char *ptr, *clean_str;
   
strcpy(separators," ,;.\"\r\n!?");      
   
clean_str=str;
   do
   {
      
ptr strpbrk(str,separators);  
      if(
ptr == str)                   
      {
         ++
str;                        
      }
      else if(
ptr == 0)                
      {
         while(*
str != 0)              
            *
clean_str++ = *str++;     
         if(*--
clean_str == ' ')       
            *
clean_str 0;            
         else
            *++
clean_str 0;          
      }
      else                             
      {
         while(
ptr != str)             
            *
clean_str++ = *str++;     
         *
clean_str++ = ' ';           
      }
   } while(
ptr != 0);                  
}
  

#int_rda   // RX ucuna veri gelince meydane gelen kesme
void serihaberlesme_kesmesi ()
{

    
output_high(L1);
   
char dummy_resp;
   
int char_base;

   
int32 temp_counter=0;
   
int16 data_counter;//=0;
  
 
gsm_interrupt=1;     //interrupt geldiğinde

  

   
data_counter=0;
   
temp_counter=0;
  
   for (
temp_counter=0;temp_counter<max_gsm_rda_data;temp_counter++)
   {
      
gsm_answer[temp_counter]=0;
  
   }
  
  
temp_counter=0;
  
   do{
      if(
kbhit(gsm_comm))
      {
        
         
dummy_resp=fgetc(gsm_comm);
      
        if(
data_counter<max_gsm_rda_data)
        {
             
gsm_answer[data_counter]=dummy_resp;
             
data_counter++;
              
        
        }
         
temp_counter=0;
      
    
      }
      
temp_counter++;
  
   }while (
temp_counter<15000);
  
   
gsm_answer[data_counter]='\0';
   
output_low(L1);
}

void ayikla(char cvp[30])
{    
gelen=" ";
     
int y 0;
     for (
int k=2;k<strlen(cvp)-2;k++)
     {
     
gelen[y] = cvp[k];
     
y++;
     }
     
gelen[y]='\0';

}


void main()
{    
      
lcd_init();// Lcd yi sifirla hazirla
      
output_high(L5); // lcd isigini yak
      
delay_ms(100);
      
printf(lcd_putc,"\fSistem basliyor"); 
     
// delay_ms(2000);
 
      



   
setup_spi(SPI_SS_DISABLED);
   
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   
setup_timer_1(T1_DISABLED);
   
setup_timer_2(T2_DISABLED,0,1);
   
enable_interrupts(GLOBAL);
   
enable_interrupts(int_rda);

       
      
output_low(pwrkey);
      
delay_ms(3000);
      
output_high(pwrkey);
      
printf("ATE 0\r");
      
delay_ms(1000);
      
ayikla(gsm_answer);
      
printf(lcd_putc,"\f%s",gelen);
   while(
TRUE)
     {
      
      
enable_interrupts(int_rda);
  
//printf("\rDongu OK!\n");
     

   //  printf("\rAdet = %i",say);
     //printf("\rcvp = %s",gelen);

     

    
    
     
             
int ptrs;
            
printf("AT\r");
            
delay_ms(2000);
            
            
ayikla(gsm_answer);
            
int say strlen(gsm_answer);
            
printf(lcd_putc,"\f%s",gelen);
            
printf(lcd_putc,"\n%i",say);

            
//printf("\r%s",gelen);
            //printf("\n%i\r",say);
           
           
            
char test[30] = "OK";
            if (!
strcmp(gelen,test))   // seri den gelen bilgis " OK" ise pin_b1 i aktif et 
            
{
             
gelen="";
             
printf(lcd_putc,"\nmodul basarili ");
             
output_toggle(L2);
             
delay_ms(2000);
            }

            
     }
}
                       





fide

Rda rutini içinde ne aldığına bak bence ilk olarak.
Rda rutini sonuna (46k22 olduğuna göre ikinci seri portun vardır) fprintf(dbg," veri:%s\r\n", gsm_answer); koy. dbg ikinci seri portun adı, ikinci seri portu tanımlarken port=dbg şeklinde tanımlarsın.

Özellikle gsm modülle çalışırken elinde enaz 3 adet usb seri çevirici olsun. Birini pic i debug etmek için ikisinin rx uçlarını da gsm den pic e, pic den gsme giden verileri takip etmek için kullan.

Diğer bir konu ayıkla içinde
if(cvp[k] >32)
{ gelen[y] =cvp[k];y++;} şeklinde kullanırsan baştaki cr lf karakterlerini de süzersin.
Böylece eşitlik kontrolün daha sıkıntısız olur.

Diğer bir konu
 printf ("at\r") ;
Delay(1000);
Verimsiz çalışır. Bu konutun ortalama cevap süresi 100ms dir.
Bunun yerine eğer bu işi adam akıllı yapacaksan (o kadar pointer kullandığına göre ciddi programlama bilgin var) önce tavsiye ettiğim yazıdaki cevap bekle ve send_cmd(xxx); komut yapısını anlamaya çalış.
Sonra debug - seri port takip olayını kesinlikle yap. Varsayımlarla program yazılmıyor. İllaki bişeyler düşündüğümüz gibi olmuyor.
Ve bi tavsiye daha aldığın metni yazdırırken önüne arkasına @,*,x gibi normalde kullanılmayan karakter yazdır. Böylece aldığın /gönderdiğin text in sonunda boşluk varsa daha kolay yakalarsın.

Kolay gelsin.

Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

saybatli

RDA da belirtiğim gibi sadece gelen ifadenin ilk 2 karakterini alabiliyorum. Yani AT\r gönderdiğimde \r\nOK\r\n yerine sadece \r\n karakterleri geliyor. USB-TTL dönüştürücü ile gelen giden veriyi takip edebiliyorum. Pic den modüle gidende ve modülün gönderdiği veride sorun yok. Tek sorun şuan gelen verinin sadece ilk 2 karakerini alıyor. USB-TTL ilede veri göndermek istediğim de sorun aynı...

saybatli

Bu tarz bir sorunla karşılaşan olmadı mı ?

saybatli

Yardımcı olan arkadaşlara teşekkür ederim sorunu modülün cevap verme şeklini değiştirerek çözdüm.