View previous topic :: View next topic |
Author |
Message |
davidroux
Joined: 19 Jul 2009 Posts: 11
|
[Urgent] GSM Project - SIM Resetting (GSM.Vcc to GSM.GND) |
Posted: Fri Oct 30, 2009 1:38 am |
|
|
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
|
|
Posted: Fri Oct 30, 2009 8:34 am |
|
|
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();
} |
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
|
|
Posted: Fri Oct 30, 2009 9:13 am |
|
|
Hey thanks for the reply
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 |
|
|
davidroux
Joined: 19 Jul 2009 Posts: 11
|
|
Posted: Sat Oct 31, 2009 8:55 am |
|
|
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
|
|
Posted: Sun Nov 01, 2009 11:26 am |
|
|
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
|
|
Posted: Sun Nov 01, 2009 3:53 pm |
|
|
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
|
|
Posted: Sun Nov 01, 2009 11:42 pm |
|
|
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 gave me the idea. Now gonna clean up this "
rats nest" of code and make neat using ISR's etc. |
|
|
bdeb Guest
|
|
Posted: Wed Nov 18, 2009 12:41 am |
|
|
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 |
|
|
|