GSM shield won't connect when array size is large

Hello,

I have created the below code (based on GSMWebClient) to push some data (in this case, the data is simply a list of numbers from 0 to the maximum array size) to an online server. The server is an online data server I created at data.sparkfun.com, which will log your data if you send it a HTTP request using the right syntax.

The code works, but only if the array holding my data (chardata_matrix in row 76) is 10. If I increase the size of this array to 100, or 1,000, it won’t connect.

The code converts the data to base 33 before sending. I left that in the below code because I can’t seem to replicate my success anymore (even with an array size of 10) and so I didn’t want to change anything just in case.

The arduino is connected to my laptop (running on battery to avoid potential ground-loop problems) via a USB cable, and I have a 1A, 5V power supply connected directly to the 5V pin.

Can anyone imagine why the below code works when sizeof(chardata_matrix) is 10, but not if it’s 100 or 1,000?

In case it’s relevant, I should say that on some occasions I have noticed it seemingly connect (noticeable from the appearance of the characters “Connec” appearing in the serial terminal) but then immediately crash (print a few characters of gibberish) and reset.

Here is the code. Many thanks for any help!

/*
Datalogger for 10-bit analog read. 0 -> 1023 readings are
converted to 2-character-byte figures, using a base of 33
letters (32^2 = 1024 for the reading, plus an extra letter
to include extra data such as "reading missed", or the
like. The char data is then uploaded via the GSM
shield to Shamba's data stream on data.sparkfun.com.
 */

#include <GSM.h>

// PIN Number
#define PINNUMBER "9223"

// APN data
#define GPRS_APN       "internet"
#define GPRS_LOGIN     "guest"
#define GPRS_PASSWORD  "guest"

// Lookup table for conversion to base 33"
char base33lookup[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVW";

// Give unique ID for datalogging platform
#define PLATFORM_ID  1

// Define SparkFun keys
#define PUBLIC_KEY "KJz6bpNroqUaNpDroQyW"
#define PRIVATE_KEY "vzbX2p5yVgCB2lv6kGjW"

// Define server
char server[] = "data.sparkfun.com";

// Initialize GSM shield library
GSMClient client;
GPRS gprs;
GSM gsmAccess;


void setup() {
  
  // Open serial communications
  Serial.begin(9600);

  // Wait for user input to continue
  Serial.println("Wait for keypress...\n");
  while(Serial.available()==0);


  // Try to connect repeatedly until success
  Serial.println("Trying to connect to GSM network...");
  boolean notConnected = true;
  while(notConnected)
  {
    if((gsmAccess.begin(PINNUMBER)==GSM_READY) &
      (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD)==GPRS_READY))
      notConnected = false;
    else
    {
      Serial.println("Failed, re-trying now...");
      delay(1000);
    }
  }
  Serial.println("Connected to GSM network");
  
}


//********************************************


void loop() {
  
  // Collect data and convert to base 33
  // [placeholder just fills array with increasing numbers]
  // Don't forget to terminate the string at the end!
  char chardata_matrix[10];
  for (int i = 0; i < (sizeof(chardata_matrix) - 1); i = i + 2) {
   chardata_matrix[i] = mscbase33(i);
   chardata_matrix[i+1] = lscbase33(i);    
  }
  chardata_matrix[sizeof(chardata_matrix)] = '\0';
  
  // Connect to SparkFun data stream HTTP port
  if(client.connect(server, 80)) {
    // Double check we've connected
    if(client.connected()) {
      // Send data to SparkFun
      Serial.println("Sending data to SparkFun...\n");    
      // Send HTTP PUT request
      client.print("GET /input/");
      client.print(PUBLIC_KEY);
      client.print("?private_key=");
      client.print(PRIVATE_KEY);
      client.print("&id=");
      client.print(PLATFORM_ID);
      client.print("&data=");
      client.print(chardata_matrix);
      client.println(" HTTP/1.1");
      client.print("Host: ");
      client.println(server);
      client.println("Connection: close");
      client.println();
 
      // Wait for SparkFun server response
      while(client.available() == 0);
      
      // Read and print SparkFun server response
      while(client.available() > 0) { 
        char inData = client.read();
        Serial.print(inData);
      }      
      Serial.println("\n");
      
      // Disconnect
      client.stop();
      Serial.print("Disconnected.");
      while(1);
      
    }
    else {
      Serial.print("Failed to connect to server. Client.connected() returned 0");
      while(1);
    } 
  }
  else {
    Serial.println("Failed to connect to server. Client.connect() didn't return 1");
    while(1);
  }
  
}

// Code to determine most significant
// character after conversion of input
// to base 33.
char mscbase33(int val) {
  
  int msc = val / 33;
  return base33lookup[msc];

}

// Code to determine least significant
// character after conversion of input
// to base 33.
char lscbase33(int val) {
  
  int lsc = val % 33;
  return base33lookup[lsc];

}

Which Arduino are you using? How much memory does it have?

Hi Dannable,

Thanks for the tip. After reading a bit about Arduino memory, this does seem to fit the symptoms of running out of SRAM memory. I am using an Arduino UNO which apparently has an SRAM memory of 2k bytes.

I went through my sketch and wrapped all Serial.print strings in F(). I also had a suspicion that using sizeof() to define the upper limit of my for loop (see row 77 in the code I posted in my first post) could be sucking up an extra byte at each loop. Do you think this is the case? Certainly, if I leave that in then I can’t get the code to run with a char array size of 100, but if I replace it with a pre-defined integer (see code below, row 77) then it works!

At least… it does with an array size of 100, and also with 500, but does not with an array size of 1000. I am supposed to have have 2048 bytes in total right? So where are the other 1048 bytes being consumed?

Later tonight I will have a go at learning how to use the MemoryFree library to probe this a little further.

Thanks again for the pointer!

Eddie

This is my improved code:

/*
Datalogger for 10-bit analog read. 0 -> 1023 readings are
converted to 2-character-byte figures, using a base of 33
letters (32^2 = 1024 for the reading, plus an extra letter
to include extra data such as "reading missed", or the
like. The char data is then uploaded via the GSM
shield to Shamba's data stream on data.sparkfun.com.
 */

#include <GSM.h>

// PIN Number
#define PINNUMBER "9223"

// APN data
#define GPRS_APN       "internet"
#define GPRS_LOGIN     "guest"
#define GPRS_PASSWORD  "guest"

// Lookup table for conversion to base 33"
char base33lookup[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVW";

// Give unique ID for datalogging platform
#define PLATFORM_ID  1

// Define SparkFun keys
#define PUBLIC_KEY "KJz6bpNroqUaNpDroQyW"
#define PRIVATE_KEY "vzbX2p5yVgCB2lv6kGjW"

// Define server
char server[] = "data.sparkfun.com";

// Initialize GSM shield library
GSMClient client;
GPRS gprs;
GSM gsmAccess;


void setup() {
  
  // Open serial communications
  Serial.begin(9600);

  // Wait for user input to continue
  Serial.println(F("Wait for keypress...\n"));
  while(Serial.available()==0);


  // Try to connect repeatedly until success
  Serial.println(F("Trying to connect to GSM network..."));
  boolean notConnected = true;
  while(notConnected)
  {
    if((gsmAccess.begin(PINNUMBER)==GSM_READY) &
      (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD)==GPRS_READY))
      notConnected = false;
    else
    {
      Serial.println(F("Failed, re-trying now..."));
      delay(1000);
    }
  }
  Serial.println(F("Connected to GSM network"));
  
}


//********************************************


void loop() {
  
  // Collect data and convert to base 33
  // [placeholder just fills array with increasing numbers]
  // Don't forget to terminate the string at the end!
  char chardata_matrix[500];
  int maxi = sizeof(chardata_matrix);
  for (int i = 0; i < (maxi - 1); i = i + 2) {
   chardata_matrix[i] = mscbase33(i);
   chardata_matrix[i+1] = lscbase33(i);    
  }
  chardata_matrix[maxi] = '\0';
  
  // Connect to SparkFun data stream HTTP port
  if(client.connect(server, 80)) {
    // Double check we've connected
    if(client.connected()) {
      // Send data to SparkFun
      Serial.println(F("Sending data to SparkFun...\n"));    
      // Send HTTP PUT request
      client.print("GET /input/");
      client.print(PUBLIC_KEY);
      client.print("?private_key=");
      client.print(PRIVATE_KEY);
      client.print("&id=");
      client.print(PLATFORM_ID);
      client.print("&data=");
      client.print(chardata_matrix);
      client.println(" HTTP/1.1");
      client.print(F("Host: "));
      client.println(server);
      client.println(F("Connection: close"));
      client.println();
 
      // Wait for SparkFun server response
      while(client.available() == 0);
      
      // Read and print SparkFun server response
      while(client.available() > 0) { 
        char inData = client.read();
        Serial.print(inData);
      }      
      Serial.println("\n");
      
      // Disconnect
      client.stop();
      Serial.print(F("Disconnected."));
      while(1);
      
    }
    else {
      Serial.print(F("Failed to connect to server. Client.connected() returned 0"));
      while(1);
    } 
  }
  else {
    Serial.println(F("Failed to connect to server. Client.connect() didn't return 1"));
    while(1);
  }
  
}

// Code to determine most significant
// character after conversion of input
// to base 33.
char mscbase33(int val) {
  
  int msc = val / 33;
  return base33lookup[msc];

}

// Code to determine least significant
// character after conversion of input
// to base 33.
char lscbase33(int val) {
  
  int lsc = val % 33;
  return base33lookup[lsc];

}