AT Commands Send SMS - Tinysine GSM Module

Hi everyone

I got a Tinysine GSM/GPRS Shield with SIM900 (total newb on this one) trying to get it to work with AT commands. I have gone through all examples given by the manufacturer at their website, with an Arduino UNO and a Mega 2560 all under great success.

Unfortunately there some things I want to do in the future regarding the GPRS FTP file transfers which I cannot locate how these can be implemented with the Tinysine GSM/GPRS shield. That is why I turned over to AT Commands where a plethora of code examples are at hand.

The problem I faced was that even when I tried to send a simple SMS totaly relying upon AT commands I failed big. I though that AT commands are solving the need of libraries, storage and compatibility around all SIM900 modules since they are "just serial" because these are common instructions across all manufacturers.

I used the code below but couldn't send anything

/*  
 *  GPRS/GSM Quadband Module (SIM900)
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  a
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           2.0
 *  Design:            David Gascón 
 *  Implementation:    Alejandro Gallego & Marcos Martinez
 */

int8_t answer;
int onModulePin= 2;
char aux_string[30];
char phone_number[]="+***********";   // ********* is the number to call
char pin[] = "****";
char sms_text[]="Test-Arduino-Hello World";     

void setup(){

    pinMode(onModulePin, OUTPUT);
    Serial.begin(9600);    
        
    Serial.println("Starting...");
    power_on();
    
    delay(3000);
    
    // sets the PIN code
    sprintf(aux_string, "AT+CPIN=%s", pin);
    sendATcommand(aux_string, "OK", 2000);
    
    delay(3000);
    
    Serial.println("Connecting to the network...");

    while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || 
            sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );

    Serial.print("Setting SMS mode...");
    sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
    Serial.println("Sending SMS");
    
    sprintf(aux_string,"AT+CMGS=\"%s\"", phone_number);
    answer = sendATcommand(aux_string, ">", 2000);    // send the SMS number
    if (answer == 1)
    {
        Serial.println(sms_text);
        Serial.write(0x1A);
        answer = sendATcommand("", "OK", 20000);
        if (answer == 1)
        {
            Serial.print("Sent ");    
        }
        else
        {
            Serial.print("error ");
        }
    }
    else
    {
        Serial.print("error ");
        Serial.println(answer, DEC);
    }

}


void loop(){

}

void power_on(){

    uint8_t answer=0;
    
    // checks if the module is started
    answer = sendATcommand("AT", "OK", 2000);
    if (answer == 0)
    {
        // power on pulse
        digitalWrite(onModulePin,HIGH);
        delay(3000);
        digitalWrite(onModulePin,LOW);
    
        // waits for an answer from the module
        while(answer == 0){     // Send AT every two seconds and wait for the answer
            answer = sendATcommand("AT", "OK", 2000);    
        }
    }
    
}

int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout){

    uint8_t x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '\0', 100);    // Initialice the string
    
    delay(100);
    
    while( Serial.available() > 0) Serial.read();    // Clean the input buffer
    
    Serial.println(ATcommand);    // Send the AT command 


    x = 0;
    previous = millis();

    // this loop waits for the answer
    do{
        // if there are data in the UART input buffer, reads it and checks for the asnwer
        if(Serial.available() != 0){    
            response[x] = Serial.read();
            x++;
            // check if the desired answer is in the response of the module
            if (strstr(response, expected_answer) != NULL)    
            {
                answer = 1;
            }
        }
    // Waits for the asnwer with time out
    }while((answer == 0) && ((millis() - previous) < timeout));    

    return answer;
}

I know that this is for a libelium GSM shield but still these are all plain AT Commands. Can anyone please inform me why I failed so big in both UNO and Mega 2560... apart from being noob!

Is it something that has to do with just RX,TX pins cause I have tried many different things but still... failure.

I know that it has nothing to do with baud rate cause they are synced at 9600 both Arduino and Tinysine GSM module. I have also crosschecked with the AT+IPR? command.

I have tried to write all required AT commands through Arduino's serial monitor but unfortunately ctrl-z cannot be written in either form hex or otherwise therefore I cannot send an SMS manually. I have succeeded through another serial terminal but not with Arduino IDE 1.0.6 (required for Tinysine GSM library) serial monitor. Why is that?

Hi everyone,

after the lack of luck on having an easy way of sending an SMS directly from AT commands and while no-one replied to my message I scrutinized over the code even more carefully and found some errors that were holding my Arduino and Tinysine GSM/GPRS module to function correctly. Most of the code is the same to the original I only made it more stable or persistent.

I removed the SIM Card's PIN variable in my case since I had removed the PIN security from SIM card. In case someone wants such security just uncomment the variable and the related AT command.

The original code wasn't working for me for a couple of reasons...

  • onModulePin was set as OUTPUT but it is actually an INPUT in my case, since I control power On or Off over that pin 8, you can also set it to pin 9 which is the reset button, I have not tested that yet but I most certain that it will work as well,
  • for some apparent reason the Tinysine GSM/GPRS module was not that stable with one of the SIM cards I tested. Probably there was a problem with the operator at that time but still I think the Tinysine GSM/GPRS module must share part of the blame since in the early testing the module was stuck on the power_on state, sending an "AT", expecting an "OK" that never actually came, I had to manually press the Arduino_reset button a couple of times before it works and it is easily understood this is not due to the Arduino but due to the Tinysine. I will see into it in the future,
  • I changed the code in order to power off the GSM/GPRS module once the message is actually sent,
  • I changed the code in order to make it more persistent, so that if the SMS message is not sent, the Arduino will continue to try and send it again and again. If the message is finally sent, the module will then be power off.

!!! DO NOT FORGET TO CHANGE THE JUMPERS IN ORDER TO USE HW SERIAL NOT SW

Have fun with it

/*  
 *  GPRS/GSM Quadband Module (SIM900)
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  a
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           2.0
 *  Design:            David Gascón 
 *  Implementation:    Alejandro Gallego & Marcos Martinez
 */

int8_t answer;
int onModulePin= 8;
char aux_string[30];
char phone_number[]="+*************";   // ********* is the number to call, always with a + for the country code e.g. for UK +44
//char pin[] = "";
char sms_text[]="Hi Publius... holly shit your Arduino code finally works -- Grab a beer";     

void setup(){

    pinMode(onModulePin, INPUT);
    Serial.begin(9600);    
              
    Serial.println("Starting...");
    power_on();
    
    delay(3000);
    
    // sets the PIN code
    //sprintf(aux_string, "AT+CPIN=%s", pin);
    //sendATcommand(aux_string, "OK", 2000);
    
    //delay(3000);
    
    Serial.println("Connecting to the network...");

    while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) || 
            sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );

    Serial.print("Setting SMS mode...");
    sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
        
    sendSMS();


    
}

void loop(){

}

void power_on(){

    uint8_t answer=0;
    
    // checks if the module is started
    answer = sendATcommand("AT", "OK", 2000);
    if (answer == 0)
    {
        // power on pulse
        digitalWrite(onModulePin,HIGH);
        delay(1500);
        digitalWrite(onModulePin,LOW);
        delay(3000);
    
        // waits for an answer from the module
        while(answer == 0){     // Send AT every two seconds and wait for the answer
            answer = sendATcommand("AT", "OK", 2000);    
        }
    }
    
}

  void power_off(){
    digitalWrite(onModulePin, HIGH);
    delay(1500);
    digitalWrite(onModulePin, LOW);
  }

int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout){

    uint8_t x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '\0', 100);    // Initialize the string
    
    delay(100);
    
    while( Serial.available() > 0) Serial.read();    // Clean the input buffer
    
    Serial.println(ATcommand);    // Send the AT command 


    x = 0;
    previous = millis();

    // this loop waits for the answer
    do{
        // if there are data in the UART input buffer, reads it and checks for the asnwer
        if(Serial.available() != 0){    
            response[x] = Serial.read();
            x++;
            // check if the desired answer is in the response of the module
            if (strstr(response, expected_answer) != NULL)    
            {
                answer = 1;
            }
        }
    // Waits for the asnwer with time out
    }while((answer == 0) && ((millis() - previous) < timeout));    

    return answer;
}

  
  void sendSMS(){
    Serial.println("Sending SMS");
    sprintf(aux_string,"AT+CMGS=\"%s\"", phone_number);
    answer = sendATcommand(aux_string, ">", 2000);    // send the SMS number
    if (answer == 1)
    {
        Serial.println(sms_text);
        Serial.write(0x1A);
        answer = sendATcommand("", "OK", 20000);  // give it time to be able to send and get a reply
        if (answer == 1)
        {
            Serial.print("Sent ");
            power_off();    
        }
        else
        {
            Serial.print("SMS not sent ");
            sendSMS();
            power_off();
        }
    }
    else
    {
        Serial.print("error ");
        Serial.println(answer, DEC);
        sendSMS();
        power_off();
    }
  }

This code is tested ONLY with an Arduino UNO. I will in the following days test it with a MEGA 2560 but I think it will work as well... its serial after all... that's Serial1, BTW.

!!! UPDATE

I have tested the same code with Arduino Mega 2560 on both serial 0 and 1 and it works great. Remember if you want to use serial 1, just change alike (from Serial to Serial1)

To connect to Arduino Mega 2560 serial 1 (2 or 3), remove the jumpers on the Tinysine GSM/GPRS module. Connect the middle pin of both RX and TX to the RX1 and TX1 of the Arduino. Pay attention to the reading of the Tinysine GSM/GPRS RX/TX, these mean that the corresponding pins should connect to RX and TX respectively NOT that they provide RX and TX. So connect Tinysine GSM/GPRS shield RX to Arduino Mega 2560 RX1 and the GSM/GPRS TX to the Mega2560 TX1. Othewise it will not send anything. Same goes for Serial2 and Serial3.

Publius:
Hi everyone,

after the lack of luck on having an easy way of sending an SMS directly from AT commands and while no-one replied to my message I scrutinized over the code even more carefully and found some errors that were holding my Arduino and Tinysine GSM/GPRS module to function correctly. Most of the code is the same to the original I only made it more stable or persistent.

I removed the SIM Card's PIN variable in my case since I had removed the PIN security from SIM card. In case someone wants such security just uncomment the variable and the related AT command.

The original code wasn't working for me for a couple of reasons...

  • onModulePin was set as OUTPUT but it is actually an INPUT in my case, since I control power On or Off over that pin 8, you can also set it to pin 9 which is the reset button, I have not tested that yet but I most certain that it will work as well,
  • for some apparent reason the Tinysine GSM/GPRS module was not that stable with one of the SIM cards I tested. Probably there was a problem with the operator at that time but still I think the Tinysine GSM/GPRS module must share part of the blame since in the early testing the module was stuck on the power_on state, sending an "AT", expecting an "OK" that never actually came, I had to manually press the Arduino_reset button a couple of times before it works and it is easily understood this is not due to the Arduino but due to the Tinysine. I will see into it in the future,
  • I changed the code in order to power off the GSM/GPRS module once the message is actually sent,
  • I changed the code in order to make it more persistent, so that if the SMS message is not sent, the Arduino will continue to try and send it again and again. If the message is finally sent, the module will then be power off.

!!! DO NOT FORGET TO CHANGE THE JUMPERS IN ORDER TO USE HW SERIAL NOT SW

Have fun with it

/*  
  • GPRS/GSM Quadband Module (SIM900)
  • Copyright (C) Libelium Comunicaciones Distribuidas S.L.
  • http://www.libelium.com
  • This program is free software: you can redistribute it and/or modify
  • it under the terms of the GNU General Public License as published by
  • the Free Software Foundation, either version 3 of the License, or
  • (at your option) any later version.
  • a
  • This program is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  • GNU General Public License for more details.
  • You should have received a copy of the GNU General Public License
  • along with this program.  If not, see Licenses - GNU Project - Free Software Foundation.
  • Version:           2.0
  • Design:            David Gascón
  • Implementation:    Alejandro Gallego & Marcos Martinez
    */

int8_t answer;
int onModulePin= 8;
char aux_string[30];
char phone_number[]="+*************";   // ********* is the number to call, always with a + for the country code e.g. for UK +44
//char pin[] = "";
char sms_text[]="Hi Publius... holly shit your Arduino code finally works -- Grab a beer";

void setup(){

pinMode(onModulePin, INPUT);
   Serial.begin(9600);    
             
   Serial.println("Starting...");
   power_on();
   
   delay(3000);
   
   // sets the PIN code
   //sprintf(aux_string, "AT+CPIN=%s", pin);
   //sendATcommand(aux_string, "OK", 2000);
   
   //delay(3000);
   
   Serial.println("Connecting to the network...");

while( (sendATcommand("AT+CREG?", "+CREG: 0,1", 500) ||
           sendATcommand("AT+CREG?", "+CREG: 0,5", 500)) == 0 );

Serial.print("Setting SMS mode...");
   sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
       
   sendSMS();

}

void loop(){

}

void power_on(){

uint8_t answer=0;
   
   // checks if the module is started
   answer = sendATcommand("AT", "OK", 2000);
   if (answer == 0)
   {
       // power on pulse
       digitalWrite(onModulePin,HIGH);
       delay(1500);
       digitalWrite(onModulePin,LOW);
       delay(3000);
   
       // waits for an answer from the module
       while(answer == 0){     // Send AT every two seconds and wait for the answer
           answer = sendATcommand("AT", "OK", 2000);    
       }
   }
   
}

void power_off(){
   digitalWrite(onModulePin, HIGH);
   delay(1500);
   digitalWrite(onModulePin, LOW);
 }

int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout){

uint8_t x=0,  answer=0;
   char response[100];
   unsigned long previous;

memset(response, '\0', 100);    // Initialize the string
   
   delay(100);
   
   while( Serial.available() > 0) Serial.read();    // Clean the input buffer
   
   Serial.println(ATcommand);    // Send the AT command

x = 0;
   previous = millis();

// this loop waits for the answer
   do{
       // if there are data in the UART input buffer, reads it and checks for the asnwer
       if(Serial.available() != 0){    
           response[x] = Serial.read();
           x++;
           // check if the desired answer is in the response of the module
           if (strstr(response, expected_answer) != NULL)    
           {
               answer = 1;
           }
       }
   // Waits for the asnwer with time out
   }while((answer == 0) && ((millis() - previous) < timeout));

return answer;
}

void sendSMS(){
   Serial.println("Sending SMS");
   sprintf(aux_string,"AT+CMGS="%s"", phone_number);
   answer = sendATcommand(aux_string, ">", 2000);    // send the SMS number
   if (answer == 1)
   {
       Serial.println(sms_text);
       Serial.write(0x1A);
       answer = sendATcommand("", "OK", 20000);  // give it time to be able to send and get a reply
       if (answer == 1)
       {
           Serial.print("Sent ");
           power_off();    
       }
       else
       {
           Serial.print("SMS not sent ");
           sendSMS();
           power_off();
       }
   }
   else
   {
       Serial.print("error ");
       Serial.println(answer, DEC);
       sendSMS();
       power_off();
   }
 }




This code is tested ONLY with an Arduino UNO. I will in the following days test it with a MEGA 2560 but I think it will work as well... its serial after all... that's Serial**1**, BTW.




!!! UPDATE

I have tested the same code with Arduino Mega 2560 on both serial 0 and 1 and it works great. Remember if you want to use serial 1, just change alike (from Serial to Serial1)

To connect to Arduino Mega 2560 serial 1 (2 or 3), remove the jumpers on the Tinysine GSM/GPRS module. Connect the middle pin of both RX and TX to the RX1 and TX1 of the Arduino. Pay attention to the reading of the Tinysine GSM/GPRS RX/TX, these mean that the corresponding pins should connect to RX and TX respectively NOT that they provide RX and TX. So connect Tinysine GSM/GPRS shield RX to Arduino Mega 2560 RX1 and the GSM/GPRS TX to the Mega2560 TX1. Othewise it will not send anything. Same goes for Serial2 and Serial3.

i used your code but it didn't work , no call and sms sent

hello how did you make work arduino mega with gsm module i try a lot to find the way to make it works but i didnt find anything

You may discover more by looking at the SIM900 AT command reference

There are simple worked examples of the command needed to send SMS and FTP transfers.

Keep in mind, your 2G modem may only work for another 12 months, as the 2G networks begin to shutdown from Christmas 2016 onwards.