Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

GSM Remote problem. Help needed.

Status
Not open for further replies.
Advanced Member level 6
Joined
Dec 4, 2012
Messages
4,280
Helped
822
Reputation
1,654
Reaction score
791
Trophy points
1,393
Location
Bangalore, India
Visit site
Activity points
0
I am doing a GSM Remote control. I am having a problem. The first time I send a command (SMS) like "Y LED ON#" without double quotes then it works but it doesn't work for successive commands (SMSs). My buffer size is 20 bytes. If buffer index reaches max value then it is reset. As the SMS will be the last part of the data received through USRT ISR the SMS (command) gets stored to the buffer. Next I loop till I find 'Y' or 'G' which is the beginning of command and later I loop till I find '#' which is the end of command. I arrange the command in another buffer named temp of same size and terminate the buffer with null character. I compare this buffer with 4 stored messages and if a match occurs then particular LED is turned ON or OFF.

In the real application I replace '#' by '\r' as \r\n is received at the end of read SMS.

Edit: I have removed old code and posted an updated code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// LCD module connections
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
 
sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections
 
#define LED_YELLOW_ON  PORTA.F0 = 1
#define LED_GREEN_ON   PORTA.F1 = 1
#define LED_GREEN_OFF  PORTA.F1 = 0
#define LED_YELLOW_OFF PORTA.F0 = 0
 
typedef unsigned char u8int_t;
 
u8int_t yLEDON[]   = "Y LED ON";
u8int_t yLEDOFF[]  = "Y LED OFF";
u8int_t gLEDON[]   = "G LED ON";
u8int_t gLEDOFF[]  = "G LED OFF";
 
u8int_t buffer[20], temp[20], index = 0, i = 0, j = 0, parseBuff = 0, count = 0;
 
#define BUFFERSIZE 19
 
void Interrupt(){
      if(RCIF_bit){
            if(OERR_bit){
                  CREN_bit = 0;
                  CREN_bit = 1;
                  OERR_bit = 0;
            }
            
            if(index > BUFFERSIZE)index = 0;
            buffer[index++] = RCREG;
            if(buffer[index - 1] == '#')parseBuff = 1;
      }
      
      RCIF_bit = 0;
}
 
void parse(){
    index = 0;
    while((buffer[index] != 'Y') && (buffer[index] != 'G'))index++;
    count = 0;
    while(buffer[index] != '#'){
              temp[count++] = buffer[index++];
              if(index > BUFFERSIZE)index = 0;
    }
    temp[count] = '\0';
    count = 0;
 
}
 
void clearBuffer(){
     for(i = 0; i = BUFFERSIZE; i++){ temp[i] = '\0'; buffer[i] = '\0';}
     i = 0;
     index = 0;
}
 
void main() {
 
    ADCON1 = 0b10000110;
    TRISA = 0x00;
    PORTA = 0x00;
    TRISB = 0x00;
    PORTB = 0x00;
    TRISC = 0xC0;
    PORTC = 0x00;
    
    UART1_Init(9600);
    Delay_ms(200);
    RCIE_bit = 1;
    INTCON = 0xC0;
    UART1_Write_Text("AT+CNMI=3,1,2,1,1\r\n");
 
    Lcd_Init();                        // Initialize LCD
    Lcd_Cmd(_LCD_CLEAR);               // Clear display
    Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
    LCD_Out(1,2,"GSM Remote");
 
    while(1){
    
            if(parseBuff){
                  parse();
                  strcat(temp, "    ");
                  if(strcmp(temp, yLEDON) == 0){LED_YELLOW_ON; LCD_Out(2,1,temp);}
                  if(strcmp(temp, yLEDOFF) == 0){LED_YELLOW_OFF; LCD_Out(2,1,temp);}
                  if(strcmp(temp, gLEDON) == 0){LED_GREEN_ON; LCD_Out(2,1,temp);}
                  if(strcmp(temp, gLEDOFF) == 0){LED_GREEN_OFF; LCD_Out(2,1,temp);}
                  clearBuffer();
                  parseBuff = 0;
            }
    }
}

 

Attachments

  • GSMRemote partly working.rar
    49.9 KB · Views: 99
Last edited:

@Jayanth,

The above code will give trouble as you are validating the buffer inside the ISR...

Instead try the below method.

1. Get the data from the UART ISR and store it in a buffer.
2. Analyse the type of data received in the main routine inside while(1)...For example AT+CNMI is used in your code..So when SMS arrives you will get indication in the ISR routine..Check the result inside your while 1 routine and if SMS had come set a flag..
3. If the smsflag is set then send AT command, AT+CMGR=1<enter>
4. Get the response and store in the buffer where the buffer size should be declared for 160...
5. Validate the buffer inside while1 and take necessary action.
6. After taking action delete the sms using AT command.
 
Should I use AT+CMGR=1\r? Doesn't the modem send the new message directly to UART (micro's Rx)? If not, can the SIM900 be configures to send the new message without expecting a AT+CMGR=1\r? If I have to use AT+CMGR=1\r when response is received then what is the response when new message comes. Foe now, I am testing in Proteus using its VT and not connecting to modem. Why the buffers should be large? I am resetting the buffer and the response like \r\nOK\r\n or SMS like Y LED ON will appear at the end of the data and it will eventually get stored in buffer. Yes, I will use AT+CMGD=index\r to delete the message.


Edit: Do I get +CMTI: "SM",1\r\nOK\r\n or just +CMTI: "SM",1 when a new message arrives? Should I also use AT+CSAS\r to save settings after issuing AT+CNMI\r?
 
Last edited:

@Jayanth,

Unless and until you delete the sms you will get the new SMS with increasing index of '1'.

That's why you should delete the sms before reading the next...

Or there is a work around like when the sms arrives do not worry about the sms index. Instead you can write a routine to read the sms by using AT+CMGR=1, AT+CMGR=2...etc upto 10.

The moment for any command you get only OK as reponse, that means there is no sms for that index and you can come out of the loop.

After this step you can delete the SMS using AT+CMGD="ALL"..

As you dont have any more sms to take action..

When the new sms arrives you will get only CMTI: "SM", SMS_INDEX_NUM...

AT+CSAS command is not needed at all..

The reason i asked you use large buffer is due to the reason, that the SMS content length max by any gsm module is 160 characters.

When you use AT+CMGR=1, then you will additional infos including the SMS data followed by OK.

That is the reason i had asked you to use large buffer size.

Once you obtain the contents of the SMS, then truncate all the unnecessary contents and validate only the original sms data..
 
Here is the updated project. I still have to add EEPROM function to store message index and allow the system to handle 25 messages from SIM. For testing I used mobile instead of SIM900 and so commented out the code related to response check of new message arrival. If somebody can test the code using SIM900 it will be helpful. In the code I am reading message at index 3 and depending on the message (command) received I am controlling LEDs.

101152d1389981637-test.png
 

Attachments

  • GSM Remote v1b.rar
    141 KB · Views: 65
  • test.png
    test.png
    123.1 KB · Views: 105

@Jayanth,

Using of external EEPROM will add up your cost and space in the hardware.

Is SMS index is very important to you? Why do you want to consider the SMS index count?

If it is not important to you then you can avoid the use of EEPROM.

There is an issue when you are reading the SMS.

When you use a micrcontroller to read the SMS using the AT+CMGR command, there will be problem when the number crosses 9(Dec)...

Say for example if you want to read 10th sms from the gsm module through your MCU, 10(dec) cannot be sent from MCU..

Hence for this reason whenever you receive a SMS indication, follow the below steps.

1. Set a flag once you receive the SMS.
2. Have a separate routine to read the SMS. Use a for loop, and send AT+CMGR=i where i = 1 to 9.
3. Once AT+CMGR=i is sent, you will received either entire message with "\r\nOK\r\n" or simply "\r\nOK\r\n".
4. Find the string len of the received reply. If it is greater than 4 that means a valid sms is present. Then process it.
5. If the string length is 4 then it means no valid sms is present and break the for loop and come out of it.
6. After that delete all sms using AT+CMGD="ALL"..
7. If new sms arrives again it will start from position 1.

So in this case you need not worry about SMS index at first place.

Secondly, no data will be missed as you reading the sms individually by sending index count manually.

Third, you are not processing or checking the sms message content inside the interrupt. It should be always processed outside interrupt.

Due to this if any new indications comes it will not be missed.
 
Ok. I will try as you say but you said...

Say for example if you want to read 10th sms from the gsm module through your MCU, 10(dec) cannot be sent from MCU..

I didn't get this.

I store "AT+CMGR=" in a string say cmdATCMGR[]; My index will be stored in eeprom of MCU. I read index of message from eeprom and then convert it to character like if index is 10 then I convert it to '1' and '0' and store it in in another array say


Code C - [expand]
1
2
3
4
tail[0] = '1';
tail[1] = '0';
tail[2] = '\r';
tail[3] = '\0';



Then I use strcat(cmdATCMGR, tail) to Concatanate both strings so, cmdATCMGR becomes "AT+CMGR=10\r". I pass this as argument to my

Code C - [expand]
1
UART1_Write_Text()

function. I hope it will be successful. Then in the response I check for mobile number using strstr(). If it passes then I check for "\r\nOK\r\n". If even this passes then I check for message like "Y LED ON" using strstr(). If it passes then the particular device is controlled.

Here is the sample code. It is not complete yet. I need to add internal eeprom functionality and message index functionality.

I have another problem. There is a initial command to set to SIM memory but if I use the full response string to check the response, it is failing but if I check only for \r\nOK\r\n then it is passing.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// LCD module connections
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
 
sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections
 
#define LED_YELLOW_ON  PORTA.F0 = 1
#define LED_GREEN_ON   PORTA.F1 = 1
#define LED_GREEN_OFF  PORTA.F1 = 0
#define LED_YELLOW_OFF PORTA.F0 = 0
 
typedef unsigned char uint8_t;
 
uint8_t cmd1[] = "AT+CNMI=3,1,2,1,1\r";
uint8_t cmd2[] = "AT+CPMS=\"SM\",\"SM\",\"SM\"\r";
uint8_t yLEDON[]   = "Y LED ON";
uint8_t yLEDOFF[]  = "Y LED OFF";
uint8_t gLEDON[]   = "G LED ON";
uint8_t gLEDOFF[]  = "G LED OFF";
uint8_t response[] = "+CMTI: \"SM\",";
uint8_t number[] = "91974245xxxx";
 
uint8_t buffer[160], index = 0, i = 0, parseBuff = 0;
 
#define BUFFERSIZE 159
 
void Interrupt(){
      if(RCIF_bit){
            if(OERR_bit){
                  //CREN_bit = 0;
                  CREN_bit = 1;
                  //OERR_bit = 0;
            }
 
            if(index > BUFFERSIZE)index = 0;
            buffer[index++] = RCREG;
            buffer[index] = '\0';
            if(buffer[index - 1] == '\n')parseBuff++;       //increment once when CMTI: SM, x\r\n is received
                                                            //Increment second time when response to AT+CMGR=x is received
      }
 
      RCIF_bit = 0;
}
 
void main() {
 
    ADCON1 = 0b10000110;
    TRISA = 0x00;
    PORTA = 0x00;
    TRISB = 0x00;
    PORTB = 0x00;
    TRISC = 0x80;
    PORTC = 0x00;
 
    UART1_Init(9600);
    Delay_ms(200);
    RCIE_bit = 1;
    INTCON = 0xC0;
    
    Lcd_Init();                        // Initialize LCD
    Lcd_Cmd(_LCD_CLEAR);               // Clear display
    Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
    LCD_Out(1,1,"GSM Remote");         // Display message on line 1
    
    while(strstr(buffer, "AT+CNMI=3,1,2,1,1\r\r\nOK\r\n") == 0){   //24 chars
        UART1_Write_Text(cmd1);
        Delay_ms(2000);
    }
    i = 0;
    while(buffer[i])buffer[i++] = '\0';
    index = 0;
    while(strstr(buffer, "\r\nOK\r\n") == 0){ //"AT+CPMS=\"SM\",\"SM\",\"SM\"\r\r\n+CPMS: 2, 25, 2, 25, 2, 25\r\r\nOK\r\n"      //58 chars
                  UART1_Write_Text("AT+CPMS=\"SM\",\"SM\",\"SM\"\r");
                  Delay_ms(4000);
    }
    i = 0;
    while(buffer[i])buffer[i++] = '\0';
    index = 0;
    while(1){
 
            if(parseBuff){
                  if(strstr(buffer, response) == 0){
                         parseBuff = 0;                 //reset to check for new message arrival
                         i = 0;
                         while(buffer[i])buffer[i++] = '\0';
                         index = 0;
                  }
                  else{
                       i = 0;
                       while(buffer[i])buffer[i++] = '\0';
                       index = 0;
                       UART1_Write_Text("AT+CMGR=1\r"); //Send AT+CMGR=1, Always check message at index 1
                       Delay_ms(3000);                  //Wait for 3 seconds
                       if(strstr(buffer, number)){
                                if(strstr(buffer, "OK")){
                                            if(strstr(buffer, yLEDON)){LED_YELLOW_ON; LCD_Out(2,1,"Y LED ON ");}
                                            else if(strstr(buffer, yLEDOFF)){LED_YELLOW_OFF; LCD_Out(2,1,"Y LED OFF");}
                                            else if(strstr(buffer, gLEDON)){LED_GREEN_ON; LCD_Out(2,1,"G LED ON ");}
                                            else if(strstr(buffer, gLEDOFF)){LED_GREEN_OFF; LCD_Out(2,1,"G LED OFF");}
                                            index = 0;
                                            UART1_Write_Text("AT+CMGD=1\r");
                                }
                       }
                  }
 
            }
 
    }
}



101169d1390030537-response3.png
 

Attachments

  • response3.png
    response3.png
    94.7 KB · Views: 93
Last edited:

I store "AT+CMGR=" in a string say cmdATCMGR[]; My index will be stored in eeprom of MCU. I read index of message from eeprom and then convert it to character like if index is 10 then I convert it to '1' and '0' and store it in in another array say

My suggestion was to avoid totally the usage of EEPROM...Hence i had asked you to use for loop.

See this below example...which i had written for some other project...


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
for(MsgCnt=1;MsgCnt<=10;MsgCnt++)
{
     fl_memset(TempRcvBuf, 0x00, sizeof(TempRcvBuf));   
    
     fl_memset(Rcvd_SMSBuf, 0x00, sizeof(Rcvd_SMSBuf));             
                
     UART_DEBUG(cmdCMGR,"\n");                                  //for hyperterminal
     UART_MODEM((u8*)cmdCMGR,fl_strlen(cmdCMGR));    //for modem
     fl_itoa(MsgCnt,MsgStr,16);         
            
     if(MsgCnt<=9)
    {
     UART_DEBUG("%d",MsgCnt);   
     UART_MODEM((u8 *)MsgStr,1);                                 
    }
    else if(MsgCnt == 10)
    {
    UART_DEBUG("10");
    UART_MODEM("10",fl_strlen("10"));            
     }
     UART_MODEM("\r",fl_strlen("\r"));
 
     if(uart_result_validate==OK)    //check if the received string contains "OK"
    {
                    
     if (fl_strlen(TempRcvBuf) > 6)   //check if the read buffer is greater than strlen 6
     {
        Validate_SMS();             //now validate the content of the message...        
        SMSPresent=TRUE;                         
     }              
     else
     {
        break;                         //if "\r\nOK\r\n" is received then just break from the for loop....
    }
   }
}



Also donot use sim memory for these functions as it might give trouble...I havent used any such thing so far..
 
Last edited by a moderator:
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top