Tutorial: How to use SIM800L GSM Module for Controlling Anything | Arduino

In this tutorial, you will be able to use the SIM800L GSM module for controlling anything through SMS. To do that, we just need to parse the incoming SMS from SIM800L through serial communication. In this Arduino sketch, we will be parsing the following:
1. Find the string “CMT:”, then save the sender’s mobile number for the purpose of replying.
2. Find the string “CMD:”, then save the specified commands
3. Find the string “NUM:”, then save the new default mobile number.

After successful parsing, we can process the command and act accordingly.

Circuit Diagram:





























Video Demonstration:

If you have any question regarding this tutorial, please do not hesitate to write it in the comment box.

If you find this tutorial helpful, please consider supporting me by SUBSCRIBING to my Youtube channel: Click this to Subscribe to TechToTinker.

Source Code / Arduino Sketch:


/*  Date: July 29, 2020
 *  Author: George Bantique, TechToTinker Youtube channel
 *          https://techtotinker.blogspot.com
 *  Tutorial: How to use SIM800L to control anything
 *  Description:
 *      In this Arduino sketch, you will be able to send specific commands 
 *      to control anything. It can also be configured to reply in every sms
 *      you send.
 *      
 *      Here are the breakdown of available option:
 *        Send command in this format:
 *            CMD: RED 1<
 *              - turn ON the red LED
 *            CMD: RED 0<
 *              - turn OFF the red LED
 *            CMD: GRN 1<
 *              - turn ON the green LED
 *            CMD: GRN 0<
 *              - turn OFF the green LED
 *            CMD: BLU 1<
 *              - turn ON the blue LED
 *            CMD: BLU 0<
 *              - turn OFF the blue LED
 *            CMD: ALL 1<
 *              - turn ON all the LED
 *            CMD: ALL 0<
 *              - turn OFF all the LED
 *            CMD: REP 1<
 *              - enable the reply for every SMS
 *            CMD: REP 0<
 *              - disable the reply, but will still reply to the following:
 *                CMD: REP 1<
 *                CMD: REP 0<
 *                CMD: GET S<
 *            CMD: GET S<
 *              - sends the current states of the LEDs
 *            NUM: +ZZxxxxxxxxxx<
 *              - changes the current default number
 *                ZZ - country code
 *                xx - 10-digit number
 *      When event is triggered let say in this tutorial, we just use a push button tactile switch    
 *      but you can expand it, for example you can use an intruder detection that will send an SMS
 *      when an intruder is detected.
 *      
 *      Please feel free to modify it to adapt to your specific needs, just leave this comments as      
 *      credits to me. Thank you and happy tinkering. -George
 */
#include "SoftwareSerial.h"

#define SERIAL_DEBUG          // comment out this to remove serial debug
#define SMS_ENABLED           // comment out this to disable sms sending, to save from expenses
#define SIMULATE_BY_SERIAL    // comment out this to use the actual SIM800L

SoftwareSerial SIM800L(11, 12);  // Arduino D11(as Rx pin) to SIM800L Tx pin
                                 // Arduino D12(as Tx pin) to SIM800L Rx pin
#define RED_LED   7   // Pin assignments for LED and Switch
#define GRN_LED   6
#define BLU_LED   5
#define SW_PIN    4

#define BUFFER_SIZE   127       // incoming data buffer size
char bufferData[BUFFER_SIZE];   // holds the char data
char bufferIndex;               // holds the position of the char in the buffer

// This variable holds the SMS sender mobile number, it will be updated when new sms arrived
char sender_num[14] = {'+', '6', '3', '9', '7', '5', '9', '2', '3', '1', '2', '4', '3' };

// This variable holds the mobile number of the owner, emergency sms will be sent to this
// when the event is triggered lets say the button press
char default_num[14] = {'+', '6', '3', '9', '7', '5', '9', '2', '3', '1', '2', '4', '3' };

char sender_cmd[7];     // holds the specific command when a new SMS is received

bool CMT_OK = false;    // CMT is for processing the SMS senders mobile number
int cmt_pos_index = 0;  
int cmt_pos_count = 0;

bool CMD_OK = false;    // CMD is for processing the parsing the sms command
int cmd_pos_index = 0;
int cmd_pos_count = 0;

bool NUM_OK = false;    // NUM is for processing the CHANGE NUMBER option
int num_pos_index = 0;
int num_pos_count = 0;

bool redLEDState = false;   // holds the state of LEDs
bool grnLEDState = false;   //    true:  means ON
bool bluLEDState = false;   //    false: means OFF

bool newData = false;

bool isReplyOn = false;     // hold the settings for sending the status update for every sms 
                            //    true:  reply to every sms
                            //    false: reply only to some sms request like request for status

bool currState = HIGH;            // this variables are for the button debouncing
bool prevState = HIGH;
unsigned long startMillis = 0;
unsigned long debounceDelay = 50;

/*
 *  Function: void setup()
 *  Purpose:
 *    This function is for initializations
 */
void setup(){
  Serial.begin(9600);
  Serial.println("Initializing...");
  SIM800L.begin(9600);
  delay(2000);      // gives enough time for the GSM module to bootup
  initializeGSM();  // set the necessary initializations for the GSM module
  pinMode(RED_LED, OUTPUT);           // set the pin directions of other pins
  pinMode(GRN_LED, OUTPUT);
  pinMode(BLU_LED, OUTPUT);
  pinMode(SW_PIN, INPUT_PULLUP);
  digitalWrite(RED_LED, redLEDState); // set the current states of LEDs
  digitalWrite(GRN_LED, grnLEDState);
  digitalWrite(BLU_LED, bluLEDState);
  memset(bufferData, 0, sizeof(bufferData)); // Initialize the string     
  bufferIndex = 0; 
  Serial.println("Setup done");

}

/*
 *  Function: void loop()
 *  Purpose:
 *    This is the main loop
 */
void loop(){
  manageButton();
  manageSIM800();
  delay(500);
}

/*
 *  Function: void initializeGSM()
 *  Purpose:
 *    This function is for the SIM800L initializations
 */
void initializeGSM() {
#ifdef SIMULATE_BY_SERIAL
  Serial.println("AT");                   // Sends an ATTENTION command, reply should be OK
  Serial.println("AT+CMGF=1");            // Configuration for sending SMS
  Serial.println("AT+CNMI=1,2,0,0,0");    // Configuration for receiving SMS
  Serial.println("AT&W");                 // Save the configuration settings
#else // actual
  SIM800L.println("AT");                  // Sends an ATTENTION command, reply should be OK
  delay(1000);
  SIM800L.println("AT+CMGF=1");           // Configuration for sending SMS
  delay(1000);
  SIM800L.println("AT+CNMI=1,2,0,0,0");   // Configuration for receiving SMS
  delay(1000);
  Serial.println("AT&W");                 // Save the configuration settings
  delay(1000);
#endif // SIMULATE_BY_SERIAL
}

/*
 *  Function: void manageButton()
 *  Purpose:
 *    This is for polling the state of the button.
 *    Additional button debouncing is use to prevent
 *    false button presses.
 */
void manageButton() {
  bool currRead = digitalRead(SW_PIN);  

  if (currState != prevState) {
    startMillis = millis();
  }
  if ((millis() - startMillis) > debounceDelay) {
    if (currRead != currState) {
      currState = currRead;
      if (currState == LOW) {
#ifdef SERIAL_DEBUG
        Serial.println("Alert!");
#endif //SERIAL_DEBUG
        sendSMS("Alert! Event triggered", default_num);
      }
    }
  }
  prevState = currState;
}

/*
 *  Function: void manageSIM800()
 *  Purpose:
 *    This is for parsing the incoming serial data from SIM800L
 *    so that we can use it for controlling something.
 */
void manageSIM800() {
 
#ifdef SIMULATE_BY_SERIAL
  while (Serial.available() > 0) {
    bufferData[bufferIndex] = Serial.read();
    // Find the string "CMD:"
    //    if found, parse the command for processing
    if( //(bufferData[bufferIndex-3] == 'C') && 
        //(bufferData[bufferIndex-2] == 'M') && 
        (bufferData[bufferIndex-1] == 'D') && 
        (bufferData[bufferIndex] == ':')      )  {               
      //Serial.println("CMD"); 
      CMD_OK = true;      
      memset(sender_cmd, 0, sizeof(sender_cmd));
      cmd_pos_index = bufferIndex;  // get the position
      cmd_pos_count = 0;            // reset pos counter   
    }    
    // Finds the string "NUM:"
    //    if found, parse the command for processing
    if( //(bufferData[bufferIndex-3] == 'N') &&
        //(bufferData[bufferIndex-2] == 'U') && 
        (bufferData[bufferIndex-1] == 'M') && 
        (bufferData[bufferIndex] == ':')      )  {              
      //Serial.println("NUM"); 
      NUM_OK = true;
      memset(default_num, 0, sizeof(default_num));
      num_pos_index = bufferIndex;  // get the position
      num_pos_count = 0;            // reset pos counter 
      
    } 
    // Finds the string "CMT:"
    //    if found, parse the command for processing
    if( //(bufferData[bufferIndex-3] == 'C') && 
        //(bufferData[bufferIndex-2] == 'M') && 
        (bufferData[bufferIndex-1] == 'T') && 
        (bufferData[bufferIndex] == ':')      )  {            
      //Serial.println("CMT");  
      CMT_OK = true;
      memset(sender_num, 0, sizeof(sender_num));    
      cmt_pos_index = bufferIndex;  // get the position
      cmt_pos_count = 0;            // reset pos counter 
    }    
    // String "CMT:" is found, 
    //  parse the sender number for the reply
    //
    if ( ( (bufferIndex - cmt_pos_index) > 2 ) && (CMT_OK) ) {
      if ( cmt_pos_count < 13 ) {
        sender_num[cmt_pos_count] =  bufferData[bufferIndex];
        cmt_pos_count++;
      } else {
        //Serial.println(sender_num);
        CMT_OK = false; // done
      }
    }
    
    // String "NUM:" is found
    //  parse it then save it as default number then send a reply
    //
    if ( ( (bufferIndex - num_pos_index) > 1 ) && (NUM_OK) ) {
      if ( bufferData[bufferIndex] != '<' ) {
        default_num[num_pos_count] =  bufferData[bufferIndex];
        num_pos_count++;
      } else {
        char msg[32] = "Default # is now ";
        sendSMS((strcat( msg, default_num )), sender_num);                          // send it to the recipient number.
        NUM_OK = false; // done
        break;
      }
    } 
    // String "CMD:" is found,
    //  parse the command, then execute the command
    //
    if ( ( (bufferIndex - cmd_pos_index) > 1 ) && (CMD_OK)) {
      if (bufferData[bufferIndex] == '<') {
        //Serial.println(sender_cmd);
        processCommand();
        CMT_OK = false; // done
        break;
      } else {
        sender_cmd[cmd_pos_count] =  bufferData[bufferIndex];
        cmd_pos_count++;
      }
    } 
    bufferIndex++;                              
  }           

  memset(bufferData, 0, sizeof(bufferData));    // Initialize the string     
  bufferIndex = 0;
#else // actual SIM800L GSM Module
  while (SIM800L.available() > 0) {
    bufferData[bufferIndex] = SIM800L.read();
    // Find the string "CMD:"
    //    if found, parse the command for processing
    if( //(bufferData[bufferIndex-3] == 'C') && 
        //(bufferData[bufferIndex-2] == 'M') && 
        (bufferData[bufferIndex-1] == 'D') && 
        (bufferData[bufferIndex] == ':')      )  {               
      //Serial.println("CMD"); 
      CMD_OK = true;      
      memset(sender_cmd, 0, sizeof(sender_cmd));
      cmd_pos_index = bufferIndex;  // get the position
      cmd_pos_count = 0;            // reset pos counter   
    }    
    // Finds the string "NUM:"
    //    if found, parse the command for processing
    if( //(bufferData[bufferIndex-3] == 'N') &&
        //(bufferData[bufferIndex-2] == 'U') && 
        (bufferData[bufferIndex-1] == 'M') && 
        (bufferData[bufferIndex] == ':')      )  {              
      //Serial.println("NUM"); 
      NUM_OK = true;
      memset(default_num, 0, sizeof(default_num));
      num_pos_index = bufferIndex;  // get the position
      num_pos_count = 0;            // reset pos counter 
    } 
    // Finds the string "CMT:"
    //    if found, parse the command for processing
    if( //(bufferData[bufferIndex-3] == 'C') && 
        //(bufferData[bufferIndex-2] == 'M') && 
        (bufferData[bufferIndex-1] == 'T') && 
        (bufferData[bufferIndex] == ':')      )  {            
      //Serial.println("CMT");  
      CMT_OK = true;
      memset(sender_num, 0, sizeof(sender_num));    
      cmt_pos_index = bufferIndex;  // get the position
      cmt_pos_count = 0;            // reset pos counter 
    }    
    // String "CMT:" is found, 
    //  parse the sender number for the reply
    // +CMT: "+639175291539"
    if ( ( (bufferIndex - cmt_pos_index) > 2 ) && (CMT_OK) ) {
      if ( cmt_pos_count < 13 ) {
        sender_num[cmt_pos_count] =  bufferData[bufferIndex];
        cmt_pos_count++;
      } else {
        //Serial.println(sender_num);
        CMT_OK = false; // done
      }
    }
    // String "NUM:" is found
    //  parse it then save it as default number then send a reply
    //
    if ( ( (bufferIndex - num_pos_index) > 1 ) && (NUM_OK) ) {
      if ( bufferData[bufferIndex] != '<' ) {
        default_num[num_pos_count] =  bufferData[bufferIndex];
        num_pos_count++;
      } else {
        char msg[32] = "Default # is now ";
        sendSMS((strcat( msg, default_num )), sender_num);                          // send it to the recipient number.
        NUM_OK = false; // done
        break;
      }
    } 
    // String "CMD:" is found,
    //  parse the command, then execute the command
    //  CMD: GRN 0<
    if ( ( (bufferIndex - cmd_pos_index) > 1 ) && (CMD_OK)) {
      if (bufferData[bufferIndex] == '<') {
        //Serial.println(sender_cmd);
        processCommand();
        CMT_OK = false; // done
        break;
      } else {
        sender_cmd[cmd_pos_count] =  bufferData[bufferIndex];
        cmd_pos_count++;
      }
    } 
    bufferIndex++;                              
  }           
  memset(bufferData, 0, sizeof(bufferData));    // Initialize the string     
  bufferIndex = 0;
#endif //SIMULATE_BY_SERIAL
}

/*
 *  Function: void processCommand()
 *  Purpose:
 *    This function execute the receive commands via SMS
 *    CMD: RED 1<
 */   
void processCommand() {
  if        (strcmp(sender_cmd, "RED 1") == 0) {
    redLEDState = true;
    if (isReplyOn)
      sendSMS("Red LED On", sender_num);
  } else if (strcmp(sender_cmd, "RED 0") == 0) {
    redLEDState = false;
    if (isReplyOn)
      sendSMS("Red LED Off", sender_num);
  } else if (strcmp(sender_cmd, "GRN 1") == 0) {
    grnLEDState = true;
    if (isReplyOn)
      sendSMS("Green LED On", sender_num);
  } else if (strcmp(sender_cmd, "GRN 0") == 0) {
    grnLEDState = false;
    if (isReplyOn)
      sendSMS("Green LED Off", sender_num);
  } else if (strcmp(sender_cmd, "BLU 1") == 0) {
    bluLEDState = true;
    if (isReplyOn)
      sendSMS("Blue LED On", sender_num);
  } else if (strcmp(sender_cmd, "BLU 0") == 0) {
    bluLEDState = false;
    if (isReplyOn)
      sendSMS("Blue LED Off", sender_num);
  } else if (strcmp(sender_cmd, "ALL 0") == 0) {
    redLEDState = false;
    grnLEDState = false;
    bluLEDState = false;
    if (isReplyOn)
      sendSMS("All LED Off", sender_num);
  } else if (strcmp(sender_cmd, "ALL 1") == 0) {
    redLEDState = true;
    grnLEDState = true;
    bluLEDState = true;
    if (isReplyOn)
      sendSMS("All LED On", sender_num);
  } else if (strcmp(sender_cmd, "REP 1") == 0) {       // This command is to turn ON the reply to every sms
    isReplyOn = true;
#ifdef SMS_ENABLED
    sendSMS("Reply is now ON", sender_num);
#endif //SMS_ENABLED
  } else if (strcmp(sender_cmd, "REP 0") == 0) {      // This command is to turn OFF the reply to every sms
    isReplyOn = false;
#ifdef SMS_ENABLED
    sendSMS("Reply is now OFF", sender_num);
#endif //SMS_ENABLED
  } else if (strcmp(sender_cmd, "GET S") == 0) {    // This command sends the current status of all LEDs
    String statusSMS = "";                               // Create the status reply
    statusSMS = "Red LED is ";
    if (redLEDState) {
      statusSMS += "ON";
    } else statusSMS += "OFF";
    statusSMS += ". Green LED is ";
    if (grnLEDState) {
      statusSMS += "ON";
    } else statusSMS += "OFF";
    statusSMS += ". Blue LED is ";
    if (bluLEDState) {
      statusSMS += "ON";
    } else statusSMS += "OFF";
#ifdef SMS_ENABLED
    sendSMS(statusSMS, sender_num);
#endif //SMS_ENABLED
  } 
  digitalWrite(RED_LED, redLEDState);   // Sets the LED states according
  digitalWrite(GRN_LED, grnLEDState);   //  according to the received
  digitalWrite(BLU_LED, bluLEDState);   //  commands

}

/*
 *  Function: void sendSMS(String message, String mobile)
 *  Purpose:
 *    This function is use for sending the reply SMS
 */
void sendSMS(String message, String mobile) {
#ifdef SIMULATE_BY_SERIAL
  Serial.println("AT+CMGS="" + mobile + ""r"); //Mobile phone number to send message
  Serial.println(message);                        // This is the message to be sent.
  Serial.println((char)26);                       // ASCII code of CTRL+Z to finalized the sending of sms
#else // actual
  //SIM800L.println("AT+CMGF=1");                    //Sets the GSM Module in Text Mode
  //delay(1000);
  SIM800L.println("AT+CMGS="" + mobile + ""r"); //Mobile phone number to send message
  delay(1000);
  SIM800L.println(message);                        // This is the message to be sent.
  delay(1000);
  SIM800L.println((char)26);                       // ASCII code of CTRL+Z to finalized the sending of sms
  delay(1000);
#endif // SIMULATE_BY_SERIAL
}

35 thoughts on “Tutorial: How to use SIM800L GSM Module for Controlling Anything | Arduino

  1. Hi Jilberth, I just updated the blog post. You can do as follows:
    1. a voltage divider circuit for the SIM800 Rx pin with 560 and 100 Ohms resistor (refer to the circuit diagram). This is to limit the voltage coming to SIM800L to acceptable value. SIM800L is 2.8V logic level.
    2. limiting resistors for LEDs could be a 220 Ohms or higher.
    3. Power the SIM800L with 3.4 to 4.4V.
    4. Any electrolytic caps could be use just to filter some noise.

    Hope this helps. Cheers, George.

  2. Sir, I need your help for a project. The light should turn on and off, when the message received is from the default number only. Can you implement this with the above code.

  3. Good day sir. Applicable din po ba ang code na ito sa sim808 module? In case palitan lng po ng sim808 lahat ng code about sim800l,pati sim800l library to sim808 library? Thank you po sa maganda niong project. Balak ko po itry kaso sim 808 po ang meron ako.. thank you un advance. GODBLESS

  4. great tutorial… will try this project when my SIM800L arrives… planning to make it as phonepatch for our ham group… hope u can help me… thabks

  5. Kindly help to formulation of code for event with current measure continuous for 3 phase by Acs712. In case current drops from set value fault signal sms by 800L. Also gives web page data by 800L.

  6. Thanks for prompt reply. Actually, we want to monitor 3 light current feedback, if any light go out due to any fault in remote location get sms alart. Current range 0.8A ac to 2A. Can you help me with any modules available in market.

  7. Thank you so much for this project!

    All commands work fine as decsribed but if I send a command from my cellphone there is no action
    Calling is possible
    Is there anything else to do?

  8. Did you format the SMS command as follows:

    * Send command in this format:
    * CMD: RED 1<
    * – turn ON the red LED
    * CMD: RED 0<
    * – turn OFF the red LED
    * CMD: GRN 1<
    * – turn ON the green LED
    * CMD: GRN 0<
    * – turn OFF the green LED
    * CMD: BLU 1<
    * – turn ON the blue LED
    * CMD: BLU 0<
    * – turn OFF the blue LED
    * CMD: ALL 1<
    * – turn ON all the LED
    * CMD: ALL 0<
    * – turn OFF all the LED
    * CMD: REP 1<
    * – enable the reply for every SMS
    * CMD: REP 0<
    * – disable the reply, but will still reply to the following:
    * CMD: REP 1<
    * CMD: REP 0<
    * CMD: GET S<
    * CMD: GET S<
    * – sends the current states of the LEDs
    * NUM: +ZZxxxxxxxxxx<
    * – changes the current default number
    * ZZ – country code
    * xx – 10-digit number

  9. Thanks for sharing such an AWESOME project.
    Can you please add some more feature to this like a 0.96 inch display showing name of the installed SIM operator & RSSI Signal Strength Level on startup of the device & then the other info status according to the current mode accordingly.

  10. Hello really thanks for your amazing work
    catch incoming mobile number to compare it with whitelist numbers to make some actions with arduino

  11. Hello really thanks for your amazing work
    catch incoming mobile number to compare it with whitelist numbers to make some actions with arduino

  12. thank you, I have practically the same tutorial, with the same hardware, I have made copy your program with some modifications of Number. I can't activate the leds with SMS received from my phone.
    when I try to read the message received, the serial monitor displays these "????" characters.
    Help please.

  13. char sender_num[14] =
    char default_num[14] =
    Hello, please explain more about these two lines. Where should I enter the sender's mobile number and the SIM card number inside GSM?

  14. default_num – should contain the number where the emergency should be sent.

    sender_num – is a variable to hold the mobile number of the sms received. You may initialized it with all zeroes if you like.

    SIM card number inside GSM – no need for this, you will not use it.

  15. No, you should learn how a function works. To give you a brief idea, a function has a parameters similar to an input and an optional return value similar to an output.

    Now the "mobile" there is a parameter from the function:
    void sendSMS(String message, String mobile)

    Cheers.

  16. Maraming salamat po sir dahil po sa inyo marami po akong natutunan sana po sir george mag labas kayo ng topic about sa gps via 800l gsm at using load po para po sa proj research po nmin.

  17. HELLO, first of all its a great idea. I have a question, how to check available balance of the sim in gsm module. or is it possible to include the balance in the end of the message? thnks kabayan.

  18. Hi sir, I try to change default number by texting NUM: +63xxxxxxxxxx,
    but nothing happen, and when I text CMD: RED 1< , it reply to me with
    "Default # is now +639177RED 1". I also notice on your video at time 3:53
    same error on your cellpone appear, How it happen? pls comment on this.

  19. Hi George! First of all,thnks for sharing this…I got it already working almost perfectly. Could you please enlightme what am i doing wrong? if everything works less the reply by sms? I can´t make it work… it replies pushing the button but doesn´t when i try to get status or activate the reply

Leave a Reply to Ahmed Cancel reply

Your email address will not be published. Required fields are marked *