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

GPS-GSM on pic16f8773a using sw uart on RB0

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



Joined: 11 Dec 2013
Posts: 5

View user's profile Send private message

GPS-GSM on pic16f8773a using sw uart on RB0
PostPosted: Sun Mar 09, 2014 7:02 am     Reply with quote

Hi,
i know there have been a lot of posts on this topic.. but after going through them a lot i couldn't find a solution.
i'm using CCS PCM C Compiler, Version 4.084, 36728 on a pic16f877a
i tested the circuit on a bread board using S1315RL gps module
datasheet
http://www.macrogroup.ru/content/data/store/images/f_1072_5364_1.pdf
i couldnt find the data sheet of the sim300 module im using.
my problem is that both the gps and gsm modules are not working together, im using a software uart on RB0 for sw uart.. individually they work perfectly.. pls help me.
this code is based on Gabriel's gsm code.. :D
my objective in this code was to send the gps cordinates through gsm
Code:

#include <16f877A.h>
#device adc=8
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NODEBUG
#use delay(clock=20000000)
#include <string.h>
#include <stdlib.h>
#use rs232(baud=9600,xmit=PIN_B1, rcv=PIN_B0,stream=GPS,DISABLE_INTS)     //TRY SAMPLE_EARLY
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,STREAM=GSM,ERRORS,DISABLE_INTS)
#DEFINE OK       0          // 1 <-- Required
#DEFINE CMTI    1          // 2 <-- Required
#DEFINE ERROR   2          // 3 <-- Required
int i=0,j=0,flag=0,gcount=0,process=1,recv=0;
int num[10];
#DEFINE SIZE_COMMAND    10   // Sets the Max command Length including '\0'
#DEFINE TOTAL_STRINGS    7   // Total number of Searchable strings
#DEFINE GBUFFER        80
#DEFINE SIZE_BUFFER    80   // Serial Buffer Size
#DEFINE NULL    '\0'      // Easier to type than '\0'
#INT_RDA
void SerialInt();         // Serial ISR used
#int_ext
void ext_isr();
int1 CHECK_COM();         // Checks Modem comms are OK
int1 SET_PDU();            // Sets modem to TXT MODE
int1 SET_MEM();            // Sets the Prefered Message Storage
int1 SET_CNMI();
int1 DEL_SMS(int);         // Deletes SMS form memory
int1 READ_SMS(int);         // Loads SMS onto buffer
int1 STRING_SEARCH(int);   // Searchs for strings or commands
int1 DELAY(int);          // Delay with Limit
void CMD_LOAD(int);         // Loads commands to a temp buffer from main "Strings" data base
void SEND_SMS();         // Sends an SMS
void SEND_SMS_NUM();
void CLEAR_BUFFER();      // Clears the serial buffer
const char Strings[TOTAL_STRINGS][SIZE_COMMAND]={   "OK\0",               // index 0
                                       "+CMTI\0",            // index 1
                                       "ERROR\0"};            // index 2
//const float stops[3][3];                                   
char Command[SIZE_COMMAND];                              // Temp command buffer
char GPSBUFFER[GBUFFER];
char Receive_String[SIZE_BUFFER];                        // Serial Buffer
int counter_read = 0x00;                              // Serial Buffer Counter
char term[3], *ptr,status[2];
float lat=0,lon=0;
//                      CHECKS COMMS WITH MODEM
int1 CHECK_COM()
{
   counter_read=0;                     // Reset buffer counter
   fprintf(GSM,"AT\r");                     // Send Attention Command
   DELAY(5);                        // Delay a maximum of X seconds
   counter_read=0;                     // Reset buffer counter
   return(STRING_SEARCH(OK));            // Check for OK response

//                      SET MODEM TO TXT MODE
int1 SET_PDU()
{
   counter_read=0;                  // Reset buffer counter
   fprintf(GSM,"AT+CMGF=1\r");            // Set modem to TXT mode
   DELAY(5);                     // Delay a maximum of X seconds
   counter_read=0;                  // Reset buffer counter
   return(STRING_SEARCH(OK));         // Check for OK response

//                     SET MESSAGE STORAGE
int1 SET_MEM()
{
   counter_read=0;                        // Reset buffer counter
   fprintf(GSM,"AT+CPMS=\"SM\",\"SM\",\"SM\"\r");   // Store in SIM Card
   DELAY(5);                           // Delay a maximum of X seconds
   counter_read=0;                        // Reset buffer counter
   return(STRING_SEARCH(OK));               // Check for OK response

//                     SET NEW SMS ALERT MSG
int1 SET_CNMI()
{
   counter_read=0;                        // Reset buffer counter
    fprintf(GSM,"AT+CNMI=2,1,2,0,0\r");              //text part of the command.
   DELAY(5);           // Delay a maximum of X seconds
   output_high(pin_b6);
   counter_read=0;                        // Reset buffer counter
   return(STRING_SEARCH(OK));// Check for OK response
   

//                     LOADS SMS INTO BUFFER
int1 READ_SMS(int index)            // index' is the memory address/location
{
   counter_read=0;                  // Reset buffer counter
   fprintf(GSM,"AT+CMGR=%d\r",index);      // Send Read SMS command
   DELAY(5);                     // Delay a maximum of X seconds
   counter_read=0;                  // Reset buffer counter
   if(STRING_SEARCH(OK))            // Check for OK response
      return(1);                  //           OR
   if(STRING_SEARCH(ERROR))         // Check for ERROR response
      return(0);

//                     DELETES SMS FROM MODEM
int1 DEL_SMS(int index)               // index' is the memory address/location
{
   counter_read=0;                  // Reset buffer counter
   fprintf(GSM,"AT+CMGD=%d\r",index);      // Send Delete SMS command
   DELAY(5);                     // Delay a maximum of X seconds
   counter_read=0;                  // Reset buffer counter
   if(STRING_SEARCH(OK))            // Check for OK response
      return(1);                  //           OR
   if(STRING_SEARCH(ERROR))         // Check for ERROR response
      return(0);

//                           SEND SMS
void SEND_SMS()

   output_high(pin_a1);
   counter_read=0;
   fprintf(GSM,"AT+CMGS=\"+91%s\"\r\n",num);
   delay_ms(10);
   fprintf(GSM,"Status is %s Lat is %.4f Long is %.4f \n\r",status,lat,lon);         // Text to reply
   fprintf(GSM,"%c",0x1a);
  // putchar(0x1A);
   DELAY(5);// send Ctrl-z
   

//               SEARCHES FOR A SPECIFIC STRING IN BUFFER
int1 STRING_SEARCH(int index)               // index' is Strings[index][SIZE_COMMAND]
{                                    // See defines at top.
   CMD_LOAD(index);                     // Loads into temp array the string to be found
   if(STRSTR(Receive_String,Command)!=NULL)   // Find String or Command in main Buffer
      return(1);                        // Return 1 if found
   else
      return(0);                        // Return 0 if not found.

//               LOADS TO TEMP ARRAY THE SEARCHABLE STRING
void CMD_LOAD(int index)
{
   int var=0;                                            // temp index for array
   memset(Command,NULL,SIZE_COMMAND);                  // Reset data array index
      while((Strings[index][var]!=NULL)&&(var<SIZE_COMMAND))   // Copy data from main "Strings" to commparing array.
      {
      Command[var]=Strings[index][var];      // Copy into temp array the strings from Main Database
         var++;                           // Up index
      }
}
//                     CLEAR SERIAL BUFFER
void CLEAR_BUFFER()
{
   memset(Receive_String,NULL,SIZE_BUFFER);      // Set all elements to NULL
   counter_read=0;                           // Reset index
}
//                         LIMITED DELAY
int1 DELAY(int Delay_ctr)
{
   counter_read=0;                     // Reset buffer counter
   while((counter_read==0)&&(Delay_ctr>0))   // stay here until modem responds (X Seconds is arbitrary)
   {                               
   delay_ms(1000);                     
   Delay_ctr--;
    }
   if((counter_read==0)&&(Delay_ctr==0))
   return(1);
   if((counter_read==0)&&(Delay_ctr>0))
   return(0);             

//                     SERIAL BUFFER ISR
#INT_RDA
void SerialInt()
{
   Receive_String[counter_read]=getchar(GSM);         // Gets chars from uart
   counter_read++;                           // Increment counter
      if(counter_read==SIZE_BUFFER)counter_read=0;   // Circle Buffer
}
#INT_EXT
void ext_isr()
{
   char temp;
   temp=fgetc(GPS);
   switch(temp)
   {
    case 'C' :    flag=1;
                  break;
    case '\r':                   
                  flag=0;                        // CR practically
                  gcount=0;
                  recv=1;
                  process=0;
                  break;
    default  :    break;
  }
       if(flag==1)
          {
            if(process==1)
            GPSBUFFER[gcount++]=temp;
          }
 if(gcount==GBUFFER)gcount=0; 
}
void main()

   int sms_index=1;
   ENABLE_INTERRUPTS(GLOBAL);               // Enable Interrupts
   ENABLE_INTERRUPTS(INT_RDA); // Enable Serial Interrupts
  //disable_interrupts(int_ext);
   CLEAR_BUFFER();
   DELAY(1);                           // Delay a maximum of X seconds
   strcpy(term,",*");
   while(1)
   { 

      if(CHECK_COM())
      {   
         CLEAR_BUFFER();
         DELAY(1);                     // Delay a maximum of X seconds
      }
      else
      {
      DELAY(1);                        // Delay a maximum of X seconds
      while(!CHECK_COM())
         {
            DELAY(1);                  // Delay a maximum of X seconds
         }
      }
      DELAY(1);                        // Delay a maximum of X seconds;

      if(SET_PDU())
      {
         CLEAR_BUFFER();
         DELAY(1);                     // Delay a maximum of X seconds
      }
      else
      {
         while(1);
       }

     
      DELAY(1);                        // Delay a maximum of X seconds;
      if(SET_MEM())
      {
         CLEAR_BUFFER();
     
         DELAY(1);                     // Delay a maximum of X seconds
      }
      else
      {
         
         while(1);
       }
       DELAY(1);                        // Delay a maximum of X seconds;
      if(SET_CNMI())
      {
         CLEAR_BUFFER();
     
         DELAY(1);                     // Delay a maximum of X seconds
      }
      else
      {
       
         while(1);
       }
   
      CLEAR_BUFFER();
     
      DELAY(1);                        // Delay a maximum of X seconds
      enable_interrupts(int_ext);
      ext_int_edge(H_TO_L);   //Initaially set pin b1 to low
      clear_interrupt(INT_EXT);
      while(1)
      { 
         sms_index=1;
         DEL_SMS(sms_index);     
         
         while(!STRING_SEARCH(CMTI)){
         output_high(pin_a0);
                                   if(recv==1)
                                   {                       
                                    ptr = strtok(GPSBUFFER,term);
                                    ptr=strtok(0,term);
                                    ptr=strtok(0,term);
                                    strcpy(status,ptr);
                                    ptr=strtok(0,term);
                                    lat=atof(ptr);                       
                                    ptr=strtok(0,term);
                                    ptr=strtok(0,term);
                                    lon=atof(ptr);                                 
                                    process=1;
                                    recv=0;
                                   
                                   }
                                    }     
                                    disable_interrupts(int_ext);                                   
                                  output_low(pin_a0);
         CLEAR_BUFFER();
         sms_index=1;
         while(READ_SMS(sms_index))
            {
            while(Receive_String[i]!='9')
             {
              i++;
               }
            j=0;
               
            while(j<10)
              {
          if((Receive_String[i]=='9')&&(Receive_String[i+1]=='1'))
                  {
                     i++;
                     i++;
                     output_high(pin_d2);
                     for(j=0;j<10;j++)
                     {
                        num[j]=Receive_String[i];
                        i++;
                     }
                     num[j]=0;
                  }
               else
               {
               i++;
               }
             }           
                  CLEAR_BUFFER();
                  SEND_SMS();
                  DELAY(3);               // Delay a maximum of X seconds
                  DEL_SMS(sms_index); 
                  CLEAR_BUFFER();
                  enable_interrupts(int_ext);
                  break;
            }
   
      }

   }//--END OF MAIN WHILE

} //End of main()

temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Mar 09, 2014 9:27 am     Reply with quote

The easiest, best solution would be to use a current PIC with 2 Hardware UARTs, like the 18F46K22. The 877 is old and obsolete. There are pin compatible PICs that are cheaper, faster, better for your purpose.

If you are really, really stuck using the 877 you'll have to decide which device, the GPS or the GSM needs to have the hardware UART. Your program shows you've chosen the GSM to have the UART, and I agree with that as it's more critical to have proper, reliable communications with the modem than the GPS.

I don't know the available GPS commands, but I'd hope there was a 'get GPS data' command. Where the PIC sends the command, then waits for the data to come back (probably as a 'stream' with a CR to terminate). This is fairly easy to cut code for BUT using a software UART is not the best solution.
Others who have used the GPS/GSM modules can advise better.

hth
jay
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Mon Mar 10, 2014 10:16 am     Reply with quote

I agree that you should try to use a pic with 2 uarts.

If you must use the 877A, i would suggest you test out your GPS code extensively using the software uart prior to integrating the code.

Once you have proven code that reads the GPS using SW uart and can report the data to a terminal with the HW uart, then you can mix the GSM code with the GPS.

I would wait for the trigger SMS and once you receive it, then poll the GPS...why?

Because if your polling the GPS constantly with SW uart, when the trigger SMS is received, the hardware uart interrupts will mess up your software uart.... the GSM module once you finish reading the trigger SMS can wait as long as you need to collect the GPS data.

In other words... do one thing at the time...
Wait for incoming SMS only
Poll the GPS only.
Reply SMS only.

Can you poll your GPS on command or is it just spitting out data constantly?

G.
_________________
CCS PCM 5.078 & CCS PCH 5.093
Ttelmah



Joined: 11 Mar 2010
Posts: 19505

View user's profile Send private message

PostPosted: Mon Mar 10, 2014 10:34 am     Reply with quote

As a comment:
1) get rid of 'disable_ints' in both the RS232 declarations. This is for where you are doing software RS232, in the 'non interrupt' code, and want to ensure that no interrupt event can affect this. Since you are doing the software serial inside an interrupt this can't happen, and this might cause problems.
2) You talk about sample early, but have not got this enabled. Enable it.
3) Set the edge, and clear the interrupt, _before_ enabling it.
4) You really need int_ext to remain enabled. Problem is that by turning it off, and then re-enabling it, you may be enabling it 'mid character'. Then data received after this can be garbage....
Akhil Thomas



Joined: 11 Dec 2013
Posts: 5

View user's profile Send private message

PostPosted: Mon Mar 10, 2014 12:14 pm     Reply with quote

Quote:

I would wait for the trigger SMS and once you receive it, then poll the GPS...why?

Because if your polling the GPS constantly with SW uart, when the trigger SMS is received, the hardware uart interrupts will mess up your software uart.... the GSM module once you finish reading the trigger SMS can wait as long as you need to collect the GPS data.

i did it this way because the reply msg wont be just the coordinates m planing to save the known bustop names in an array and define a range of cordinates for each of them.this way all the cordinates can be arranged in order of the bustops n i jus need to check the next location.... for this to work the cordinates need to be constantly updated.. this might mess up d buffer but if i clear the buffer after sending a msg then its ok right?
Akhil Thomas



Joined: 11 Dec 2013
Posts: 5

View user's profile Send private message

PostPosted: Mon Mar 10, 2014 12:17 pm     Reply with quote

Quote:

Can you poll your GPS on command or is it just spitting out data constantly?

yes the gps is constantly sending out data.. i jus need the GPRMC format
Akhil Thomas



Joined: 11 Dec 2013
Posts: 5

View user's profile Send private message

PostPosted: Mon Mar 10, 2014 12:27 pm     Reply with quote

GSM module works perfectly but when i connect the GPS Tx and Rx pins, GSM starts sending out garbage. I'm monitoring the data using a serial cable, but once i remove the GPS wires it works fine. This is really annoying. :(
ex
GSM sends AT+CMGR=1
But along with GPS it sends A+MGR1 things like this. Characters get mixed.
But the really crazy this was this thing worked completely perfect (both GPS and GSM ) for sometime, but when i tried it again the whole thing went haywire.
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Mar 10, 2014 12:57 pm     Reply with quote

The 'garbage' is probably due to the fact you're using a software UART and not properly synchonizing with the GPS data stream. One way to avoid( or minimize) it , is to send the GPS the 'send me data' command and NOT having it always send data to you.
Consider the PIC as the master, the GPS the slave where the slave(GPS) ONLY sends data when the master(PIC) commands it to.

hth
jay
Akhil Thomas



Joined: 11 Dec 2013
Posts: 5

View user's profile Send private message

PostPosted: Mon Mar 10, 2014 11:19 pm     Reply with quote

Is there any problem to use software uart on pin RB0??
I have used it like this
Code:
#use rs232(baud=9600,xmit=PIN_B1, rcv=PIN_B0,stream=GPS)
Ttelmah



Joined: 11 Mar 2010
Posts: 19505

View user's profile Send private message

PostPosted: Tue Mar 11, 2014 1:38 am     Reply with quote

Both 'no problem', and 'almost infinite problems'....

Key thing to understand, is that with the CCS 'software UART', the code has to sit doing precise timings and sampling the input pin. Now using the RB0 interrupt, the interrupt triggers to say 'we have a falling edge' (the start bit), and _assuming nothing else at all is happening_, about thirty instruction cycles later you arrive in the interrupt handler. Then the code sits in the 'getc' routine, for the whole of the character time, reading the bits at first 52uSec after arriving at the 'getc', and then every 104uSec for each bit.

Now first problem. If you have another interrupt enabled, and this is called just _before_ the RB0 interrupt triggers, then the arrival in the RB0 interrupt handler, will be delayed by how long the other interrupt takes to handle. Perhaps 90 instructions. So now, the arrival is about 90+30 instructions - 24uSec _late_. Now this is where 'sample early' comes in. This tells the software UART code, to _not_ do the extra delay at the start of the byte. It is needed when using this type of configuration, yet is not enabled in your code....

Then though there are other things that may delay more. 4.084, is one of the compilers, that may be disabling interrupts on printf. I'd have to check (this was one of the problems which appeared, disappeared, re-appeared, with various CCS versions). It is possible to bodge round this, but starts to become rather major. Use buffered TX with interrupt driven hardware serial (ex_stisr.c) and do the GSM printing to this, then make sure that the global interrupt is fully re-enabled in your code.

Change the order that the interrupts are declared, so that INT_RB, is declared first (this gives it priority if two interrupts trigger at the same time).

Then you have the already mentioned problem of sync. The software routine gets called as soon as a falling edge is seen. Now if it is continuously enabled, this should be the first 'start' bit of a byte. However because you disable it, if a byte has already _started_ when the interrupt is re-enabled, you miss the first bit, and instead trigger 'mid byte', on a bit inside the byte. Result 'garbage'. Since it takes longer to loop with all the GSM stuff enabled, this becomes more likely to happen once you enable GSM.

Now, it is undoubtedly 'possible' to do what you are trying to do, _but_ it requires really careful thought at every stage. A full understanding of the times involved in everything, looking at when interrupts are disabled internally, and ensuring that things like the out of sync problem can't occur. However it is a _lot_ of work....
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