Send Receive SMS & Call with SIM800L GSM Module & Arduino

Whether you want to know what’s happening miles away from your home or activate the sprinkler system in your garden with just a missed call; Then the SIM800L GSM/GPRS module can serve as a solid launching point for you to get started with IoT!

The SIM800L GSM/GPRS module is a miniature GSM modem that can be integrated into a large number of IoT projects. You can use this module to accomplish almost anything that a normal cell phone can do such as sending SMS messages, making phone calls, connecting to the Internet via GPRS, and much more.

To top it all off, the module supports quad-band GSM/GPRS networks, which means it works pretty much anywhere in the world.

Hardware Overview

At the heart of the module is a SIM800L GSM cellular chip from Simcom.

The chip’s operating voltage ranges from 3.4V to 4.4V, making it an ideal candidate for direct LiPo battery supply. This makes it a good option for embedding in projects that are short of space.

SIM800L Module Hardware Overview - LED Indicator, u.fl Connector, Helical Antenna

All the necessary data pins of the SIM800L GSM chip are broken out to a 0.1″ pitch headers, including the pins required for communication with the microcontroller over the UART. The module supports baud rate from 1200bps to 115200bps with auto-baud detection.

An external antenna is needed for the module to be connected to the network. The module usually comes with a helical antenna that can be soldered onto the module. The board also features a U.FL connector in case you want to keep the antenna away from the board.

SIM800L Module Hardware Overview - Micro SIM Socket, Direction to Insert SIM

There’s a SIM socket on the back! Any 2G Micro SIM card will work perfectly. The correct direction to insert the SIM card is usually engraved on the surface of the SIM socket.

Features

This module measures only 1 inch2, but packs a surprising amount of features into its tiny frame. Some of them are listed below:

  • Supports Quad-band: GSM850, EGSM900, DCS1800 and PCS1900
  • Connect onto any global GSM network with any 2G SIM
  • Make and receive voice calls using an external 8Ω speaker & electret microphone
  • Send and receive SMS messages
  • Send and receive GPRS data (TCP/IP, HTTP, etc.)
  • Scan and receive FM radio broadcasts
  • Transmit Power:
    • Class 4 (2W) for GSM850
    • Class 1 (1W) for DCS1800
  • Serial-based AT Command Set
  • FL connectors for cell antennae
  • Accepts Micro SIM Card

LED Status Indicators

On the top right of the SIM800L module is an LED that indicates the status of your cellular network. It blinks at different rates depending on which state it is in:

Netlight LED Blinking Finding Network Connection

Blink every 1s

The module is running but the connection to the cellular network has not yet been made.

Netlight LED Blinking Active GPRS Connection

Blink every 2s

The GPRS data connection you requested is active.

Netlight LED Blinking Network Connection Established

Blink every 3s

The module has made contact with the cellular network and can send/receive voice and SMS.

Selecting Antenna

An antenna is required to use the module for any type of voice or data communication. So selecting an antenna can be a crucial thing. There are two ways to add an antenna to the SIM800L module.

The first is a helical antenna that usually comes with the module and can be soldered directly onto the PCB. This antenna is very useful for projects that need to save space. But be aware that it may struggle to get connectivity, especially if your project is indoors.

SIM800L GSM Module with Helical Antenna

Another way is a 3dBi GSM antenna with a U.FL to SMA adapter that can be found online for less than $3. You can snap-fit this antenna into the small u.fl connector located on the top-left corner of the module. This type of antenna has better performance and even allows your module to be placed inside a metal box, as long as the antenna is outside.

SIM800L GSM Module with 2dBi Duck Antenna

Power Consumption

One of the most important parts of getting the SIM800L module working is to supply enough power to it.

Depending on what state it’s in, the SIM800L can be a relatively power-hungry device. The module’s maximum current draw is about 2A during a transmission burst. It usually doesn’t draw that much, but can draw around 216mA during phone calls and 80mA during network transmission. The following chart summarizes what you can expect:

ModesFrequencyCurrent Consumption
Power down60 uA
Sleep mode1 mA
Stand by18 mA
CallGSM850199 mA
EGSM900216 mA
DCS1800146 mA
PCS1900131 mA
GPRS453 mA
Transmission burst2 A

Selecting Power Supply

Since the SIM800L module does not come with an onboard voltage regulator, an external power supply adjusted to a voltage between 3.4V to 4.4V (ideally 4.1V) is required. Despite this the power supply must also be capable of supplying 2A surge current, otherwise the module will keep shutting down.

Here are some options you can consider to supply power to your GSM module correctly.

Li-Po Battery

One of the nice things about Li-Po batteries is that their voltage is generally in the range of 3.7V – 4.2V which is perfect for a SIM800L module. Any 1200mAh or larger Li-Po battery may be perfect as it can provide the correct voltage range even during 2 Amp spikes.

1200mAh LiPo Battery

DC-DC Buck Converter

Any 2A-rated DC-DC buck converter like the LM2596 will work. These are much more efficient than linear voltage regulators such as the LM317 or LM338.

LM2596 DC-DC Buck Converter

SIM800L GSM Module Pinout

The SIM800L module has a total of 12 pins. The pinout is as follows:

SIM800L GSM Module Pinout

NET is a pin where you can solder the helical antenna provided with the module.

VCC supplies power to the module. It can be anywhere from 3.4V to 4.4 volts. Remember that connecting this to the 5V will probably damage your module! It doesn’t even run on 3.3 V! So try using a 3.7V 2A rated external power source like a Li-Po battery or a DC-DC buck converter.

RST (Reset) is a hard reset pin. If you got the module in an absolutely bad space, pull this pin LOW for 100ms to perform a hard reset.

RxD (Receiver) pin is used to send commands to the module. This pin is auto-baud so the baud rate at which you send the “AT” command after reset is the baud rate used.

TxD (Transmitter) pin transmits data from the module to the microcontroller.

GND is the Ground Pin.

RING pin acts as a Ring Indicator. This is basically the ‘interrupt-out’ pin from the module. It is HIGH by default and pulses LOW for 120ms when a call is received. It can also be configured to pulse when SMS is received.

DTR pin activates/deactivates the sleep mode. Pulling it HIGH will put the module into sleep mode, disabling serial communication. Pulling it LOW will wake up the module.

MIC± is a differential microphone input. A microphone can be connected directly to these two pins.

SPK± is a differential speaker interface. A speaker can be connected directly to these two pins.

Wiring a SIM800L GSM Module to an Arduino

Now that we know everything about the module, we can start connecting it to our Arduino!

Begin by connecting the antenna to the module and inserting a micro SIM card into the socket.

Next, connect the Tx pin on the module to digital pin #3 on the Arduino as we will be using software serial to communicate with the module.

We cannot connect the module’s Rx pin directly to the Arduino’s digital pin because Arduino UNO uses 5V logic level while SIM800L module uses 3.3V logic level. Simply put, the Rx pin of the SIM800L module is not 5V tolerant. Therefore the Tx signal coming from the Arduino must be stepped down to 3.3V.

There are many ways to do this but the easiest way is to use a simple resistor divider. A 10K resistor between SIM800L’s Rx and Arduino’s D2, and 20K between SIM800L’s Rx and GND will work fine.

Now we are left with the pins that are used to supply power to the module. Since you have several options for powering the module, we have provided two example schematics. The first uses a 1200mAh Li-Po battery.

Arduino Wiring Fritzing Connections with SIM800L GSM GPRS Module & 3.7V LiPo Battery

And the second uses an LM2596 DC-DC buck converter.

Arduino Wiring Fritzing Connections with SIM800L GSM GPRS Module & LM2596

Warnings:

  • You must be very careful not to disconnect GND before VCC and always connect GND before VCC. Otherwise the module may use the low voltage serial pins as ground causing damage to the module.
  • And make sure your circuit and Arduino share a common ground.

Arduino Code – Testing AT Commands

To send AT commands and communicate with the SIM800L module, we will be using the Serial Monitor. The sketch below will enable the Arduino to communicate with the SIM800L module over the serial monitor. Before we proceed with the detailed analysis of the code, connect your Arduino to PC, compile the below code and upload it to Arduino.

Once you open the Serial Monitor, make sure the ‘Both NL and CR‘ option is selected!

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2

void setup()
{
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM800L
  mySerial.begin(9600);

  Serial.println("Initializing...");
  delay(1000);

  mySerial.println("AT"); //Once the handshake test is successful, it will back to OK
  updateSerial();
  mySerial.println("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
  updateSerial();
  mySerial.println("AT+CCID"); //Read SIM information to confirm whether the SIM is plugged
  updateSerial();
  mySerial.println("AT+CREG?"); //Check whether it has registered in the network
  updateSerial();
}

void loop()
{
  updateSerial();
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

Once you have uploaded the sketch, open the serial monitor at baud rate 9600. You should see the output below on the serial monitor.

SIM800L GSM Module Basic AT Commands on Arduino

Code Explanation:

The sketch begins by including the SoftwareSerial.h library and initializing the SoftwareSerial object with the Arduino pins to which the Tx and Rx of the SIM800L module are connected.

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2

In the setup function, we initiate a serial communication link between the Arduino, the Arduino IDE and the SIM800L module at a baud rate of 9600.

//Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM800L
  mySerial.begin(9600);

Now that we have established a basic connection, we will try to communicate with the SIM800L module by sending AT commands.

AT – This is the most basic AT command. It also initializes the Auto-bauder. If all is well, it sends the OK message, telling you that it is understanding you correctly. You can then send some commands to query the module and get information about it.

AT+CSQ – It checks ‘Signal Strength’. The first number in the output response is the signal strength in dB. It should be more than about 5. Higher is better. Note that this signal strength depends on your antenna and location!

AT+CCID – It checks whether the SIM card is valid or not and sends the SIM card number.

AT+CREG? – It checks whether you are registered to the network or not. The second number in the output response should be 1 or 5. 1 indicates that you are registered to a home network and 5 indicates a roaming network. Any number other than these two indicates that you are not registered to any network.

  mySerial.println("AT"); //Once the handshake test is successful, it will back to OK
  updateSerial();
  mySerial.println("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
  updateSerial();
  mySerial.println("AT+CCID"); //Read SIM information to confirm whether the SIM is plugged
  updateSerial();
  mySerial.println("AT+CREG?"); //Check whether it has registered in the network
  updateSerial();

In the loop, we call a custom function called updateSerial() which continuously waits for any input from the serial monitor and sends it to the SIM800L module via the D2 pin (the module’s RX). It also continuously reads the D3 pin (the module’s TX) to see if there is a response from the SIM800L module.

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

Try Sending Different AT Commands

You are now free to send commands such as the following through the Serial Monitor which give more information about network connection and battery status:

ATI – Returns the module name and revision.

AT+COPS? – Checks which network you are connected to, in our case Vodafone.

AT+COPS=? – Returns the list of operators present in the network.

AT+CBC – Returns Li-Po battery status. The second number is the battery level (in our case it is 93%) and the third number is the actual voltage in mV (in our case 3.877 V)

SIM800L GSM Module Network Connection AT Commands on Arduino

Arduino Code – Sending an SMS

Let’s move on to the interesting stuff. Let’s program our Arduino to send an SMS.

Before trying out the sketch, you’ll need to enter the phone number to which you want to send an SMS. Look for the highlighted string ZZxxxxxxxxxx and replace ZZ with the county code and xxxxxxxxxx with the 10 digit phone number.

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2

void setup()
{
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM800L
  mySerial.begin(9600);

  Serial.println("Initializing..."); 
  delay(1000);

  mySerial.println("AT"); //Once the handshake test is successful, it will back to OK
  updateSerial();

  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
 mySerial.println("AT+CMGS=\"+ZZxxxxxxxxxx\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("Last Minute Engineers | lastminuteengineers.com"); //text content
  updateSerial();
  mySerial.write(26);
}

void loop()
{
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

The screenshot below shows the SMS sent from the SIM800L GSM module.

SIM800L GSM Module AT Commands for Sending SMS on Arduino
Sending SMS through SIM800L GSM Module

Code Explanation:

The sketch is almost the same as the first sketch except for the code snippet below. Once the connection is established, we send the following AT commands:

AT+CMGF=1 – Selects the SMS message format as text. The default format is Protocol Data Unit (PDU).

AT+CMGS=+ZZxxxxxxxxxx – Sends SMS to the specified phone number. After this AT command any text message followed by ‘Ctrl+z’ character is treated as SMS. ‘Ctrl+z’ is actually a 26th non-printing character that is described as ‘substitute’ in the ASCII table. Therefore, we need to send 26DEC (1AHEX) at the end of the command.

  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CMGS=\"+ZZxxxxxxxxxx\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("Last Minute Engineers | lastminuteengineers.com"); //text content
  updateSerial();
  mySerial.write(26);

The loop is kept empty because we want to send SMS only once. If you want to send SMS one more time, just press the RESET key on your Arduino.

Arduino Code – Reading an SMS

Now let’s program our Arduino to read incoming messages. This sketch can be very useful when you need to perform an action like turn ON/OFF lights, enable fan, enable sprinkler system when you receive a specific SMS. You got the idea!

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2

void setup()
{
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM800L
  mySerial.begin(9600);

  Serial.println("Initializing..."); 
  delay(1000);

  mySerial.println("AT"); //Once the handshake test is successful, it will back to OK
  updateSerial();
  
  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CNMI=1,2,0,0,0"); // Decides how newly arrived SMS messages should be handled
  updateSerial();
}

void loop()
{
  updateSerial();
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

Once you send SMS to the SIM800L GSM module, you will see the following output on the serial monitor.

Reading SMS through SIM800L GSM Module
SIM800L GSM Module AT Commands for Reading SMS on Arduino

As you can see the output response starts with +CMT: All the fields in the response are comma separated where the first field is the phone number and the second field is the name of the person sending the SMS. The third field is a timestamp while the fourth field is the actual message.

Code Explanation:

The sketch is almost the same as the first sketch except for the code snippet below. Once the connection is established, we send the following AT commands:

AT+CMGF=1 – Selects the SMS message format as text. The default format is Protocol Data Unit (PDU)

AT+CNMI=1,2,0,0,0 – Specifies how incoming SMS messages should be handled. This way you can tell the SIM800L module to either forward incoming SMS messages directly to the PC, or save them to the message storage and then inform the PC about their locations in the message storage.

  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CNMI=1,2,0,0,0"); // Decides how newly arrived SMS messages should be handled
  updateSerial();

Note that this time we have not kept the loop function empty as we are polling incoming SMS messages.

Expanding Arduino SoftwareSerial Buffer Size

If your message is long enough like the one above, you’ll probably receive it with some missing characters. This is not because of a faulty code, but because the ‘Software Serial Receive Buffer’ is filling up completely, discarding the remaining characters.

The simplest solution is to increase the size of the SoftwareSerial buffer to 256 bytes from the default size of 64 bytes.

On a Windows PC, go to C:\Program Files (x86) -> Arduino -> hardware -> Arduino -> avr -> libraries -> SoftwareSerial (-> src for newer version of Arduino IDE). Open SoftwareSerial.h and change this line:

// RX buffer size
#define _SS_MAX_RX_BUFF 64

to

// RX buffer size
#define _SS_MAX_RX_BUFF 256

Save the file and try the sketch again.

Expanding Arduino SoftwareSerial Buffer Size
Expanding Arduino SoftwareSerial Buffer Size

Arduino Code – Making a Call

Now let’s program our Arduino to make a call. This sketch can be very useful when you want your Arduino to make a SOS/distress call in case of an emergency like the temperature is exceeded or someone breaks into your house. You got the idea!

Before trying out the sketch, you’ll need to enter the phone number you want to call. Look for the highlighted string ZZxxxxxxxxxx and replace ZZ with the county code and xxxxxxxxxx with the 10 digit phone number.

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2

void setup()
{
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM800L
  mySerial.begin(9600);

  Serial.println("Initializing..."); 
  delay(1000);

  mySerial.println("AT"); //Once the handshake test is successful, i t will back to OK
  updateSerial();
  
 mySerial.println("ATD+ +ZZxxxxxxxxxx;"); //  change ZZ with country code and xxxxxxxxxxx with phone number to dial
  updateSerial();
  delay(20000); // wait for 20 seconds...
  mySerial.println("ATH"); //hang up
  updateSerial();
}

void loop()
{
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

The following screenshot shows a call made from the SIM800L GSM module.

SIM800L GSM Module AT Commands for Making Call on Arduino
Calling through SIM800L GSM Module

Code Explanation:

The following AT commands are used to make a call:

ATD+ +ZZxxxxxxxxxx; – Dials a specified number. Don’t forget the semicolon ; at the end of the command.

ATH – Hangs up the call.

  mySerial.println("ATD+ +ZZxxxxxxxxxx;"); //  change ZZ with country code and xxxxxxxxxxx with phone number to dial
  updateSerial();
  delay(20000); // wait for 20 seconds...
  mySerial.println("ATH"); //hang up
  updateSerial();

Arduino Code – Receiving a Call

No special code is required to receive calls; You just have to keep listening to the SIM800L module. You may find this sketch very useful when you need to perform an action when a call is received from a specific phone number.

#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2

void setup()
{
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  
  //Begin serial communication with Arduino and SIM800L
  mySerial.begin(9600);

  Serial.println("Initializing..."); 
}

void loop()
{
  updateSerial();
}

void updateSerial()
{
  delay(500);
  while (Serial.available()) 
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available()) 
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

The following output on the serial monitor shows the calls received by the SIM800L GSM module.

Receiving Call on SIM800L GSM Module
SIM800L GSM Module AT Commands for Receiving Call on Arduino

As you can see incoming calls are usually represented by ‘RING’ on the serial monitor, followed by the phone number and caller ID. The following AT commands can be used to accept or hang up the call:

ATA – Accepts incoming call.

ATH – Hangs up the call. On hanging up the incoming call, we get NO CARRIER on the serial monitor indicating that the call could not be connected.