send sms after receiving sms using sim900

Hello. Can you guys help me with my codes, I can’t figure out how to code the part where the module will only reply to me whenever I send an SMS to the module(content of the message does not matter). The thing is, when I upload my codes, I won’t stop sending me “TEST” sms. I want it to be like stay in wait mode until I send an SMS then reply to me the TEST sms and then be on the wait mode again. sorry for bad english. Please help, I need it for my project.

Here’s my code:

#include <SoftwareSerial.h>

SoftwareSerial SIM900(7, 8);
 
void setup(){
  
  SIM900.begin(19200);
  delay(10000);
  SIM900.print("AT+CMGF=1\r");
  delay(100);
  SIM900.println("AT+CNMI=2,2,0,0,0"); // AT Command to receive a live SMS
  delay(1000);

}


void sendSMS(){
  
  SIM900.print("AT+CMGF=1\r");
  delay(100);
  SIM900.println("AT + CMGS = \"mynumberhere\"");
  delay(100);   
  SIM900.print("Test");
  delay(100);
  SIM900.println((char)26);                                                         
  delay(100);
  SIM900.println();
  delay(5000);
} 


void loop() {

    if(SIM900.available() >0){
      sendSMS();
      }  
}

Your line if(SIM900.available() >0) tests whether there is any data in the incoming buffer. Even if no SMS has been received there will be stuff in the buffer after startup such as unsolicited result codes (I would check your AT settings to minimise these).

This data will stay in the buffer until you read it. Therefore if you don't read it (or clear it some other way) the line if(SIM900.available() >0) will always be true and you will keep sending SMS messages.

After startup you should have a line like while(SIM900.available() > 0) SIM900.read());

Wait a few seconds for the SIM900 to join the cell network, as you will get some connection status codes from the SIM900, and repeat the line again.

During testing I use while(SIM900.available() > 0) Serial.print((char)SIM900.read()); so that I can (a) see what is coming through and (b) know when all the SIM900 guff has stopped coming through and only what I want is about to come through. This allows you to fine tune the period to wait before clearing out the buffer.

I put the SIM900 on the hardware serial port for reliable buffering and throughput as the module can spew out a fair bit of stuff and overflow the buffers if you are not rigorous with the polling. Setting the modules baud rate to 9600-19200 also helps with the polling/parsing as your sketch grows beyond the proof-of-concept stage.

I strongly suggest that you SMS a specific character (e.g. "^") that is not included in the response codes of the SIM900. Then you can search for this as you clear out the buffer. If you find the "^" you respond other wise dump the char. If you clear the buffer at startup like I suggest above, then 10 minutes later there may be a change in network status and you will receive a status notification. The sketch will start sending messages non stop. Similarly if someone SMS the wrong number and you receive their message, you will send start sending SMS again. Remember to clear the buffer after sending the SMS. Also you may receive a status on whether the SMS went OK or not. This will trigger a new round of SMS. Clear the buffer after sending.

lemming:
During testing I use
Code: [Select]

while(SIM900.available() > 0) Serial.print((char)SIM900.read());

so that I can (a) see what is coming through and (b) know when all the SIM900 guff has stopped coming through and only what I want is about to come through. This allows you to fine tune the period to wait before clearing out the buffer.

I've put this code in my Main loop now

while(SIM900.available() >0){
      incoming_char=SIM900.read();
      Serial.print(incoming_char); 
      
      if(incoming_char == 'x'){
        sendSMS();
        }
      }

and I think it is working now the way I want to. but instead of using "^" as you suggested, somehow it doesn't work for me and so I tried using "x" instead and it works fine now. thanks a lot for your help !

Just make sure that there are no "x"s in any of the SIM900’s result codes or it may send prematurely and unexpectedly.
That is why I used the “^” character as it is unlikely to be used in text and isn’t in the result codes. I would suggest using any character except a-z, numbers, and common punctuation marks. Remember to turn off echo (ATE command) and result codes if you don’t use them.

Also I find it good practice to clear the buffer once you have received the character (“x” in your case) you are looking for. While you are off sending the SMS there is probably more guff coming in, and at 115200 baud that buffer may overflow not allowing that next “x” or relevant data to come in .

The are several fields coming back in a received SMS and only one of those is data. It would be best practice to ignore those non-data fields so you don’t get snafus in your logic when it reads an “x” from a non-intended field.

I use the following to break the incoming message into its constituent parts.

char InBuffer[80];
char delimiters[] = {',', '\0'};
char *Command;
char *Preamble;
char *Status;
char *PhoneNo;
char *Sundry;
char *Date;
char *Time;
char *Text;

boolean CheckSMS()
{
  if(Serial.available() > 0)
  {
    int i = 0;
    char lastchar = 'A';
    char temp;    
    for(int x = 0; x < 80; x++)
    {
      InBuffer[x] = '\0';
    }
    delay(60);
    
    while(Serial.available() > 0 && i < 80)
    {      
      char temp = Serial.read();      
      if(temp == 0x0A && i > 2) temp = ',';  //  LF
      if(temp == 0x2B && i > 9) temp = ',';  //  +
      if(temp == 0x3A && i < 9) temp = ',';  //  :
      if(temp == 0x0D) temp = 0x20;          //  CR
      if(temp == 0x0A) temp = 0x20;          //  LF
      
      if((temp == 0x22) && (lastchar == 0x22))  //  "
      {
        InBuffer[i++] = 0x20;        
        lastchar = temp;
        temp = 0x20;
      }
      else if(temp == 0x22)
      {
        lastchar = temp;
        temp = 0x20;
      }      
      if((temp != 0x20))
      {
        InBuffer[i++] = temp;
        lastchar = temp;
      }
    }
    InBuffer[i] = '\0';
    SS1.println(InBuffer);
    if(Splitter())
    {
      return(true);
    }
    else return(false);
  }
  return(false);
}

boolean Splitter()
{
  Command = strtok(InBuffer, delimiters);    
  PhoneNo = strtok(NULL, delimiters);
  Preamble = strtok(NULL, delimiters);    
  Date = strtok(NULL, delimiters);
  Time = strtok(NULL, delimiters);
  Sundry = strtok(NULL, delimiters);
  Text = strtok(NULL, delimiters);
  Status = strtok(NULL, delimiters);
  SS1.print("Command/Status: ");
  SS1.println(Command);    
  SS1.print("Phone No.: ");
  SS1.println(PhoneNo);
  SS1.print("Preamble: ");
  SS1.println(Preamble);    
  SS1.print("Date: ");
  SS1.println(Date);
  SS1.print("Time: ");
  SS1.println(Time);    
  SS1.print("Sundry: ");
  SS1.println(Sundry);
  SS1.print("Text: ");
  SS1.println(Text);
  SS1.print("Status: ");
  SS1.println(Status);
  strcpy(PumpCommand, Text);
  strcpy(Sender, PhoneNo);
  //SS1.println(PumpCommand);
  //SS1.println(Sender);
  return(true);  
}

The first part accepts the data into a buffer and cleans up the string before passing it on to the strtok() function to split it into the various fields. It makes the data very simple to work with and no ambiguity when it comes to which field the “x” actually came from. It comes in handy if you want to return an SMS to whichever number sends you an SMS.

The code above is snippets from my larger program (and is a bit rough) so probably won’t compile. I’ll let you fill in the missing bits if you want to use it and remove the bunch of print statements. Can’t make it too easy. :slight_smile: