|
|
View previous topic :: View next topic |
Author |
Message |
Akhil Thomas
Joined: 11 Dec 2013 Posts: 5
|
GPS-GSM on pic16f8773a using sw uart on RB0 |
Posted: Sun Mar 09, 2014 7:02 am |
|
|
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: 9228 Location: Greensville,Ontario
|
|
Posted: Sun Mar 09, 2014 9:27 am |
|
|
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
|
|
Posted: Mon Mar 10, 2014 10:16 am |
|
|
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: 19515
|
|
Posted: Mon Mar 10, 2014 10:34 am |
|
|
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
|
|
Posted: Mon Mar 10, 2014 12:14 pm |
|
|
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
|
|
Posted: Mon Mar 10, 2014 12:17 pm |
|
|
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
|
|
Posted: Mon Mar 10, 2014 12:27 pm |
|
|
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: 9228 Location: Greensville,Ontario
|
|
Posted: Mon Mar 10, 2014 12:57 pm |
|
|
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
|
|
Posted: Mon Mar 10, 2014 11:19 pm |
|
|
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: 19515
|
|
Posted: Tue Mar 11, 2014 1:38 am |
|
|
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.... |
|
|
|
|
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
|