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; }