GSM/GPRS modems are getting very common these days, as prices are getting cheaper and cheaper. Apart from providing SMS and call functions to my projects I also wanted to communicate via TCP.
Although there are many documents and blog posts to help but I have always found that they either are answers to specific problem faced by someone or not providing complete details. In this post I would first explain the AT commands used in brief. You may connect your SIM900 to your computer via a serial/usb and test these commands. In the later part of this post I would include arduino example code.
AT commands for TCP/UDP Connection with example response and a brief description are given in the table below. Refer to the AT commands manual of your modem for details
AT command |
Response |
Description |
AT |
OK |
test command. reply is OK |
AT+CGATT? |
+CGATT:n |
checks if GPRS is attached? n=1 if attached |
AT+CIPMUX=n |
OK |
use n as 0 for single connection
or use 1 for multiple connections |
AT+CSTT=”apn”,”username”,”pass” |
OK |
Sets APN, user name and password |
AT+CIICR |
OK |
Brings up wireless connection |
AT+CIFSR |
ip address |
Get local IP address if connected |
AT+CIPSTART=“TYPE” , “domain”, “port” |
Connected |
Establishes a connection with a server. Type can be UDP or TCP |
AT+CIPSEND |
> |
Sends data when the a connection is established. |
AT+CIPCLOSE |
OK |
Closes the connection |
AT+CIPSHUT |
SHUT OK |
resets IP session if any |
how to make a connection:
- Send ATr and wait for a response from the modem. You should recieve OK
if everything is set.
- Make sure that the Modem has registered to network and that PIN code is disabled on the SIM. Send AT+CGATT?r to check if GPRS is attached or not. +CGATT: 1 indicates that GPRS is attached.
- Send AT+CIPSHUTr . Although its optional this will be helpful as it resets IP session if any. you will get a response SHUT OK .
- Send AT+CIPMUX=0 to set a single connection mode, response would be OK
- Now set APN settings by AT+CSTT= “apn ”, “username”, “password”r . replace apn, username and password to match APN (Access Point Name) ,username and password for your service provider.
- Now send AT+CIICRr , this will bring up the wireless connection. OK is received on successful connection
- Send AT+CIFSRr , this will reply with the IP address the modem has been assigned.
- Send AT+CIPSTART=”TCP”,”server domain name or ip”,”port”r, replace the domain name/ip and port with appropriate values, on connection modem will reply with CONNECT OK
- Now you can send your data using AT+CIPSENDr AT command. modem will respond with > indicating it is ready to receive data to be sent. Type in your data.
- Now the modem is waiting for the ASCII 26 that is control+z on keyboard. Depending on the terminal software used you can either press control and Z together on keyboard or send hex value 0x1A. The modem will then send the response from server.
- Now send AT+CIPSHUT to shut down the connection. Modem will reply with SHUT OK
- cheers 🙂
ARDUINO CODE :
Below is example code for single and multiple connection using arduino and sim900
int8_t answer;
int onModulePin= 2;
char aux_str[50];
char ip_data[40]="Test string from GPRS shieldrn";
void setup(){
pinMode(onModulePin, OUTPUT);
Serial.begin(115200);
Serial.println("Starting...");
power_on();
delay(3000);
// sets the PIN code
sendATcommand2("AT+CPIN=****", "OK", "ERROR", 2000);
delay(3000);
Serial.println("Connecting to the network...");
while( sendATcommand2("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000)== 0 );
}
void loop(){
// Selects Single-connection mode
if (sendATcommand2("AT+CIPMUX=0", "OK", "ERROR", 1000) == 1)
{
// Waits for status IP INITIAL
while(sendATcommand2("AT+CIPSTATUS", "INITIAL", "", 500) == 0 );
delay(5000);
// Sets the APN, user name and password
if (sendATcommand2("AT+CSTT="APN","user_name","password"", "OK", "ERROR", 30000) == 1)
{
// Waits for status IP START
while(sendATcommand2("AT+CIPSTATUS", "START", "", 500) == 0 );
delay(5000);
// Brings Up Wireless Connection
if (sendATcommand2("AT+CIICR", "OK", "ERROR", 30000) == 1)
{
// Waits for status IP GPRSACT
while(sendATcommand2("AT+CIPSTATUS", "GPRSACT", "", 500) == 0 );
delay(5000);
// Gets Local IP Address
if (sendATcommand2("AT+CIFSR", ".", "ERROR", 10000) == 1)
{
// Waits for status IP STATUS
while(sendATcommand2("AT+CIPSTATUS", "IP STATUS", "", 500) == 0 );
delay(5000);
Serial.println("Openning TCP");
// Opens a TCP socket
if (sendATcommand2("AT+CIPSTART="TCP","IP_address","port"",
"CONNECT OK", "CONNECT FAIL", 30000) == 1)
{
Serial.println("Connected");
// Sends some data to the TCP socket
sprintf(aux_str,"AT+CIPSEND=%d", strlen(ip_data));
if (sendATcommand2(aux_str, ">", "ERROR", 10000) == 1)
{
sendATcommand2(ip_data, "SEND OK", "ERROR", 10000);
}
// Closes the socket
sendATcommand2("AT+CIPCLOSE", "CLOSE OK", "ERROR", 10000);
}
else
{
Serial.println("Error openning the connection");
}
}
else
{
Serial.println("Error getting the IP address");
}
}
else
{
Serial.println("Error bring up wireless connection");
}
}
else
{
Serial.println("Error setting the APN");
}
}
else
{
Serial.println("Error setting the single connection");
}
sendATcommand2("AT+CIPSHUT", "OK", "ERROR", 10000);
delay(10000);
}
void power_on(){
uint8_t answer=0;
// checks if the module is started
answer = sendATcommand2("AT", "OK", "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 = sendATcommand2("AT", "OK", "OK", 2000);
}
}
}
int8_t sendATcommand2(char* ATcommand, char* expected_answer1,
char* expected_answer2, unsigned int timeout){
uint8_t x=0, answer=0;
char response[100];
unsigned long previous;
memset(response, ' ', 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 1 is in the response of the module
if (strstr(response, expected_answer1) != NULL)
{
answer = 1;
}
// check if the desired answer 2 is in the response of the module
else if (strstr(response, expected_answer2) != NULL)
{
answer = 2;
}
}
}
// Waits for the asnwer with time out
while((answer == 0) && ((millis() - previous) < timeout));
return answer;
}
int8_t answer;
int onModulePin= 2;
char aux_str[50];
char ip_data[40]="Test string from GPRS shieldrn";
void setup(){
pinMode(onModulePin, OUTPUT);
Serial.begin(115200);
Serial.println("Starting...");
power_on();
delay(3000);
// sets the PIN code
sendATcommand2("AT+CPIN=****", "OK", "ERROR", 2000);
delay(3000);
Serial.println("Connecting to the network...");
while( sendATcommand2("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000) == 0 );
}
void loop(){
// Selects Multi-connection mode
if (sendATcommand2("AT+CIPMUX=1", "OK", "ERROR", 1000) == 1)
{
// Waits for status IP INITIAL
while(sendATcommand2("AT+CIPSTATUS", "INITIAL", "", 500) == 0 );
delay(5000);
// Sets the APN, user name and password
if (sendATcommand2("AT+CSTT="APN","user_name","password"", "OK", "ERROR", 30000) == 1)
{
// Waits for status IP START
while(sendATcommand2("AT+CIPSTATUS", "START", "", 500) == 0 );
delay(5000);
// Brings Up Wireless Connection
if (sendATcommand2("AT+CIICR", "OK", "ERROR", 30000) == 1)
{
// Waits for status IP GPRSACT
while(sendATcommand2("AT+CIPSTATUS", "GPRSACT", "", 500) == 0 );
delay(5000);
// Gets Local IP Address
if (sendATcommand2("AT+CIFSR", ".", "ERROR", 10000) == 1)
{
// Waits for status IP STATUS
while(sendATcommand2("AT+CIPSTATUS", "IP STATUS", "", 500) == 0 );
delay(5000);
Serial.println("Openning TCP");
// Opens a TCP socket with connection 1
if (sendATcommand2("AT+CIPSTART=1,"TCP","IP_address","port"",
"CONNECT OK", "CONNECT FAIL", 30000) == 1)
{
Serial.println("Connected");
// Sends some data to the TCP socket
sprintf(aux_str,"AT+CIPSEND=1,%d", strlen(ip_data));
if (sendATcommand2(aux_str, ">", "ERROR", 10000) == 1)
{
delay(500);
sendATcommand2(ip_data, "SEND OK", "ERROR", 10000);
}
// Closes the socket
sendATcommand2("AT+CIPCLOSE=1", "CLOSE OK", "ERROR", 10000);
}
else
{
Serial.println("Error openning the connection 1");
}
}
else
{
Serial.println("Error getting the IP address");
}
}
else
{
Serial.println("Error bring up wireless connection");
}
}
else
{
Serial.println("Error setting the APN");
}
}
else
{
Serial.println("Error setting the multi-connection");
}
sendATcommand2("AT+CIPSHUT", "OK", "ERROR", 10000);
delay(10000);
}
void power_on(){
uint8_t answer=0;
// checks if the module is started
answer = sendATcommand2("AT", "OK", "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 = sendATcommand2("AT", "OK", "OK", 2000);
}
}
}
int8_t sendATcommand2(char* ATcommand, char* expected_answer1,
char* expected_answer2, unsigned int timeout){
uint8_t x=0, answer=0;
char response[100];
unsigned long previous;
memset(response, ' ', 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 1 is in the response of the module
if (strstr(response, expected_answer1) != NULL)
{
answer = 1;
}
// check if the desired answer 2 is in the response of the module
else if (strstr(response, expected_answer2) != NULL)
{
answer = 2;
}
}
}
// Waits for the asnwer with time out
while((answer == 0) && ((millis() - previous) < timeout));
return answer;
}