Tutorial: How to use SIM800L DTMF to Control Anything | Arduino
In here we will learn how we can use SIM800L DTMF to control anything from simple turning On or turning Off of LED to big projects like home automation.
DTMF stands for Dual Tone Multi Frequency or more commonly known as Touch Tone. You will most likely to experience the use of DTMF when you call the customer support hotline of big companies which requires you to press a set of different numbers. I am thinking that this is to categories customer concerns and direct you to a specific person who is knowledgeable about your concern.
With DTMF, each key you press on your phones generates 2 tones of specific frequency. The tones is generated in pairs of high and low frequency groups.
Key | Low Frequency | High Frequency |
1 | 697 | 1209 |
2 | 697 | 1336 |
3 | 697 | 1477 |
4 | 770 | 1209 |
5 | 770 | 1336 |
6 | 770 | 1477 |
7 | 852 | 1209 |
8 | 852 | 1336 |
9 | 852 | 1477 |
0 | 941 | 1336 |
* | 941 | 1209 |
# | 941 | 1477 |
For example when you press #1 key, you are sending a 697 Hz tone and a 1209 Hz tone. This is in order to separate DTMF from human voice.
Circuit Diagram:
Video Demonstration:
Source Code:
#include "SoftwareSerial.h"
# define SIM800L_Tx 7
# define SIM800L_Rx 6
# define RED_LED_PIN 5
# define GRN_LED_PIN 4
SoftwareSerial SIM800L(SIM800L_Tx, SIM800L_Rx);
char dtmf_cmd;
bool call_flag = false;
bool RED_LED_STATE = false;
bool GRN_LED_STATE = false;
void init_gsm();
void update_led();
void setup()
{
SIM800L.begin(9600);
Serial.begin(9600);
pinMode(RED_LED_PIN, OUTPUT);
pinMode(GRN_LED_PIN, OUTPUT);
digitalWrite(RED_LED_PIN, RED_LED_STATE);
digitalWrite(GRN_LED_PIN, GRN_LED_STATE);
init_gsm();
}
void loop()
{
String gsm_data;
int x = -1;
// Store serial data from SIM800L
while (SIM800L.available())
{
char c = SIM800L.read();
gsm_data += c;
delay(10);
}
// Check if DTMF is receive from SIM800L
if (call_flag)
{
// Call is answered and ongoing
// Wait for DTMF command
// Then store the dtmf command
x = gsm_data.indexOf("DTMF");
if (x > -1)
{
dtmf_cmd = gsm_data[x + 6];
Serial.println(dtmf_cmd);
update_led();
}
x = gsm_data.indexOf("NO CARRIER");
if (x > -1)
{
// Terminate ongoing call when call is disconnected
SIM800L.println("ATH");
call_flag = false;
}
} else {
// SIM800L is in idle, just waiting for calls
// answer incoming call when ringing
// then process it
x = gsm_data.indexOf("RING");
if (x > -1)
{
delay(5000);
SIM800L.println("ATA");
call_flag = true;
}
}
}
void init_gsm()
{
boolean gsm_Ready = 1;
Serial.println("initializing GSM module");
while (gsm_Ready > 0)
{
SIM800L.println("AT");
Serial.println("AT");
while (SIM800L.available())
{
if (SIM800L.find("OK") > 0)
gsm_Ready = 0;
}
delay(2000);
}
Serial.println("AT READY");
boolean ntw_Ready = 1;
Serial.println("finding network");
while (ntw_Ready > 0)
{
SIM800L.println("AT+CPIN?");
Serial.println("AT+CPIN?");
while (SIM800L.available())
{
if (SIM800L.find("+CPIN: READY") > 0)
ntw_Ready = 0;
}
delay(2000);
}
Serial.println("NTW READY");
boolean DTMF_Ready = 1;
Serial.println("turning DTMF ON");
while (DTMF_Ready > 0)
{
SIM800L.println("AT+DDET=1");
Serial.println("AT+DDET=1");
while (SIM800L.available())
{
if (SIM800L.find("OK") > 0)
DTMF_Ready = 0;
}
delay(2000);
}
Serial.println("DTMF READY");
}
void update_led()
{
if (dtmf_cmd == '1') {
if (RED_LED_STATE) {
RED_LED_STATE = false;
digitalWrite(RED_LED_PIN, RED_LED_STATE); //relay 1 on
Serial.println("RELAY 1 OFF");
} else {
RED_LED_STATE = true;
digitalWrite(RED_LED_PIN, RED_LED_STATE); //relay 1 on
Serial.println("RELAY 1 ON");
}
}
if (dtmf_cmd == '2') {
if (GRN_LED_STATE) {
GRN_LED_STATE = false;
digitalWrite(GRN_LED_PIN, GRN_LED_STATE); //relay 2 on
Serial.println("RELAY 2 OFF");
} else {
GRN_LED_STATE = true;
digitalWrite(GRN_LED_PIN, GRN_LED_STATE); //relay 2 on
Serial.println("RELAY 2 ON");
}
}
}
This source code is for Ajit Zagade as requested:
#include "SoftwareSerial.h"
# define SIM800L_Tx 7
# define SIM800L_Rx 6
# define RED_LED_PIN 5
# define GRN_LED_PIN 4
SoftwareSerial SIM800L(SIM800L_Tx, SIM800L_Rx);
String number = "+ZZxxxxxxxxxx"; // Replaced the following:
// ZZ - your country code
// xx - 10-digit mobile number
char dtmf_cmd;
bool call_flag = false;
bool RED_LED_STATE = false;
bool GRN_LED_STATE = false;
void init_gsm();
void update_led();
void setup()
{
SIM800L.begin(9600);
Serial.begin(9600);
pinMode(RED_LED_PIN, OUTPUT);
pinMode(GRN_LED_PIN, OUTPUT);
digitalWrite(RED_LED_PIN, RED_LED_STATE);
digitalWrite(GRN_LED_PIN, GRN_LED_STATE);
init_gsm();
}
void loop()
{
String gsm_data;
int x = -1;
// Store serial data from SIM800L
while (SIM800L.available())
{
char c = SIM800L.read();
gsm_data += c;
delay(10);
}
// Check if DTMF is receive from SIM800L
if (call_flag)
{
// Call is answered and ongoing
// Wait for DTMF command
// Then store the dtmf command
x = gsm_data.indexOf("DTMF");
if (x > -1)
{
dtmf_cmd = gsm_data[x + 6];
Serial.println(dtmf_cmd);
update_led();
}
x = gsm_data.indexOf("NO CARRIER");
if (x > -1)
{
// Terminate ongoing call when call is disconnected
SIM800L.println("ATH");
call_flag = false;
}
} else {
// SIM800L is in idle, just waiting for calls
// answer incoming call when ringing
// then process it
x = gsm_data.indexOf("RING");
if (x > -1)
{
delay(5000);
SIM800L.println("ATA");
call_flag = true;
}
}
}
void init_gsm()
{
boolean gsm_Ready = 1;
Serial.println("initializing GSM module");
while (gsm_Ready > 0)
{
SIM800L.println("AT");
Serial.println("AT");
while (SIM800L.available())
{
if (SIM800L.find("OK") > 0)
gsm_Ready = 0;
}
delay(2000);
}
Serial.println("AT READY");
boolean ntw_Ready = 1;
Serial.println("finding network");
while (ntw_Ready > 0)
{
SIM800L.println("AT+CPIN?");
Serial.println("AT+CPIN?");
while (SIM800L.available())
{
if (SIM800L.find("+CPIN: READY") > 0)
ntw_Ready = 0;
}
delay(2000);
}
Serial.println("NTW READY");
boolean DTMF_Ready = 1;
Serial.println("turning DTMF ON");
while (DTMF_Ready > 0)
{
SIM800L.println("AT+DDET=1");
Serial.println("AT+DDET=1");
while (SIM800L.available())
{
if (SIM800L.find("OK") > 0)
DTMF_Ready = 0;
}
delay(2000);
}
Serial.println("DTMF READY");
}
void update_led()
{
if (dtmf_cmd == '1') {
if (RED_LED_STATE) {
RED_LED_STATE = false;
digitalWrite(RED_LED_PIN, RED_LED_STATE); //relay 1 on
Serial.println("RELAY 1 OFF");
SendSMS("RELAY 1 OFF");
} else {
RED_LED_STATE = true;
digitalWrite(RED_LED_PIN, RED_LED_STATE); //relay 1 on
Serial.println("RELAY 1 ON");
SendSMS("RELAY 1 ON");
}
}
if (dtmf_cmd == '2') {
if (GRN_LED_STATE) {
GRN_LED_STATE = false;
digitalWrite(GRN_LED_PIN, GRN_LED_STATE); //relay 2 on
Serial.println("RELAY 2 OFF");
SendSMS("RELAY 2 OFF");
} else {
GRN_LED_STATE = true;
digitalWrite(GRN_LED_PIN, GRN_LED_STATE); //relay 2 on
Serial.println("RELAY 2 ON");
SendSMS("RELAY 2 ON");
}
}
}
void SendSMS(String SMS)
{
//Serial.println ("Sending Message");
SIM800L.println("AT+CMGF=1"); //Sets the GSM Module in Text Mode
delay(1000);
//Serial.println ("Set SMS Number");
SIM800L.println("AT+CMGS="" + number + ""r"); //Mobile phone number to send message
delay(1000);
SIM800L.println(SMS);
delay(100);
SIM800L.println((char)26);// ASCII code of CTRL+Z
delay(1000);
}
I hope you and enjoy this article. If you have any question, please do not hesitate to write it in the comment box.
Thank you and have a good day.
Happy tinkering.
sir please i want you to help me with my project on vehicle speed monitoring system. the device has a GSM to monitor the speed of the motor. plsease the following are the working conditions.
{ 1. a sensor monitor the speed speeed of the motor.
2. microcontroller counts the number of revolution per second
3. microcontroller performs calculations eg. 10 revelution = 20km/hr
4. set the speed limits to 100km/hr
5. if speed exceeds limits, send sms to phone or user
6. use can send sms to turn off the motor }
counting on your cooperation. thank you
To give you an idea, you need a hall sensor to number of revolution per second. By this you can solve the steps #1 to #4
For #5:
if (speed == 100kph)
sendSMS()
For this, you can use the code in this tutorial when the button switch is press.
For #6,
Parse the SMS
if sms == turn off
turnOffEngine
I hope this could help you and if you still have question, just write it here.
Hi sir .. l need help that . When I call the gsm it should automatically register my number in order to send messages.
Hi, look here: https://techtotinker.blogspot.com/2020/08/tutorial-how-to-use-sim800l-gsm-module.html
In this article, I show how to parse the sender mobile number.
Hello. Can I check this work you do as an SMS?
Sir,
I build a project as like same you made.
But It's not working.
Can you help me for this project?
Hi sir help me answer only default number
If its not working, then may I know what is not working with you?
@GK, what do you mean? Can you try again?
hi sir .
Call receive only my phone number
please add command sir
Hola, buen proyecto….como se puede adaptar una contraseña y poder manipular el módulo desde cualquier móvil a través de comandos dtmf?..Muchas gracias.
Sir! how about if I use water sensors. When the sensor works the gsm module should send a text to the default number that the sensor sensed water
how to make it as respond only my call while othe's unknonwn call be rejected. plz suggest
Hi sir! What diode did u used 1N4148 1N4007 1N5819 1N5399 1N5408 1N5822 FR107 FR207 as rectifier diode?
Can I get the values of the resistors you used? Thank youuuu!
Hi @nica, I believe I have answered your question in the Youtube video comments section. Cheers.
HI SIR THANK YOU FOR DEATILED INFORMATION ABOUT PROJECT,
I USE YOUR CODE FOR SAME PROJECT
BUT WHEN I CALL TO SIM(INSERTED IN SIM8OOL MODULE)
IT RING TWO TIMES, AFTER WHEN I PRESS 1 IT DOESN'T RESPONDED.
CAN YOU PLEASE HELP IN THIS ISSUE??
THANK IN ADVANCE
@shindevicky, you might like to check this AT commands reference: https://cdn-shop.adafruit.com/product-files/2637/SIM800+Series_AT+Command+Manual_V1.09.pdf check page 333.
Check 16.2.1 AT+DDET DTMF Detection Control and set reportMode to 1 (or enable).
Please kindly let me know your progress.
You did a great job here, my compliments. It works perfectly. I spent a lot of time to find something for relay control. Thanks for sharing and good luck with your projects.
That's great, glad that it helps you and thank you for the kind words. Cheers.
This comment has been removed by the author.
Hi sir,
I want to do a project like this. But I want it like, when I call the sim in a GSM sim800l module, It answers me as "press 1 to light ON", "Press 2 to light OFF". Is it possible make project like this by without using DTMF decoder. For that replies what will I want to do sir?
Plz help me sir.
This comment has been removed by the author.
Hi sir,
thank you for your reply.
solved the issue, everything is now OK.
can you please edit code for white list or registred numbers,
means arduino only takes action when calling from pre registered number.
Thank You,
shindevishal88@gmail.com
Hi @Kevin Karthick, for that you won't need DTMF. You maybe do it as follows:
1. Call the SIM800 sim number.
2. Get the caller number then terminate the call
3. Reply (SMS) using the caller number with the message you want.
4. Respond according to the command receive (via SMS)
So what will happen is when you call the sim number it will sms you the list of commands possible. And it should also be able to follow your command through SMS.
I hope this gives you idea.
Cheers, George Bantique | tech.to.tinker@gmail.com
@shindevicky,
It's should be like this:
if sender number == whitelist number
do the stuff you want
You might refer to this blog on parsing the sender number: https://techtotinker.blogspot.com/2020/08/tutorial-how-to-use-sim800l-gsm-module.html
thank you sir
@shindevicky,
You're most welcome 🙂
greet , I want to register the access control (number + data and time) and mead allow list for the number to control and all anther number drub it .
What a great person George Bantique you are….so helpful to all mates seeking your help!!!
Thanks mate. I am glad that you found it helpful.
Hello sir,
I have a project which is based on sim800l. There are 4 relays on the board. I am now able to control all of them via sms and call.
But, my problems are;
1)There is no eeprom trait in the software. I would like to remember the state of my relays. How can i integrate this to my code.
2)I want to use gprs(2g) to build an IOT system.
3)The most important one is that; when the communication signal is down, the system reset itself and dont come back the old state. How can i save my relay's states after reset of software.
Thanks in advance…
hi ı want to send message to calling number but ı cant do it. ı use at+clip command. my problem is sending message to number which calls
This code is not working on wemos d1 mini board. When I make call to gsm module d1 mini keeps restarting. Any solution or suggestion?
Thanks for your great tutorial.