My Cart

How to Upload Data to a Personal Cloud Server (Thingspeak) Using 3G+GPS Mobile Kit

Difficulty Level: Expert -

1. Introduction

This tutorial allows the user to measure the temperature and the light level in a room. This data is sent each minute to a personal cloud server in Thingspeak, so you will be able to see both graphics in a web page.

Ingredients:

    - 1 x 3G+GPS Mobile Kit:
    • 1x Platform
    • 1x 3G + GPS shield
    • 1x GPRS antenna
    • 1x Temperature sensor (MCP9700A)
    • 1x Light sensor (LDR)
    • 1x Breadboard
    • 1x External power supply
    • 1x Programming cable
    • Jumper Wires

Preparation Time: 30 minutes

Buy now
NOTE: Depending on the platform chosen to develop the project, the ingredients and the schematics shown in this tutorial can vary.

This project can be developed with Arduino or Intel Galileo. It is also compatible with Raspberry Pi using the Raspberry Pi to Arduino shields connection bridge.

For further information about the 3G + GPS Shield, consult the main tutorial.

Step 1: Connection

Connect the GPRS antenna to the shield and then, connect the shield to Arduino or to Raspberry Pi connection bridge. Connect the light sensor and the temperature sensor in the breadboard as you can see in the next diagram.

Connect two wires, red and black, to the two long rows on the side of the breadboard to provide access to the 5 volt supply and ground.

Place the temperature sensor with the flat part looking up like the diagram. Connect the left leg of the temperature sensor to GDN and the right to 5 volt. Connect the central leg to the first pin at bottom left of the shield (Analog 0).

Connect the right leg of the light sensor to 5V and the left to the second pin at bottom left of the shield (Analog 1) and also to a 220 Ohm resistor. Finally connect the other leg of the resistor to GND. This structure is called "voltage divider".

Step 2: The Code

First you will have to create a free acount in Thingspeak. Then create a New Channel with these two fields:

  • Field 1: Light (LDR)
  • Field 2: Temperature (NTC)

Finally type in the next code your API Write Key.

Arduino:

Code:
/*  
 *  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);

}
void loop(){
  
  light = analogRead(A1);
  measure_temperature();
  
  //Send data to Thingspeak via HTTP GET
  send_data(light, temperature);
  
  //Wait a minute
  delay(60000);
}



/************************************************************************
 ****               Definition of functions                          ****
 ************************************************************************/

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

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

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

Raspberry Pi:

Code:
/*  
 *  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
 */
 
//Include ArduPi library
#include "arduPi.h"

//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[] = "******";

void power_on();
int8_t sendATcommand(const char* ATcommand, const char* expected_answer1, unsigned int timeout);
int8_t sendATcommand2(const char* ATcommand, const char* expected_answer1, const char* expected_answer2, unsigned int timeout);
void measure_temperature();
void send_data(int _light, float _temperature);

char url[ ]= "api.thingspeak.com";
int port= 80;
int light;
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);   

  printf("Starting...\n");
  power_on();

  delay(3000);

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

  delay(3000);
  printf("Connecting to the network....\n");

  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);
  
  printf("Connected to the network!!\n");
  delay(2000);

}
void loop(){
  light = analogRead(1);
  measure_temperature();
    
  //Send data to Thingspeak via HTTP GET
  printf("Sending data:  light:%d - temperature:%f\n", light, temperature);
  send_data(light, temperature);
  
  //Wait a minute
  delay(6000);
}

/************************************************************************
 ****               Definition of functions                          ****
 ************************************************************************/

void measure_temperature()
{
  // take 10 samples from the MCP9700
  for (sample = 0; sample < 10; sample++) {
    // convert A0 value to temperature
    temperature = ((float)analogRead(0) * 5.0 / 1024.0) - 0.5;
    temperature = temperature / 0.01;
    // 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;
}

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)
  { 
    // set the request
    sprintf(aux_str, "GET /update?key=%s&field1=%d&field2=%f HTTP/1.1\r\nHost: api.thingspeak.com\r\nContent-Length: 0\r\n\r\n", APIWriteKey, _light, _temperature)  ; 
    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)
    {
        printf("Done!\n");
    }
    else
    {
      printf("Error sending the request\n");
    }
  }
  else
  {
    printf("Error waiting the request\n");
  }

  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(const char* ATcommand, const char* expected_answer1, unsigned int timeout)
{

  uint16_t x = 0,  answer = 0;
  char response[1000];
  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();
      printf("%c", response[x]);
      x++;
      // check if the desired answer is in the response of the module
      if (strstr(response, expected_answer1) != NULL)
      {
        printf("\n");
        answer = 1;
      }
    }
    // Waits for the asnwer with time out
  }
  while ((answer == 0) && ((millis() - previous) < timeout));

  return answer;
}



int8_t sendATcommand2(const char* ATcommand, const char* expected_answer1, const 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();
      printf("%c", response[x]);
      x++;
      // check if the desired answer 1 is in the response of the module
      if (strstr(response, expected_answer1) != NULL)
      {
        printf("\n");
        answer = 1;
      }
      // check if the desired answer 2 is in the response of the module
      if (strstr(response, expected_answer2) != NULL)
      {
        printf("\n");
        answer = 2;
      }
    }
    // Waits for the answer with time out
  }
  while ((answer == 0) && ((millis() - previous) < timeout));

  return answer;
}


int main () {
  setup();
  while (1) {
    loop();
  }
  return (0);
}


        

Intel Galileo:

Code:
/*  
 *  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:    Jorge Casanova, Luis Martin
 */

//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);
  Serial1.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);

}
void loop(){
  
  light = analogRead(A1);
  measure_temperature();
  
  //Send data to Thingspeak via HTTP GET
  send_data(light, temperature);
  
  //Wait a minute
  delay(60000);
}



/************************************************************************
 ****               Definition of functions                          ****
 ************************************************************************/

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

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)
  { 
    // set the request
    sprintf(aux_str, "GET /update?key=%s&field1=%d&field2=%f HTTP/1.1\r\nHost: api.thingspeak.com\r\nContent-Length: 0\r\n\r\n", APIWriteKey, _light, _temperature); 
    Serial1.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( Serial1.available() > 0) Serial1.read();    // Clean the input buffer

  Serial1.println(ATcommand);    // Send the AT command 


    x = 0;
  previous = millis();

  // this loop waits for the answer
  do{

    if(Serial1.available() != 0){    
      if (x == 100)
      {
        strncpy(response, response +1, 99);
        response[99] = Serial1.read();
      }
      else
      {
        response[x] = Serial1.read();
        Serial.print(response[x]);
        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( Serial1.available() > 0) Serial1.read();    // Clean the input buffer

  Serial1.println(ATcommand);    // Send the AT command 


    x = 0;
  previous = millis();

  // this loop waits for the answer
  do{

    if(Serial1.available() != 0){    
      response[x] = Serial1.read();
      Serial.print(response[x]);
      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;
}