Problems with sending multiple fields to ThingSpeak over Cooking Hacks 3G shield

Hello,

I am trying to upload some data to ThingSpeak using Cooking Hacks 3G shield on Arduino UNO. I tested the setup with Cooking Hacks example code "How to Upload Data to a Personal Cloud Server (Thingspeak)" https://www.cooking-hacks.com/documentation/tutorials/how-to-upload-data-to-a-personal-cloud-server-using-3g-gps/ and it is working well. With this code I can send 2 fields to ThingSpeak. However, when I tried sending one more field, the code is stuck at AT mode and not sending anything. I think I am doing something wrong with function send_data(). Below is the original function that sends 2 fields.

void send_data(int _light, float _temperature){
  // request the url
  sprintf(aux_str, "AT+CHTTPACT=\"%s\",%d", url, port);
  answer = sendATcommand(aux_str, "+CHTTPACT: REQUEST", 60000);

  if (answer == 1)
  { 
    dtostrf(_temperature,2,1,data);

    // set the request
    sprintf(aux_str, "GET /update?key=%s&field1=%d&field2=%s HTTP/1.1\r\nHost: api.thingspeak.com\r\nContent-Length: 0\r\n\r\n", APIWriteKey, _light, data)  ; 
    Serial.println(aux_str);
    // Sends "Ctrl+Z"
    aux_str[0] = 0x1A;
    aux_str[1] = 0x00;
    answer = sendATcommand(aux_str, "+CHTTPACT: 0", 60000);

    x=0;
    if (answer == 1)
    {

      Serial.println("OK");

    }
    else
    {
      Serial.println("Error sending the request");
    }
  }
  else
  {
    Serial.println("Error waiting the request");    
  }

  delay(10000);
}

And here is the version that I modified to add one more field. There are only two lines different from the original.

  1. number of parameters in the first line
  2. content of sprintf() that set the request. Added field3
void send_data(int _light, float _temperature, int randomNumber){ // Change 1 ********
  // request the url
  sprintf(aux_str, "AT+CHTTPACT=\"%s\",%d", url, port);
  answer = sendATcommand(aux_str, "+CHTTPACT: REQUEST", 60000);

  if (answer == 1)
  { 
    dtostrf(_temperature,2,1,data);

    // set the request
// Change 2 ********
    sprintf(aux_str, "GET /update?key=%s&field1=%d&field2=%s&field3=%d HTTP/1.1\r\nHost: api.thingspeak.com\r\nContent-Length: 0\r\n\r\n", APIWriteKey, _light, data, randomNumber)  ; 
    Serial.println(aux_str);
    // Sends "Ctrl+Z"
    aux_str[0] = 0x1A;
    aux_str[1] = 0x00;
    answer = sendATcommand(aux_str, "+CHTTPACT: 0", 60000);

    x=0;
    if (answer == 1)
    {

      Serial.println("OK");

    }
    else
    {
      Serial.println("Error sending the request");
    }
  }
  else
  {
    Serial.println("Error waiting the request");    
  }

  delay(10000);
}

The rest of the modified code is the same with the example code.

Am I missing something? Any pointer is much appreciated.

Thanks.

Am I missing something?

Yes. A whole bunch of code.

The rest of the modified code is the same with the example code.

Why should we go looking for it? It is YOUR code, not the example, that doesn't work. Post YOUR code.

Here is the full code where I made change in 2 functions. One is in void loop() and another in void send_data().

/*  
 *  3G + GPS shield
 *  
 *  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. 
 *  
 *  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:           1.0
 *  Design:            David Gascón 
 *  Implementation:    Alejandro Gallego & Victor Boria
 */

//Write here you SIM data
const char pin_number[] = "****";
const char apn[] = "******";
const char user_name[] = "******";
const char password[] = "******";

//Write here you Thingspeak data
const char APIWriteKey[] = "******";

char url[ ]= "api.thingspeak.com";
int port= 80;

int light;  // Stores the light level

float temperature = 0.0; // Stores the calculated temperature
int sample;              // Counts through ADC samples
float ten_samples = 0.0; // Stores sum of 10 samples

int8_t answer;
int onModulePin = 2, aux;
int data_size = 0;
int end_file = 0;
char aux_str[100];
char data[800];
int x = 0;
long previous;


void setup(){

  pinMode(onModulePin, OUTPUT);
  Serial.begin(115200);   

  Serial.println("Starting...");
  power_on();

  delay(3000);

  //sets the PIN code
  sprintf(aux_str, "AT+CPIN=%s", pin_number);
  sendATcommand(aux_str, "OK", 2000);

  delay(3000);

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

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

  // sets APN, user name and password
  sprintf(aux_str, "AT+CGSOCKCONT=1,\"IP\",\"%s\"", apn);
  sendATcommand(aux_str, "OK", 2000);

  sprintf(aux_str, "AT+CSOCKAUTH=1,1,\"%s\",\"%s\"", user_name, password);
  sendATcommand(aux_str, "OK", 2000);

}



/*
 * In this function, I added a random number as the third parameter
 * when calling function send_data()
 */
void loop(){
  
  light = analogRead(A1);
  measure_temperature();
  int randomInt = random(10, 50);
  //Send data to Thingspeak via HTTP GET
  send_data(light, temperature, randomInt);
  
  //Wait a minute
  delay(60000);
}





void measure_temperature()
{
  // take 10 samples from the MCP9700
  for (sample = 0; sample < 10; sample++) {
    // convert A0 value to temperature
    temperature = ((float)analogRead(A0) * 5.0 / 1024.0) - 0.5;
    temperature = temperature / 0.01;
    temperature = temperature - 5.3;
    // sample every 0.1 seconds
    delay(100);
    // sum of all samples
    ten_samples = ten_samples + temperature;
  }
  // get the average value of 10 temperatures
  temperature = ten_samples / 10.0;
  ten_samples = 0.0;
}




/*
 * In this function, I added the int randomNumber in the function 
 * parameter and added field3 in the sprintf() when setting the request
 */
void send_data(int _light, float _temperature, int randomNumber){ 
  // request the url
  sprintf(aux_str, "AT+CHTTPACT=\"%s\",%d", url, port);
  answer = sendATcommand(aux_str, "+CHTTPACT: REQUEST", 60000);

  if (answer == 1)
  { 
    dtostrf(_temperature,2,1,data);

    // set the request
    sprintf(aux_str, "GET /update?key=%s&field1=%d&field2=%s&field3=%d HTTP/1.1\r\nHost: api.thingspeak.com\r\nContent-Length: 0\r\n\r\n", APIWriteKey, _light, data, randomNumber)  ; 
    Serial.println(aux_str);
    // Sends "Ctrl+Z"
    aux_str[0] = 0x1A;
    aux_str[1] = 0x00;
    answer = sendATcommand(aux_str, "+CHTTPACT: 0", 60000);

    x=0;
    if (answer == 1)
    {

      Serial.println("OK");

    }
    else
    {
      Serial.println("Error sending the request");
    }
  }
  else
  {
    Serial.println("Error waiting the request");    
  }

  delay(10000);
}




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_answer1, 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(Serial.available() != 0){    
      if (x == 100)
      {
        strncpy(response, response +1, 99);
        response[99] = Serial.read();
      }
      else
      {
        response[x] = Serial.read();
        x++;
      }
      // check if the desired answer is in the response of the module
      if (strstr(response, expected_answer1) != NULL)    
      {
        answer = 1;
      }
    }
    // Waits for the asnwer with time out
  }
  while((answer == 0) && ((millis() - previous) < timeout));    

  return answer;
}





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, '\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(Serial.available() != 0){    
      response[x] = Serial.read();
      x++;
      // check if the desired answer is in the response of the module
      if (strstr(response, expected_answer1) != NULL)    
      {
        answer = 1;
      }
      // check if the desired answer is in the response of the module
      if (strstr(response, expected_answer2) != NULL)    
      {
        answer = 2;
      }
    }
    // Waits for the asnwer with time out
  }
  while((answer == 0) && ((millis() - previous) < timeout));    

  return answer;
}
    sprintf(aux_str, "GET /update?key=%s&field1=%d&field2=%s&field3=%d HTTP/1.1\r\nHost: api.thingspeak.com\r\nContent-Length: 0\r\n\r\n", APIWriteKey, _light, data, randomNumber)  ;
    Serial.println(aux_str);
    // Sends "Ctrl+Z"
    aux_str[0] = 0x1A;
    aux_str[1] = 0x00;
    answer = sendATcommand(aux_str, "+CHTTPACT: 0", 60000);

Store some data in aux_str. Print that data, but don't show it to us. Then, crap all over the data in aux_str, and send that data.

Actually sending the data in aux_str before you crap on it seems like a good idea to me. I could be wrong, though.

Thanks PaulS. I have encountered another problem. After reversing the code to its original example just to test that if there's anything wrong with the setup. Then the code was stuck in AT command, not receiving any response from ThingSpeak after sending GET request. Awaiting advices from technicians at Cooking Hacks. To update here once I have further progress.

Just a quick update on problem/solution.

RE the board not working, it turned out to be the problem of damaged antenna connector. Once replaced with a new one, the shield was back to work but I still couldn't push string data to the sever when the string was constructed with sprintf() function.

As PaulS suggested, I stored all data in the aux_str variable and tried printing to see what in it. All the string value is in there but I just couldn't manage it to push data through. In the end, I use += operator to prepare the string and push to the server. It's working just fine now.

Thanks.