My Cart

How to Send Filtered Photos via E-mail Using 3G+GPS Mobile Kit

Difficulty Level: Expert -

1. Introduction

This tutorial allows the user to send three different emails with color filtered photos. This is achieved by moving three color sheets attached to a servo.

Ingredients:

    - 1 x 3G+GPS Mobile Kit:
    • 1x Platform
    • 1x 3G + GPS shield
    • 1x GPRS antenna
    • 1x Servo
    • 1x Camera
    • 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 servo in the breadboard as you can see in the next diagram. We will also need the camera in this example, connect it to the shield as you can see here.

Connect two wires, red and black, to the two long rows on the side of the breadboard to provide access to the 3.3 volt supply and ground. Servo has 3 wires with different colors. Connect Black/Brown wire to GND, Red wire to 3.3 volt and the remaining wire, Yellow/Orange, to pin 9 of Arduino. Pin 9 has PWM control so you can move your servo from 0 to 180 degrees.

Step 2: The Code

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:    Victor Boria
 */

#include <Servo.h>  //Servo-motor library

Servo myServo;  // create a servo object
int angle;   // variable to hold the angle for the servo motor


//Write here you server and account data
const char smtp_server[ ] = "*********";      // SMTP server
const char smtp_user_name[ ] = "*********";   // SMTP user name
const char smtp_password[ ] = "*********";    // SMTP password
const char smtp_port[ ] = "***";              // SMTP server port

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

//Write here your information about sender, direcctions and names
const char sender_address[ ] = "*********";    // Sender address
const char sender_name[ ] = "*********";       // Sender name

const char to_address[ ] = "*********";        // Recipient address
const char to_name[ ] = "*********";           // Recipient name

//Write here the subject and body of the email
char subject_red[ ] = "Red photo";
char subject_green[ ] = "Green photo";
char subject_blue[ ] = "Blue photo";
const char body[ ] = "Hello! This is your picture";

int8_t answer, counter;
int onModulePin = 2;    // the pin to switch on the module (without press on button)
char picture_name[25];
char aux_str[128];


void setup() {
  myServo.attach(9); // attaches the servo on pin 9 to the servo object
  myServo.write(90); // set the servo in the center position

  delay(1000);

  pinMode(onModulePin, OUTPUT);
  Serial.begin(115200);      // UART baud rate

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

  power_on();    // Switches the module ON

  delay(3000);

  //sets the PIN code
  sprintf(aux_str, "AT+CPIN=%s", pin_number);
  sendATcommand(aux_str, "OK", 2000);
  
  //Deletes the photos and files in the internal memory, 
  //if it is full the camera doesn't work
  //sendATcommand("AT+FSDEL=*.*", "OK", 2000);
}

void loop() {
  
  //Red photo
  myServo.write(0);        // Turn the servo to red position
  delay(1000);
  take_picture();          // Takes a picture
  send_email(subject_red); // Sends an email with the picture
  delay(10000);            //Waits 10 seconds

  //Blue photo
  myServo.write(90);       // Turn the servo to red position
  delay(1000);
  take_picture();          // Takes a picture
  send_email(subject_blue);// Sends an email with the picture
  delay(10000);            //Waits 10 seconds

  //Green photo
  myServo.write(180);       // Turn the servo to red position
  delay(1000);
  take_picture();           // Takes a picture
  send_email(subject_green);// Sends an email with the picture
  
  //Deletes the photos in the internal memory
  //sendATcommand("AT+FSDEL=*.*", "OK", 2000);
  delay(10000);             //Waits 10 seconds
}


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

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




void take_picture() {

  // Starts the camera

  sendATcommand2("AT+CCAME", "OK", "CAMERA NO SENSOR", 1000);
  answer = sendATcommand2("AT+CCAMS", "OK", "CAMERA NO SENSOR", 3000);
  if (answer == 1)
  {
    // Sets resolution (Old camera)
    //sendATcommand2("AT+CCAMSETD=640,480", "OK", "ERROR", 2000);

    // Sets resolution (New camera)
    sendATcommand2("AT+CCAMSETD=1600,1200", "OK", "ERROR", 2000);

    // Takes a picture, but not saved it
    answer = sendATcommand2("AT+CCAMTP", "OK", "ERROR", 5000);
    delay(1000);
    if (answer == 1)
    {
      // Saves the picture into C:/Picture
      answer = sendATcommand2("AT+CCAMEP", "C:/Picture/", "ERROR", 2000);

      if (answer == 1)
      {
        memset(picture_name, 0x00, sizeof(picture_name));
        counter = 0;
        while (Serial.available() == 0);
        do {
          picture_name[counter] = Serial.read();
          counter++;
          while (Serial.available() == 0);
        } while (picture_name[counter - 1] != 0x0D);

        picture_name[counter - 1] = '\0';

        Serial.print("Picture name: ");
        Serial.println(picture_name);

        sendATcommand2("AT+CCAME", "OK", "", 2000);

      }
      else
      {
        Serial.println("Error saving the picture");
      }
    }
    else if (answer == 2)
    {
      Serial.println("Camera invalid state");
    }
    else
    {
      Serial.println("Error taking the picture");
    }
  }
  else if (answer == 2)
  {
    Serial.println("Camera not detected");
  }
  else
  {
    Serial.println("Error starting the camera");
  }

}

void send_email(char* _subject) {

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

  // sets the SMTP server and port
  sprintf(aux_str, "AT+SMTPSRV=\"%s\",%s", smtp_server, smtp_port);
  sendATcommand(aux_str, "OK", 2000);

  // sets user name and password
  sprintf(aux_str, "AT+SMTPAUTH=1,\"%s\",\"%s\"", smtp_user_name, smtp_password);
  sendATcommand(aux_str, "OK", 2000);

  // sets sender adress and name
  sprintf(aux_str, "AT+SMTPFROM=\"%s\",\"%s\"", sender_address, sender_name);
  sendATcommand(aux_str, "OK", 2000);

  // sets sender adress and name
  sprintf(aux_str, "AT+SMTPRCPT=1,0,\"%s\",\"%s\"", to_address, to_name);
  sendATcommand(aux_str, "OK", 2000);

  // subjet of the email
  sprintf(aux_str, "AT+SMTPSUB=\"%s\"", _subject);
  sendATcommand(aux_str, "OK", 2000);

  // body of the email
  sprintf(aux_str, "AT+SMTPBODY=\"%s\"", body);
  sendATcommand(aux_str, "OK", 2000);



  sendATcommand("AT+FSCD=Picture", "OK", 2000);

  //memcpy(picture_name_new, picture_name, sizeof(picture_name) - 1);

  sprintf(aux_str, "AT+SMTPFILE=1,\"%s\"", picture_name);
  sendATcommand(aux_str, "OK", 2000);


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

  delay(2000);

  Serial.println("Sending email...");
  // sends the email and waits the answer of the module
  answer = sendATcommand2("AT+SMTPSEND", "+SMTP: SUCCESS", "NETWORK ERROR", 60000);
  if (answer == 1)
  {
    Serial.println("Done!");
  }
  else if (answer == 2)
  {
    Serial.println("Error2");
  }

  else
  {

    Serial.println("Error");
  }

}


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 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 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 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
      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 server and account data
const char smtp_server[ ] = "*********";      // SMTP server
const char smtp_user_name[ ] = "*********";   // SMTP user name
const char smtp_password[ ] = "*********";    // SMTP password
const char smtp_port[ ] = "***";              // SMTP server port

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

//Write here your information about sender, direcctions and names
const char sender_address[ ] = "*********";    // Sender address
const char sender_name[ ] = "*********";       // Sender name

const char to_address[ ] = "*********";        // Recipient address
const char to_name[ ] = "*********";           // Recipient name

//Write here the subject and body of the email
char subject_red[ ] = "Red photo";
char subject_green[ ] = "Green photo";
char subject_blue[ ] = "Blue photo";
const char body[ ] = "Hello! This is your picture";

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 take_picture();
void send_email(char* _subject);
void servoWrite(int servo, int angle);

int angle;   // variable to hold the angle for the servo motor
int servo = 9;
unsigned int us;
int8_t answer, counter;
int onModulePin = 2;    // the pin to switch on the module (without press on button)
char picture_name[25];
char aux_str[128];


void setup() {
  pinMode(servo, OUTPUT);
  servoWrite(servo, 90);  
  delay(1000);

  pinMode(onModulePin, OUTPUT);
  Serial.begin(115200);      // UART baud rate

  printf("Starting...\n");
  power_on();    // Switches the module ON
  delay(3000);

  //sets the PIN code
  sprintf(aux_str, "AT+CPIN=%s", pin_number);
  sendATcommand(aux_str, "OK", 2000);
  
  //We recommend deleting the files in the memory, if it's full the code doesn't work
  //Uncomment these two lines for deleting
  //sendATcommand("AT+FSDEL=*.*", "OK", 2000); 
  //delay(2000);
  //printf("Deleting files in internal memory\n");

}
void loop() {
  
  //Red photo
  printf("Taking red photo\n");
  servoWrite(servo, 0);  
  delay(1000);
  take_picture();   // Takes a picture
  send_email(subject_red);     // Sends an email with coordinates and picture

  delay(10000);

  //Blue photo
  printf("Taking blue photo\n");
  servoWrite(servo, 90);  
  delay(1000);
  take_picture();   // Takes a picture
  send_email(subject_blue);     // Sends an email with coordinates and picture

  delay(10000);

  //Green photo
  printf("Taking green photo\n");
  servoWrite(servo, 180);  
  delay(1000);
  take_picture();   // Takes a picture
  send_email(subject_green);     // Sends an email with coordinates and picture

  delay(10000);
  
  //We recommend deleting the files in the memory, if it's full the code doesn't work
  //Uncomment these two lines for deleting
  //sendATcommand("AT+FSDEL=*.*", "OK", 2000); 
  //delay(2000);
  //printf("Deleting files in internal memory\n");

}


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


void servoWrite(int servo, int angle)
{
  for(int i=0; i<20; i++){
    us = (angle*11) + 450;      // Convert angle to microseconds
    digitalWrite(servo, HIGH);
    delayMicroseconds(us);
    digitalWrite(servo, LOW);
    delay(50);                  // Refresh cycle of servo
  }               
}


void take_picture(){

  // Starts the camera
  sendATcommand2("AT+CCAME", "OK", "CAMERA NO SENSOR", 1000);
  answer = sendATcommand2("AT+CCAMS", "OK", "CAMERA NO SENSOR", 3000);
  if (answer == 1)
  {
    // Sets resolution (Old camera)
    //sendATcommand2("AT+CCAMSETD=640,480", "OK", "ERROR", 2000);

    // Sets resolution (New camera)
    sendATcommand2("AT+CCAMSETD=1600,1200", "OK", "ERROR", 2000);

    // Takes a picture, but not saved it
    answer = sendATcommand2("AT+CCAMTP", "OK", "ERROR", 5000);
    delay(1000);
    if (answer == 1)
    {
      // Saves the picture into C:/Picture
      answer = sendATcommand2("AT+CCAMEP", "C:/Picture/", "ERROR", 2000);

      if (answer == 1)
      {
        memset(picture_name, 0x00, sizeof(picture_name));
        counter = 0;
        while (Serial.available() == 0);
        do {
          picture_name[counter] = Serial.read();
          counter++;
          while (Serial.available() == 0);
        } while (picture_name[counter - 1] != 0x0D);

        picture_name[counter - 1] = '\0';

        printf("Picture name: %s\n", picture_name);

        sendATcommand2("AT+CCAME", "OK", "", 2000);

      }
      else
      {
        printf("Error saving the picture\n");
      }
    }
    else if (answer == 2)
    {
		printf("Camera invalid state\n");

    }
    else
    {
      printf("Error taking the picture\n");
    }
  }
  else if (answer == 2)
  {
    printf("Camera not detected\n");
  }
  else
  {
    printf("Error starting the camera\n");
  }

}

void send_email(char* _subject) {

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

  // sets the SMTP server and port
  sprintf(aux_str, "AT+SMTPSRV=\"%s\",%s", smtp_server, smtp_port);
  sendATcommand(aux_str, "OK", 2000);

  // sets user name and password
  sprintf(aux_str, "AT+SMTPAUTH=1,\"%s\",\"%s\"", smtp_user_name, smtp_password);
  sendATcommand(aux_str, "OK", 2000);

  // sets sender adress and name
  sprintf(aux_str, "AT+SMTPFROM=\"%s\",\"%s\"", sender_address, sender_name);
  sendATcommand(aux_str, "OK", 2000);

  // sets sender adress and name
  sprintf(aux_str, "AT+SMTPRCPT=1,0,\"%s\",\"%s\"", to_address, to_name);
  sendATcommand(aux_str, "OK", 2000);

  // subjet of the email
  sprintf(aux_str, "AT+SMTPSUB=\"%s\"", _subject);
  sendATcommand(aux_str, "OK", 2000);

  // body of the email
  sprintf(aux_str, "AT+SMTPBODY=\"%s\"", body);
  sendATcommand(aux_str, "OK", 2000);



  sendATcommand("AT+FSCD=Picture", "OK", 2000);

  //memcpy(picture_name_new, picture_name, sizeof(picture_name) - 1);

  sprintf(aux_str, "AT+SMTPFILE=1,\"%s\"", picture_name);
  sendATcommand(aux_str, "OK", 2000);


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

  delay(2000);

  printf("Sending %s email...\n", _subject);
  // sends the email and waits the answer of the module
  answer = sendATcommand2("AT+SMTPSEND", "+SMTP: SUCCESS", "NETWORK ERROR", 60000);
  if (answer == 1)
  {
    printf("Done!\n");
  }
  else if (answer == 2)
  {
	  printf("Error2\n");
  }

  else
  {

    printf("Error\n");
  }

}


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:
#include <Servo.h>  //Servo-motor library

Servo myServo;  // create a servo object
int angle;   // variable to hold the angle for the servo motor


//Write here you server and account data
const char smtp_server[ ] = "*********";      // SMTP server
const char smtp_user_name[ ] = "*********";   // SMTP user name
const char smtp_password[ ] = "*********";    // SMTP password
const char smtp_port[ ] = "***";              // SMTP server port

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

//Write here your information about sender, direcctions and names
const char sender_address[ ] = "*********";    // Sender address
const char sender_name[ ] = "*********";       // Sender name

const char to_address[ ] = "*********";        // Recipient address
const char to_name[ ] = "*********";           // Recipient name

//Write here the subject and body of the email
char subject_red[ ] = "Red photo";
char subject_green[ ] = "Green photo";
char subject_blue[ ] = "Blue photo";
const char body[ ] = "Hello! This is your picture";

int8_t answer, counter;
int onModulePin = 2;    // the pin to switch on the module (without press on button)
char picture_name[25];
char aux_str[128];


void setup() {
  myServo.attach(9); // attaches the servo on pin 9 to the servo object
  myServo.write(90); // set the servo in the center position

  delay(1000);

  pinMode(onModulePin, OUTPUT);
  Serial.begin(115200);      // UART baud rate
  Serial1.begin(115200);

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

  power_on();    // Switches the module ON

  delay(3000);

  //sets the PIN code
  sprintf(aux_str, "AT+CPIN=%s", pin_number);
  sendATcommand(aux_str, "OK", 2000);
  
  //Deletes the photos and files in the internal memory, 
  //if it is full the camera doesn't work
  sendATcommand("AT+FSDEL=*.*", "OK", 2000);
}

void loop() {
  
  //Red photo
  myServo.write(0);        // Turn the servo to red position
  delay(1000);
  take_picture();          // Takes a picture
  send_email(subject_red); // Sends an email with the picture
  delay(10000);            //Waits 10 seconds

  //Blue photo
  myServo.write(90);       // Turn the servo to red position
  delay(1000);
  take_picture();          // Takes a picture
  send_email(subject_blue);// Sends an email with the picture
  delay(10000);            //Waits 10 seconds

  //Green photo
  myServo.write(180);       // Turn the servo to red position
  delay(1000);
  take_picture();           // Takes a picture
  send_email(subject_green);// Sends an email with the picture
  
  //Deletes the photos in the internal memory
  sendATcommand("AT+FSDEL=*.*", "OK", 2000);
  delay(10000);             //Waits 10 seconds
}


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

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




void take_picture() {

  // Starts the camera

  sendATcommand2("AT+CCAME", "OK", "CAMERA NO SENSOR", 1000);
  answer = sendATcommand2("AT+CCAMS", "OK", "CAMERA NO SENSOR", 3000);
  if (answer == 1)
  {
    // Sets resolution (Old camera)
    //sendATcommand2("AT+CCAMSETD=640,480", "OK", "ERROR", 2000);

    // Sets resolution (New camera)
    sendATcommand2("AT+CCAMSETD=1600,1200", "OK", "ERROR", 2000);

    // Takes a picture, but not saved it
    answer = sendATcommand2("AT+CCAMTP", "OK", "ERROR", 5000);
    delay(1000);
    if (answer == 1)
    {
      // Saves the picture into C:/Picture
      answer = sendATcommand2("AT+CCAMEP", "C:/Picture/", "ERROR", 2000);

      if (answer == 1)
      {
        memset(picture_name, 0x00, sizeof(picture_name));
        counter = 0;
        while (Serial1.available() == 0);
        do {
          picture_name[counter] = Serial1.read();
          counter++;
          while (Serial1.available() == 0);
        } while (picture_name[counter - 1] != 0x0D);

        picture_name[counter - 1] = '\0';

        Serial.print("Picture name: ");
        Serial.println(picture_name);

        sendATcommand2("AT+CCAME", "OK", "", 2000);

      }
      else
      {
        Serial.println("Error saving the picture");
      }
    }
    else if (answer == 2)
    {
      Serial.println("Camera invalid state");
    }
    else
    {
      Serial.println("Error taking the picture");
    }
  }
  else if (answer == 2)
  {
    Serial.println("Camera not detected");
  }
  else
  {
    Serial.println("Error starting the camera");
  }

}

void send_email(char* _subject) {

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

  // sets the SMTP server and port
  sprintf(aux_str, "AT+SMTPSRV=\"%s\",%s", smtp_server, smtp_port);
  sendATcommand(aux_str, "OK", 2000);

  // sets user name and password
  sprintf(aux_str, "AT+SMTPAUTH=1,\"%s\",\"%s\"", smtp_user_name, smtp_password);
  sendATcommand(aux_str, "OK", 2000);

  // sets sender adress and name
  sprintf(aux_str, "AT+SMTPFROM=\"%s\",\"%s\"", sender_address, sender_name);
  sendATcommand(aux_str, "OK", 2000);

  // sets sender adress and name
  sprintf(aux_str, "AT+SMTPRCPT=1,0,\"%s\",\"%s\"", to_address, to_name);
  sendATcommand(aux_str, "OK", 2000);

  // subjet of the email
  sprintf(aux_str, "AT+SMTPSUB=\"%s\"", _subject);
  sendATcommand(aux_str, "OK", 2000);

  // body of the email
  sprintf(aux_str, "AT+SMTPBODY=\"%s\"", body);
  sendATcommand(aux_str, "OK", 2000);



  sendATcommand("AT+FSCD=Picture", "OK", 2000);

  //memcpy(picture_name_new, picture_name, sizeof(picture_name) - 1);

  sprintf(aux_str, "AT+SMTPFILE=1,\"%s\"", picture_name);
  sendATcommand(aux_str, "OK", 2000);


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

  delay(2000);

  Serial.println("Sending email...");
  // sends the email and waits the answer of the module
  answer = sendATcommand2("AT+SMTPSEND", "+SMTP: SUCCESS", "NETWORK ERROR", 60000);
  if (answer == 1)
  {
    Serial.println("Done!");
  }
  else if (answer == 2)
  {
    Serial.println("Error2");
  }

  else
  {

    Serial.println("Error");
  }

}


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 there are data in the UART input buffer, reads it and checks for the asnwer
    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;
      }
    }
    // 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 there are data in the UART input buffer, reads it and checks for the asnwer
    if (Serial1.available() != 0) {
      response[x] = Serial1.read();
      Serial.print(response[x]);
      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
      if (strstr(response, expected_answer2) != NULL)
      {
        answer = 2;
      }
    }
    // Waits for the asnwer with time out
  } while ((answer == 0) && ((millis() - previous) < timeout));

  return answer;
}