SparkFun Forums 

Where electronics enthusiasts find answers.

All things pertaining to wireless and RF links
By shfitz
#112342
Any help with this would be really great.

I can't make a socket connection using an Arduino Duemilanove.

Currently, my code looks like this :
Code: Select all
#define BUFFSIZ 90

#include <NewSoftSerial.h>  //Include the NewSoftSerial library to send serial commands to the cellular module.
#include <string.h>         //Used for string manipulations

int sockConnect = 0; //checks to see if the sockets is connected
int dataIn = 0; //is there data in the buffer?
boolean modemOnline=false; // is the modem online yet?
char incoming_char=0;      //Will hold the incoming character from the Serial Port.
int firstTimeInLoop = 1; //is this the first time we're starting?
int GPRS_registered;
int GPRS_AT_ready;
char buffidx;
char at_buffer[BUFFSIZ];
String statusRegistered="\r\n+SIND: 4";

NewSoftSerial cell(2,3);  //Create a 'fake' serial port. Pin 2 is the Rx pin, pin 3 is the Tx pin.

//read the inciming strings from the modem to check for conection to the cell network
void readATString(void) {
  char c;
  buffidx= 0; // start at begninning
  while (1) {
    if(cell.available() > 0) {
      c=cell.read();
      if (c == -1) {
        at_buffer[buffidx] = '\0';
        return;
      }
      if (c == '\n') {
        continue;
      }
      if ((buffidx == BUFFSIZ - 1) || (c == '\r')){
        at_buffer[buffidx] = '\0';
        return;
      }
      at_buffer[buffidx++]= c;
    }
  }
}


/* Processes the AT String to determine if GPRS is registered and AT is ready */
void ProcessATString() {

  if( strstr(at_buffer, "+SIND: 8") != 0 ) {
    GPRS_registered = 0;
    Serial.println("GPRS Network Not Available");
  }

  if( strstr(at_buffer, "+SIND: 11") != 0 ) {
    GPRS_registered=1;
    Serial.println("GPRS Registered");
    //blinkLed(redLedPin,5,100);
  }

  if( strstr(at_buffer, "+SIND: 4") != 0 ) {
    GPRS_AT_ready=1;
    Serial.println("GPRS AT Ready");
  }

}

//does this
void makeEuro(){
  cell.print("AT+SBAND=4"); 
  Serial.println("AT+SBAND=4"); 
  cell.print(0x0D);
  waitForOK(); 
}

void gprsinit(){
  cell.print("AT+CGATT=?");
  Serial.println("AT+CGATT=?");
  cell.print(0x0D); 
  waitForOK();
  cell.print("AT+CGDCONT=1,'IP','telenor'");
  Serial.println("AT+CGDCONT=1,'IP','telenor'");
  cell.print(0x0D); 
  waitForOK();
  cell.print("AT+CGPCO=0,'dj','dj',1");
  Serial.println("AT+CGPCO=0,'dj','dj',1");
  cell.print(0x0D); 
  waitForOK();
  cell.print("AT+CGACT=1,1");
  Serial.println("AT+CGACT=1,1");
  cell.print(0x0D);  
  waitForOK();
}

void datasendandreceive(){
  cell.print("at+sdataconf=1,\"TCP\",\"www.google.com\",80"); 
  Serial.println("at+sdataconf=1,\"TCP\",\"www.google.com\",80"); 
  cell.print(0x0D);  
  waitForOK();
  cell.print("at+sdatastart=1,1");
  Serial.println("at+sdatastart=1,1");
  cell.print(0x0D); 
  waitForOK();
  cell.print("at+sdatastatus=1"); 
  Serial.println("at+sdatastatus=1"); 
  cell.print(0x0D);  
  Serial.println("Socket Status to Follow");
  waitForSockStatus();
  cell.print("at+sdatasend=1,10");  // where 10 is how many bytes to send
  cell.print("1");
  cell.print(0x1A);
  waitForOK();

  //check to see if data has been received +STCPD:1
  hasDataBeenReceived();
  if(dataIn==1){
    cell.print("AT+SDATATREAD=1");  // read the data
    cell.print(0x0D);  
    getMessage();
  }
  else{
    //start over
  }

  cell.print("AT+SDATASTART=1,0");  // close the connection 
  waitForOK();
}

//reads through the buffer until it reaches the letter 'K'
void waitForOK(){
  while(cell.available())
  {
    incoming_char=cell.read();    //Get the character from the cellular serial port.
    Serial.print(incoming_char);
    delay(2);
  }
  Serial.println();
}


//waits to connect to the socket
void waitForSockStatus(){
  //Patterns to look for
  String prefix="+SOCKSTATUS: 1,";
  String input="";
  char value;

  while(cell.available()<1){
    //wait for a cycle
  }

  while(cell.available()>0){
    incoming_char=cell.read();  //read the buffer
    Serial.println(incoming_char);
    input+=incoming_char;      //add it to the string
    if(input.substring(0)==prefix)  //if it matches our expected string
    {
      break;
    }
  }

  incoming_char=cell.read();
  //Serial.println(incoming_char);
  if(incoming_char=='1'){
    Serial.println("Socket connected");
    sockConnect=1;
  }
  else{
    Serial.println("Socket NOT connected");
    sockConnect=0;
  }

  //clear the buffer
  while(cell.available()>0){
    incoming_char=cell.read(); 
  }
}

void getMessage(){
  //Patterns
  String prefix="+SDATA: 1, ";
  String input="";  
  String ourM="\r\n";

  boolean y=false;
  boolean m=false;


  //print the message
  cell.print('AT+SDATATREAD=1');
  cell.print(0x0D); 


  while(cell.available()<1){
    //wait for a cycle
  }

  //First, find the prefix
  while(cell.available()>0){
    incoming_char=cell.read();  //read the buffer
    input+=incoming_char;      //add it to the string
    if(input.substring(0)==prefix)  //if it matches our expected string
    {
      //Data is present
      y=true;
      break;
    }
  }

  //read message until we reach the comma, which is the start of the new message
  while(cell.available()&&y==true) 
  {
    if(incoming_char!=','){
      incoming_char=cell.read();
    }
    else{
      break;
    }
  } 

  //get our message
  while(cell.available()>0){  
    incoming_char = cell.read(); //read the buffer
    messageToSign.concat(incoming_char); //add it to the string 
    if(messageToSign.endsWith(ourM))
    {     
      break;
    }
  }

  messageToSign=messageToSign.trim(); 
}  

void hasDataBeenReceived(){
// this needs to run until we get a 1
//a 0 means we are still connecting...........

  //Pattern
  String hopeItsThere= "+STCPD:1"; 
  String input="";  

  while(cell.available()<1){
    //wait for a cycle
  }

  while(cell.available()>0){
    incoming_char=cell.read();  //read the buffer
    input+=incoming_char;      //add it to the string
    if(input.substring(0)==hopeItsThere)  //if it matches our expected string
    {
      //Data is present
      dataIn=1;
    } 
    else{
      //no data
      dataIn=0;
    }
  }
}


void setup()
{
  //Initialize serial ports for communication.
  Serial.begin(9600);
  cell.begin(9600);
  delay(1000);
  //Let's get started!
  Serial.println("Booting up...");
}

void loop() {

  //check on startup to see if we have registered on the network
  if(firstTimeInLoop) {
    firstTimeInLoop = 0;
    while (GPRS_registered == 0 || GPRS_AT_ready == 0) {
      readATString();
      ProcessATString();
    }
  }

  gprsinit();
  datasendandreceive();  
}

All it returns is this :

Booting up...
GPRS Registered
GPRS AT Ready
AT+CGATT=?


AT+CGDCONT=1,'IP','telenor'

AT+CGPCO=0,'dj','dj',1

AT+CGACT=1,1

at+sdataconf=1,"TCP","google.com",80

at+sdatastart=1,1

at+sdatastatus=1
Socket Status to Follow

Which is weird, because I would expect to see the cell's printout whenever waitForOK() is called...
By shfitz
#112446
Some cleaned up code, but still no love from the modem.

Now I'm getting the following from the serial monitor :
Starting SM5100B Communication...
GPRS Network Not Available
GPRS AT Ready
Setting up PDP Context
OK
Sending Password
OK
Activating PDP Context
Configuring TCP connection to TCP Server
OK
Starting TCP Connection
Checking Connection Status
RzµÕ¤ø
+SOCKSTATUS: 1,0,0100,0,0,0
OK
Checking Connection Status
+SOCKSTATUS: 1,0,0100,0,0,0
With this code :
Code: Select all
#include <NewSoftSerial.h>  //Include the NewSoftSerial library to send serial commands to the cellular module.
#include <string.h>

#define POWERPIN 4

#define BUFFSIZ 90

char at_buffer[BUFFSIZ];
char buffidx;


int firstTimeInLoop = 1;

int GPRS_registered;
int GPRS_AT_ready;

char incoming_char=0;      //Will hold the incoming character from the Serial Port.
char buffer[60];


String myString="1";

NewSoftSerial cell(2,3);  //Create a 'fake' serial port. Pin 2 is the Rx pin, pin 3 is the Tx pin.

// Do system wide initialization here in this function
void setup()
{


    Serial.begin(9600);
    cell.begin(9600);
   
//Let's get started!

    Serial.println("Starting SM5100B Communication...");

    delay(5000);

    /* Currently GPRS is not registered and AT is not ready */

    GPRS_registered = 0;
    GPRS_AT_ready = 0;


}

/* Reads AT String from the SM5100B GSM/GPRS Module */

void readATString(void) {

    char c;
    buffidx= 0; // start at begninning
    while (1) {
        if(cell.available() > 0) {
            c=cell.read();
            if (c == -1) {
                at_buffer[buffidx] = '\0';
                return;
            }

            if (c == '\n') {
                continue;

            }

            if ((buffidx == BUFFSIZ - 1) || (c == '\r')){
                at_buffer[buffidx] = '\0';
                return;
            }

            at_buffer[buffidx++]= c;
        }
    }
}


/* Processes the AT String to determine if GPRS is registered and AT is ready */

void ProcessATString() {

    if( strstr(at_buffer, "+SIND: 8") != 0 ) {
        GPRS_registered = 0;
        Serial.println("GPRS Network Not Available");
    }

    if( strstr(at_buffer, "+SIND: 11") != 0 ) {
        GPRS_registered=1;
        Serial.println("GPRS Registered");
    }

    if( strstr(at_buffer, "+SIND: 4") != 0 ) {
        GPRS_AT_ready=1;
        Serial.println("GPRS AT Ready");
    }

}


void loop() {

    /* If called for the first time, loop until GPRS and AT is ready */

    if(firstTimeInLoop) {
        firstTimeInLoop = 0;
        while (GPRS_registered == 0 && GPRS_AT_ready == 0) {
           readATString();
           ProcessATString();

        }

        Serial.println("Setting up PDP Context");
   cell.println("AT+CGDCONT=1,\"IP\",\"epc.tmobile.com\"");
    delay(1000);
    while(cell.available()){
      incoming_char=cell.read();
      Serial.print(incoming_char);
    }
        Serial.println("Sending Password");       
        cell.println("AT+CGPCO=0,\"\",\"\", 1");
    delay(1000);
    while(cell.available()){
      incoming_char=cell.read();
      Serial.print(incoming_char);
    }
        Serial.println("Activating PDP Context");
        cell.println("AT+CGACT=1,1");
    delay(1000);
    while(cell.available()){
      incoming_char=cell.read();
      Serial.print(incoming_char);
    }
        Serial.println("Configuring TCP connection to TCP Server");
        cell.println("AT+SDATACONF=1,\"TCP\",\"88.87.58.126\",5000");
    delay(1000);
    while(cell.available()){
      incoming_char=cell.read();
      Serial.print(incoming_char);
    }
        Serial.println("Starting TCP Connection\n");
        cell.println("AT+SDATASTART=1,1");
    }
   Serial.println("Checking Connection Status\n");
    cell.println("AT+SDATASTATUS=1");
    delay(1000);
    while(cell.available()){
      incoming_char=cell.read();
      Serial.print(incoming_char);
    }
Anyone done this successfully know why I can't connect?
By willrot
#113650
Has anyone figured this out yet? I am stalled here myself. I have done the same sequence of commands and can't get a web page to respond properly.

I am talking directly to the shield through a terminal emulator.

If anyone has a sample of a successful connection to a web page, please post it.

Thanks
By gorillapilot
#118396
daleread wrote:Yeh done it...

Anybody need help??

DaleR
Yes. I have been fighting for days trying to get the SM5100 to see the network. Link Sprite support says the default band is gsm900, which is right for China. But for North America it must be changed to 850 using AT+SBAND=7. But this command always returns an error for me.

Were you able to make your work in North America?

Thanks,
Mike
By sleahey
#119636
thebecwar is right

you need to read the HTTP standard and figure out how to send a valid HTTP GET command.
Then the server will send the page.

If you only make a TCP connection, how is the server going to know what to do?
If you install wireshark, start her up, create a filter with www.google.com, look at the transactions that take place between your computer and www.google.com

You will see that a TCP connection is only the first step.

I'm using post because thats my application, and my code is quite dynamic, but if your always sending the same GET command, its doesn't need all the variables in there. It could be a fixed packet.

Be careful if you are connecting to an IP, that the 'host' value is actually the web address and not the IP. If you use the IP the server wont know what to do with it. This is because there might be more than one web server on that IP.... likely not the case for google.com, but to be sure.

Read the standard, and get used to reading, because reading is king in development... you need to do it... alot.
Code: Select all
		//"AT+SDATASEND=1, "..."
		Serial1.print("AT+SDATATSEND=1, ");
		Serial1.print(packetSize);
		Serial1.print(CR);

		delay(100);
/*--------------------Sart TCP Packet--------------------------*/		
/*--------------------Sart HTTP Header-------------------------*/
		Serial1.print("POST ");							//5
		Serial1.print(webExt);							//var
		Serial1.print(" http/1.1"); 					//9
		Serial1.print(CR);		 						//1
		Serial1.print(LF);							 	//1
		Serial1.print("Host: ");						//6
		Serial1.print(webAdd);							//var
		Serial1.print(CR);								//1
		Serial1.print(LF);								//1
		Serial1.print("User-Agent: ");					//12
		Serial1.print(userAgent);						//var
		Serial1.print(CR);								//1
		Serial1.print(LF);								//1
		Serial1.print("Content-Type: application/x-www-form-urlencoded");	//47
		Serial1.print(CR);								//1
		Serial1.print(LF);								//1
		Serial1.print("Content-Length: ");				//16
		Serial1.print(contentSize);						//var
		Serial1.print(CR);								//1
		Serial1.print(LF);								//1
		Serial1.print(CR);								//1
		Serial1.print(LF);								//1
/*--------------------End HTTP Header-------------------------*/
/*-------------------Start of Content-------------------------*/	    
		Serial1.print("s=");
		for (int k=0; k<12; k++){
			Serial1.print(payload[k]);
		} 
		if (howmanyInt>0){
			Serial1.print("&f=");
			for (int i=0; i<howmanyInt; i++){
				for (int k=0; k<12; k++){
					Serial1.print(payload[(i*12)+k]);
				}
				if (i<(howmanyInt-1)){
					Serial1.print(",");
				}
			}
		}
		if (reboot == true){
			Serial1.print("&e=");
			Serial1.print(Err_Reset);
			reboot = false;
		}
		Serial1.print(CR); // Carridge return			//1
/*--------------------End of Content--------------------------*/
/*--------------------End TCP Packet--------------------------*/	

		Serial1.print(UC); // Up caret
By sleahey
#122710
Was just implementing a GET.
Its got some quirks... thats for sure...

Once you have the tcp connection setup use this
AT+SDATARXMD=<connect ID>,1,0

Makes the data the comes out ASCII, and also makes sure you get the +STCPD:<connect ID> when data is received.

Then
Code: Select all

				Serial1.print("AT+SDATATSEND=1, ");
				Serial1.print(packetSize);
				Serial1.print(CR);
			
				delay(100);
				/*--------------------Sart TCP Packet--------------------------*/
				/*--------------------Sart HTTP Header-------------------------*/
				Serial1.print("GET ");							//4
				Serial1.print(getExt);							//var
				Serial1.print(" HTTP/1.0"); 						 //9
				Serial1.print(CR);		 						//1
				Serial1.print(LF);							 	//1
				Serial1.print("Connection: Keep-Alive");			 	//22
				Serial1.print(CR);		 						//1
				Serial1.print(LF);							 	//1
				Serial1.print(CR);		 						//1
				Serial1.print(LF);							 	//1
				/*--------------------End HTTP Header-------------------------*/
				/*-------------------Start of Content-------------------------*/
				/*--------------------End of Content--------------------------*/
				/*--------------------End TCP Packet--------------------------*/
wait for OK, however you implement

then wait for +STCPD:<connect ID>
(some code below... its kinda crap but works)
Code: Select all

			waiting = true;
			while	(waiting == true){
				if(Serial1.available() > 7){
					inByte = getbyteSerial1();
					if (inByte=='+'){
						for (k=0 ; k<7 ; k++){
							searchString[k]=getbyteSerial1();
						}
					
						if (	searchString[0]=='S'
							&& 	searchString[1]=='T'
							&& 	searchString[2]=='C'
							&& 	searchString[3]=='P'
							&& 	searchString[4]=='D'
							&& 	searchString[5]==':'
							&& 	searchString[6]=='1'){		// 1 in this line is the TCP connection ID
							Serial1.println("AT+SDATAREAD=1");
							waiting = false;
							#ifdef debug_ctv2
							Serial.println("Data!");
							#endif
						}
						else{
							#ifdef debug_ctv2
							Serial.println("No Data");
							#endif
							return some error;
						}
					}
				}
			}

handle the returned data...

I noticed that If I waited too long the socket gets closed by the server and then the module deletes the data...
so the read has to happen immediately after the message of data availability

I haven't field tested this, but it seems to be working fine.

Hope it helps.
By sleahey
#122774
Definitely with Keep Alive disabled this module would be useless...

I have an apache server running and it had keep alive disabled, it was making getting the data intermittent. Sometimes it was fast enough, sometimes not.... with Keep Alive enabled on the server, and I set the timeout to 5 seconds, it now appears to be working correctly.
By chaost
#136938
I'm no expert on these matters, but I have found the following:

Anyone getting the same issues as shfitz might want to adjust the following code:
Code: Select all
      while (GPRS_registered == 0 && GPRS_AT_ready == 0) {
           readATString();
           ProcessATString();
       }
Should be an AND statement (note the two || characters instead of &&):
Code: Select all
      while (GPRS_registered == 0 || GPRS_AT_ready == 0) {
           readATString();
           ProcessATString();
       }
Otherwise, script could run without getting full network and that will lead to a fail.

If you get CME ERROR: 33 - this seems to be as a result of calling AT+SDATACONF too early or PDP Context not activating. I put a 5 second delay after AT+CGACT=1,1 and it works a dream every time now.
By jremington
#136946
The two characters "||" constitute an OR logical operator, not an AND logical operator. Is that what you meant?

As an aside, to avoid mistakes and make the logical operator precedence clear to others, it is usually a good idea to use extra parentheses as follows

if ( (GPRS_registered == 0) || (GPRS_AT_ready == 0) ) {
By tommys
#137610
Not having any luck with the cellular shield either.

I modified the AT+CGDCONT & AT+CGPCO sends to match my carrier, added SIM PIN, and took hints from http://www.sparkfun.com/datasheets/Cell ... 20Note.pdf where solutions to CME Error 28 is mentioned, I get:
Code: Select all
Starting SM5100B Communication...
Inputting SIM PIN
GPRS Registered
GPRS AT Ready
Setting up PDP Context


OK
Sending Password

OK
Activating PDP Context

+CME ERROR: 28
DE-Activating PDP Context

NO CARRIER
Activating PDP Context

+CME ERROR: 28
DEtaching GRPS Network

+CME ERROR: 65536014
Attaching GPRS Network

+CME ERROR: 65536014
Activating PDP Context

+CME ERROR: 28
Configuring TCP connection to TCP Server

OK
Starting TCP Connection

Checking Connection Status

RôµªHø
+SOCKSTATUS:  1,0,0100,0,0,0

OK
Checking Connection Status


+SOCKSTATUS:  1,0,0100,0,0,0
Any ideas?