CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

[Urgent] GSM Project - SIM Resetting (GSM.Vcc to GSM.GND)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
davidroux



Joined: 19 Jul 2009
Posts: 11

View user's profile Send private message

[Urgent] GSM Project - SIM Resetting (GSM.Vcc to GSM.GND)
PostPosted: Fri Oct 30, 2009 1:38 am     Reply with quote

Hey guys, I would really like your help on this. I have tried many many different things and in some cases has worked but for only a short time. The following code demonstrates just simply sending AT commands to the Siemens TC35i and getting it back. I get everything back as requested but once I8 connect SIM... it gets stuck in ATE1 (1st AT command reply).

Weird thing is I copied and pasted someones code here on ccs forums and sent sms's every now and then, but I need to do data handling of what I am receiving. I initially used kbhit to poll.. now using int driven and freezes never (if SIM not connected).. but unfortunately for some reason I have to run my 1st AT command with polling before int based works...

so in summary it freezes on line : InBuffer[i] = getc(); under goto sniffer in wait for ok.. when SIM connected.. if not connected it finished perfectly... obv replying Full signal strength etc of antenna

Oh I'm using CCS compiler through mplab.
version 4.084

Code:

#include <18F4620.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC                    //Internal RC Osc
#FUSES NOPROTECT                //Code not protected from reading
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV21                   //Brownout reset at 2.1V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                     //Master Clear pin enabled

#use delay(clock=8000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#byte rcreg = 0xFAE
#byte txreg = 0xFAD
#byte RCSTA = 0xFAB
#bit  OERR =  RCSTA.1
#bit  CREN =  RCSTA.4

int8 initmodem(void);
int8 SendCommandGetOK(char *dummy);
int8 SendCommandGetNoResp(char *dummy);
int8 WaitForOK(void);
int8 PowerUp(void);
int8 PowerDown(void);

//Definitions for the Modem Setup
char SCID[] = "AT\r\n!";
char IMEI[] = "AT+CGSN\r\n!";
char ECHON[] = "ATE1\r\n!";
char CREG[] = "AT+CREG=2\r\n!";         //enable URC +CREG:<stat> to report status of network registration
char CREGQUERY[] = "AT+CREG?\r\n!";
char ERROR2[] = "AT+CMEE=2\r\n!";      //AT+CMEE Report mobile equipment error, To obtain enhanced error messages choose <n>=2, EX phone failure
char CNMI[] = "AT+CNMI=2,1,0,0,1\r\n!";   //New SMS message indications
char TEXTMODE[] = "AT+CMGF=1\r\n!";      //Select SMS message format, TEXT MODE
char COPS[] = "AT+COPS?\r\n!";
char CPIN[] = "AT+CPIN?\r\n!";
char CSQ[] = "AT+CSQ\r\n!";
char CFUN[] = "AT+CFUN=1,1\r\n!";

int test = 0;

//Definitions for buffers that will be used for the input and output of modem data
char InBuffer[168];
char OutBuffer[168];
char variable=0;
int status = 0;


//******************************************************//
//**MAIN FUNCTION**//
//WILL TURN MODEM ON AND RUN VARIOUS FUNCTIONS
//******************************************************//
void main()
{
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
      //Lets first turn the modem on before we can do anything

while (1){

   if(PowerUp()){
   output_high(pin_D2);
   break;
   }else {
   powerDown();
   }           
}
   //So at this stage, we are happy to say that the modem will be on

   if (!initmodem()){
      output_high(pin_D0);       // turn the red LED on
   }else {output_high(pin_D1);}    // turn the yellow LED on
   
}

//******************************************************//
//INITIALISE THE MODEM, WILL CALL FUNCTIONS THAT WILL RUN
//PARTICULAR AT COMMANDS
//******************************************************//
int8 initmodem()
{

   if (!SendCommandGetOK(ECHON)){
         delay_ms(100);
         if (!SendCommandGetOK(ECHON)){            //2 opportunities to get an "OK" back
            return (0);
         }

    }
   delay_ms(500);

   test=1;
   rcreg = 0x00;
   txreg = 0x00;

   if (!SendCommandGetOK(ERROR2)){
         delay_ms(100);
         if (!SendCommandGetOK(ERROR2)){            //2 opportunities to get an "OK" back
            return (0);
         }

    }
   delay_ms(500);
   
   rcreg = 0x00;
   txreg = 0x00;

   if (!SendCommandGetOK(TEXTMODE)){
         delay_ms(100);
         if (!SendCommandGetOK(TEXTMODE)){            //2 opportunities to get an "OK" back
            return (0);
         }
    }
   delay_ms(500);

   rcreg = 0x00;
   txreg = 0x00;

   if (!SendCommandGetOK(CREG)){
         delay_ms(100);
         if (!SendCommandGetOK(CREG)){            //2 opportunities to get an "OK" back
            return (0);
         }
    }

   delay_ms(500);

   rcreg = 0x00;
   txreg = 0x00;

   if (!SendCommandGetOK(CSQ)){
         delay_ms(100);
         if (!SendCommandGetOK(CSQ)){            //2 opportunities to get an "OK" back
            return (0);
         }
    }
        
}


//******************************************************//
//FUNCTION TO POWER UP THE MODEM, WILL RETURN 1 IF VDD IS
//HIGH
//******************************************************//
int8 PowerUp()
{
   output_high(pin_D5);
   delay_ms(200);         
   output_low(pin_D5);     
   delay_ms(5000);
   output_high(pin_D5);
   delay_ms(2000); 
   output_low(pin_D5);     
   delay_ms(5000);

   if( input(PIN_D7) ){
               
      return (1);
   }else {return (0);}
}
      
//******************************************************//
//FUNCTION TO POWER DOWN THE MODEM, PULL HIGH TO DO THIS
//******************************************************//
int8 PowerDown()
{
   output_high(pin_D5);
   delay_ms(5000);
}
      
//******************************************************//
//WILL RUN THIS FUNCTION THAT EXPECTS AN OK IN RETURN
//SENDS VIA THE UART USING PUTC USING OUT BUFFER
//******************************************************//
int8 SendCommandGetOK(char *dummy)
{
      int i=0;

   //lets first clear the INBuffer so we do not get the Input messgaes mixed up
   for (i=0;i<168;i++)
   {
      OutBuffer[i] = 0;
   }
   
   //Lets copy the contents from the dummy input to the OutBuffer
   for (i=0;i<168;i++){
      if (dummy[i] == '!'){
         break;         
      }else OutBuffer[i] = dummy[i];
   }
   i=0;
   while (OutBuffer[i] != 0x0A){
         putc(OutBuffer[i]);
      i = i+1;
   }

   if (test==1){
   enable_interrupts(INT_RDA);
    enable_interrupts(global);
   

   while(1){
   
      if (status ==1 ){
      return (1);
      }
      if (status == 2){
      return (0);
      }
   }
}

   if(!WaitForOK())
   {
      return (0);
   }else return (1);
}

//******************************************************//
//WAIT FOR AN OK, AND STORE IN BUFFER
//AND YES I HAVE TO HAVE THIS 1ST IN INITMODEM ELSE ISR WONT WORK
//... NO IDEA WHY
//******************************************************//
int8 WaitForOK()
{   

//   //lets first clear the INBuffer so we do not get the Input messgaes mixed up
int i=0;
int j=0;

for (i=0;i<168;i++)
   {
      InBuffer[i] = 0;
   }

   i=0;

sniffer:
   
   if(kbhit())
   {
      InBuffer[i] = getc();
      if ((InBuffer[i]=='K')&&(InBuffer[i-1]=='O')){         //ok replied
      variable = 1;
      return (1);
      }
      if ((InBuffer[i]=='R')&&(InBuffer[i-1]=='O')){         //error
      variable = 2;
      return (0);
      }
      if ((InBuffer[i]=='9')&&(InBuffer[i-1]=='9')){         //"99" antenna problem
      variable = 3;
      return;
      }
      
      i=i+1;
      goto sniffer;
   }
   else goto sniffer;
   
}

//******************************************************//
//WILL RUN THIS FUNCTION THAT DOESNT EXPECT A REPLY IN RETURN
//******************************************************//
int8 SendCommandGetNoResp(char *dummy)
{
   int i=0;   

   //lets first clear the INBuffer so we do not get the Input messgaes mixed up
   for (i=0;i<168;i++)
   {
      OutBuffer[i] = 0;
   }
   
   //Lets copy the contents from the dummy input to the OutBuffer
   for (i=0;i<168;i++){
      if (dummy[i] == '!'){
         break;         
      }else OutBuffer[i] = dummy[i];
   }
   i=0;
   while (OutBuffer[i] != 0){
         putc(OutBuffer[i++]);
   }
   putc(13);
}

//*************************************//
//ISR FOR RX OF UART//
//************************************//
#INT_RDA
void RDA_ISR()
{
   int i=0;
   status = 0;   
   disable_interrupts(INT_RDA);
   for (i=0;i<168;i++)
      {
      InBuffer[i] = 0;
      }

   i=0;
   for (i=0;i<168;i++)
      {
      InBuffer[i] = getc();
      if ((InBuffer[i]=='K')&&(InBuffer[i-1]=='O')){
      status = 1;
      return;
         }
      if ((InBuffer[i]=='R')&&(InBuffer[i-1]=='O')){
      status = 2;
      return;
      }



   }

}


Last edited by davidroux on Sat Oct 31, 2009 10:54 pm; edited 3 times in total
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Oct 30, 2009 8:34 am     Reply with quote

Code:
   rcreg = 0x00;
This sequence is four times in your code and has several problems:
rcreg is normally read only, I don't know if writing has any effect but certainly it is not going to clear the register as you want to. To clear rcreg you have to read all the data waiting in the receive queue:
Code:
while (kbhit())
{
  getc();
}


Code:
   txreg = 0x00;
My guess is you want to set some kind of initial value? You don't have to, the start up code will handle this for you.
What actually happens is you are transmitting the value 0x00 to your modem. I don't know how the modem will respond to this, but it definitely is a communication error and perhaps the reason for your first command to fail?

Your interrupt receive routine is not implemented the way an interrupt routine should be designed. Because it is waiting for a complete message to arrive, your routine is taking a long time in terms of computer speed. Even at 115kbaud a character arrives with slow 0.1ms intervals.
Interrupts should have as short execution times as possible so to return processor resources to other parts of your program. For example, if you had a second interrupt routine it would now be blocked by your slow Serial Receive interrupt.
Best practice is to implement a serial receive interrupt routine is to have the interrupt write the data to a (large) circular buffer. This ensures you won't loose incoming data. Then at regular intervals in your main routine you check the circular buffer to contain data. An example of such an implementation is the program ex_sisr.c in your compiler's example directory.

Another possible problem in your program is that you are not processing the newline character following the modem's response. This character will be waiting to be processed until the next time you enable the receive interrupt. With a character still present the processor immediately enters the receive interrupt and in your implementation will wait there until a valid response is received, or times out after 168 characters (i.e. never).

The function WaitForOK() contains a return statement without return value. This is a serious bug as you are now testing an unknown response value. The compiler generates a warning for this.

There are more compiler warnings for your program. When posting code ensure it is as small as possible with all unused variables and functions removed.

How is your modem connected to the PIC? PIN_D5 and D7 are connected to what?
davidroux



Joined: 19 Jul 2009
Posts: 11

View user's profile Send private message

PostPosted: Fri Oct 30, 2009 9:13 am     Reply with quote

Hey thanks for the reply Smile

D5 is connected the modem which is required to be driven low for like 2 secs or something. I add some more to be safe. D7 is an i/p to the micro from the tc35i modem to inform if indeed powered or not. I turn on light when powered which works.

Yah those rxreg and txreg things are me just fiddling Iwas trying to be hopeful. hehe

The thing that confuses me is how come it only freezes with SIM connected. I will post schematic of SIM cct and surroundings asap. I can query IMEI nos etc of modem (also used to be able to query if SIM requires PIN nos etc). So everything obv goes through the RX and TX lines of modem.

The ISR I wrote works all the time with the other AT commands, and thats not where it freezes. It does so on waitforok (which i need else ISR aint work. No idea why again).

Oh and "test" is just me quickly changing between polling vs int driven. Basically this is not nearly final code but code that should be able to give me back example AT+CREG? returning like 1,2 etc. I just really need to logon to network before I can continue with more stuff :(

many thanks guys Smile
davidroux



Joined: 19 Jul 2009
Posts: 11

View user's profile Send private message

PostPosted: Sat Oct 31, 2009 8:55 am     Reply with quote

update : ok so problem is that the SIM is powering off!!! I added while (1); at end of main so not go into sleep mode. I saw it replied with sim id (SCID) but then I quickly tried to phone it (should get ringing on my side) but the SIM quickly turns off... and sometimes it turns off before I even get to SCID (added it into code now with more delay).
davidroux



Joined: 19 Jul 2009
Posts: 11

View user's profile Send private message

PostPosted: Sun Nov 01, 2009 11:26 am     Reply with quote

latest is its replying now!!! but replying siff things.. like SIM failure and sim blocked.. but working when put in phone... so must be h/w... this is code if anyone wants... this sends and listens same time... thats what i was doing wrong...

Code:
int8 SendCommandSIMGetOK(char *dummy)
{
   int i=0, j=0;
   
     //Empty the uart fifo
      while (kbhit())
      {
        getc();
      }
      //Clear the receive buffer
    for (i=0;i<50;i++)
     {
        InBuffer[i] = 0;
     }
     i=0;
     //Send the command, but at the same time check for any characters being received
      while (dummy[j] != '!'){
         putc(dummy[j++]);
         if (kbhit()){
            InBuffer[i++] = getc();
         }
      }
      while (1) {
         if (kbhit()){
            InBuffer[i++] = getc();
         }
      }

}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Nov 01, 2009 3:53 pm     Reply with quote

Quote:
this sends and listens same time... thats what i was doing wrong...
For this exact problem they have invented interrupts...
While your main routine is sending data, the receive interrupt will handle the data receptions and store the data in a buffer for processing at a later time. Exactly like you are doing now, but when you are adding more transmit routines you will also have to duplicate the receiver code. Would you have implemented a separate receive interrupt, the receive code is there only once.

Did you have a look at the ex_sisr.c example code like I suggested?
Implementations of this serial buffer for GSM communications have been discussed on this forum several times before. Use this forum's search function to find these examples.
davidroux



Joined: 19 Jul 2009
Posts: 11

View user's profile Send private message

PostPosted: Sun Nov 01, 2009 11:42 pm     Reply with quote

Yeah I tried isr.. as u can see but it was wrong, well at least s/w is sorted just gotta clean that up, but now h/w problem which is worst.

Yeah I looked at it thanks Smile gave me the idea. Now gonna clean up this "
rats nest" of code Laughing and make neat using ISR's etc.
bdeb
Guest







PostPosted: Wed Nov 18, 2009 12:41 am     Reply with quote

Hmm...
Maybe a stupid theory...


When you insert the SIM, the modem tries to register.
It will therefore consume a lot of power (1A in burst).

If power supply, cables, decoupling capacitors, etc are not correctly dimensioned, the voltage will drop and the modem will power off.


Regards

/BdeB
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group