Hot to Answer a specific SMS using Arduino?

Hello mates,

I am developing a Energy Meter with communication by SMS.
I got to send the message with the variable that I want to consult. However, I need to implement a conditional function that when I send from my mobile phone a specific word such as "consult", the code answer me with a SMS with the variables bill and consumption.

Does anyone know how can I implement this on this code??

I have developed the following code so far:

#include <SoftwareSerial.h>

 
//SIM800 TX is connected to Arduino D8
#define SIM800_TX_PIN 8
 
//SIM800 RX is connected to Arduino D7
#define SIM800_RX_PIN 7
 
//Create software serial object to communicate with SIM800
SoftwareSerial serialSIM800(SIM800_TX_PIN,SIM800_RX_PIN);
 
void setup() {
int bill= 415;
int consumption= 876;
  //Begin serial comunication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);
  while(!Serial);
   
  //Being serial communication witj Arduino and SIM800
  serialSIM800.begin(9600);
  delay(1000);



String textSms; 
  Serial.println("Setup Complete!");
  Serial.println("Sending SMS...");
   
  //Set SMS format to ASCII
  serialSIM800.println("AT+CMGF=1\r\n");
  delay(1000);

         
  //Send new SMS command and message number
  serialSIM800.println("AT+CMGS=\"+5531985644009\"\r\n");
  delay(1000);
   
  //Send SMS content
  serialSIM800.println("Bill: R$");
  serialSIM800.println(bill);
  serialSIM800.println("consumption: kwh");
  serialSIM800.println(consumption);
  delay(1000);
   
  //Send Ctrl+Z / ESC to denote SMS message is complete
  serialSIM800.println((char)26);
  delay(1000);
     
  Serial.println("SMS Sent!");}
void loop() {
  
}

Thanks very much.

How experienced are you with coding?

Have you looked at libraries to send and receive SMS? They will provide examples and a layer of abstraction to make your life easier.

You can of course study one of the library as well to see how they work. Good opportunity for leaning.

There are many options.

I suggest you look at an example, try to build a code that listens for an SMS to arrive, verify the text received and turn on a LED for example if it's the right word. Post here and we will help.

HI J-M-L,
Thanks for your reply.

To be honest, I am not very experienced with coding.

I am learning in the last few days because I need to develop a project to get my graduation in Electrical Engineering.

Anyway...

I did what you suggested about the code to turn on a LED.

I used an example to do it which exists in the library SIM800L.

The code I used was the following:

#include <Sim800l.h>
#include <SoftwareSerial.h> //is necesary for the library!! 
Sim800l Sim800l;  //to declare the library



String textSms,numberSms;
uint8_t index1;
uint8_t LED2=13; // use what you need 
bool error;



void setup(){
 
pinMode(LED2,OUTPUT); 
digitalWrite(LED2,HIGH);

    Serial.begin(9600); // only for debug the results . 
    Sim800l.begin(); // initializate the library. 
    Sim800l.reset();
    //don't forget to catch the return of the function delAllSms! 
    error=Sim800l.delAllSms(); //clean memory of sms;
    
}

void loop(){
    textSms=Sim800l.readSms(1); //read the first sms
    
             {
                
                numberSms=Sim800l.getNumberSms(1);  // Here you have the number
                //for debugin
                Serial.println(numberSms); 
                textSms.toUpperCase();  // set all char to mayus ;)

                if (textSms.indexOf("TURNON")!=-1){
                    Serial.println("LED TURN ON");
                    digitalWrite(LED2,1);
                }
                else if (textSms.indexOf("TURNOFF")!=-1){
                    Serial.println("LED TURN OFF");
                    digitalWrite(LED2,0);

                }
                else{
                    Serial.println("Not Compatible ...sorry.. :D");
                }


            Sim800l.delAllSms(); //do only if the message is not empty,in other case is not necesary
             //delete all sms..so when receive a new sms always will be in first position
            } 



        }
    }

However, I am not getting to receive any message from my mobile phone. I used another similar codes to send a message and I got.

I dont know why, but the issue is that I am not receiving any message.

Is SIM800L matching your hardware?
What component do you really have ?
How is this wired?

Hi J-M-L.

Yes. I have the GSM Module SIM800L. Follow the image attached.
About the code to turn on the LED it is wired as below:

SIM800L >>>>>>>>>>>> ARDUINO

TX PIN 10
RX PIN 11

About the first code that I posted it is wired as below, because the library is different

SIM800L >>>>>>>>>>>> ARDUINO

TX PIN 7
RX PIN 8

download.jpg

which library do you use? this one?

doing thisSim800l Sim800l;  //to declare the library is not a best practice. You declare an instance of the class Sim800l which has the same name as the class. that's Highly confusing, don't you think? you should call that GSMModule for example.

How do you power your unit? I don't think it's 5V compliant. what about the pins?

From the library I linked above, this is their wiring:

Yes.
It is that library.
But its weird because with the example to send SMS of the same library I get send the SMS.

I am powering my module with 4.3V.

When I started to work with this module I was supplying with the 5V and it was not working.
But now, at least to send SMS I am getting.

Can you disconnect your unit, send an SMS to the unit SIM card number, then ensure the wiring is correct and upload and run this code.

What do you get?

/*
      PINOUT:
          _____________________________
         |  ARDUINO UNO >>>   SIM800L  |
          -----------------------------
              GND      -->   GND
          RX  10       -->   TX
          TX  11       -->   RX
       RESET   2       -->   RST

     POWER SOURCE 4.2V --> VCC
*/


#include <Sim800l.h>
#include <SoftwareSerial.h>

Sim800l Sim800l_GSM_Module;

void setup() {
  Serial.begin(9600);          // only for debug the results .
  Sim800l_GSM_Module.begin();  // initialize the library.
  Serial.println(Sim800l_GSM_Module.readSms(1));
}

void loop() {}

Hey J-M-L,

I got to receive and send SMS with the following code:

*/

#include <Sim800l.h>
#include <SoftwareSerial.h> //is necesary for the library!! 
Sim800l Sim800l;  //to declare the library



String textSms, numberSms;
uint8_t index;
uint8_t LED2 = 13; // use what you need
bool error;



void setup() {

  pinMode(LED2, OUTPUT);
  digitalWrite(LED2, HIGH);

  Serial.begin(9600); // only for debug the results .
  Sim800l.begin(); // initializate the library.
  //don't forget to catch the return of the function delAllSms!
  error = Sim800l.delAllSms(); //clean memory of sms;

}

void loop() {
  index = 1;
  textSms = Sim800l.readSms(index); //read the first sms
if (textSms.indexOf("OK")!=-1){
  if (textSms.length() > 5) {
    numberSms = Sim800l.getNumberSms(1); // Here you have the number
    //for debugin
    Serial.println(numberSms);
    Serial.println(textSms);
    textSms.toUpperCase();  // set all char to mayus ;)

    if (textSms.indexOf("FATURA") != -1) {
      Serial.println("VALOR DA CONTA");
      Sim800l.sendSms("+5531985644009", "the text go here");
      Sim800l.delAllSms();
      delay(2000);
    }
    else {
      Serial.println("Not Compatible ...sorry.. :D");
      Sim800l.delAllSms();
      delay(2000);

    }
  }
}

The unique problem I am having now is that when the Module receive the word "FATURA" ir answers me, but uninterruptedly. I receive milions of answers and I need to receive just one for each request.

I wrote the function to delete the message in SIM card that I sent from mobile. But it seems not working.

Can u help me?

First let me preface this by stating that I'm not using that library - I don't like it for many reasons I describe below, so take this as exploration ideas.


don't do thisSim800l Sim800l;  //to declare the libraryThe comment is wrong. you do not declare the library, you are creating an instance of the class Sim800l which you name Sim800l. As said before, this is regarded as bad programing practice because it's easy to confuse if you are talking to the class or instance later on (even if the compiler would understand most of the time).

-->**action:**suggest you change that name to Sim800l_GSM_Module for example and fix the commentSim800l Sim800l_GSM_Module;  //to declare an instance variable to use the methods in the librarySimilarly the comment for   Sim800l.begin(); // initializate the library.is not about the library but your instance of the class.

-->action: read about object oriented programing, class and object or instances. Change the instance variable name to something meaningful and modify your code accordingly.


What the readSms() function does in the class is to first send AT+CMGF=1 to the module to sets the GSM modem in SMS Text Mode (In Text Mode, SMS messages are represented as readable text) and checks if this leads to an Error (checks if the answer contain ER as in ERROR). If there was no error it sends AT+CMGR=1 (where 1 is your index variable) to read an SMS message at a certain location of the message storage area. It will return something like this

{

[color=blue]+CMGR: "REC READ","+5531985644009",,"16/09/16,10:12:05+32"
SMS text body goes here.

OK[/color]

}

without the red brackets which I added just for readability.

the code in the class then checks if the string "CMGR:" is part of the answer and if it is assumes it's good and returns the full buffer to you.

But if there is an error like there is no SMS at that location, then an error message is returned and this is implementation dependant, the AT spec does not tells you exactly what will be returned.

-->action: I would encourage you to test what answer you get if there is not SMS to see if your code does the right thing.


when you delete the SMS, I noticed that in the library, the code for deleting SMS is written like this:

SIM.print(F("at+cmgda=\"del all\"\n\r"));

some poor implementations of the AT specification do not like non caps letters. I'd be tempted to modify in the library into

SIM.print(F("AT+CMGDA=\"DEL ALL\"\n\r"));

Also at that stage the library assumes the chip is in SMS text mode. if it is in PDU mode what would need to be sent is "Delete all SMS" instead of "DEL ALL". if your unit is in the wrong mode for whatever reason then that command will fail. So either you modify the library to force SMS text mode (send AT+CMGF=1)

but that might not be your problem; Another challenge I see is timing. the delete SMS command takes 5 seconds to execute for 1 message and up to 25s to delete 50 messages; The library implements in its _readSerial code a statically configured timeout of 156 seconds waiting for some sign of life on the serial port and when there is, reads it in one go with the readString() method call. I hate this as it leads to disappointment and timeout() etc...

-->action: In your code you should check the value returned by delAllSms(). It will return true if deleting the SMS has worked or false otherwise.


Talking about timing management: I notice you ask to send an SMS right after detecting the word FATURA and with no delay you ask to delete the SMS. depending on how things work with the Software Serial port and your unit, you might want to give enough time for the SMS to be sent out before sending new commands on the Software Serial Port.

In general if you saturate the buffer of the Serial line, then you will loose infos. The receive buffer is small, only 64 bytes - and the SMS info you read is larger. so better read SMS quickly when they arrive...

-->action: be mindful of timing. Don't create delays() just for the sake of it.


Last but not least - and I know it's not directly your choice because the library drives you there, but don't use Strings with a capital S ([b]String textSms, numberSms;[/b]) because on processor with very limited HEAP size and no dynamic memory management, you are fragmenting your Heap which might lead to situation where memory is no longer available after a while. if you plan to have this code running without reset for a long time, then it's a best practice to get rid of all the Strings.

-->action: rewrite the Sim800l library without using Strings at all. rewrite your code appropriately. You will learn a lot that way.


When I code I don't use that library. if you read the library you can see it's just about sending to the serial line AT commands and then reading what's coming back at you.

-->action: I would encourage you to read the great article about Serial Input Basics by Robin and use that directly into your code. this way you'll be 100% in control of what's going on.

You will find the version 1.10 of the AT command set here which has been updated on 2016-05-18. make sure your firmware is also recent on your unit obviously.

there is also a good read here

hope this helps.

Hi J-M-L...

I tried to do your sugestions but I did not get to achieve what I was trying.

So I decided to give up to use the SIM800L library and use just SoftSerial. I am getting to receive SMS from module and to delete the SMS that I send from my mobile. However, the unique issue I am facing is that when the software loads on the hardware, it starts to send sms to my mobile.
My conditional funcion is not working.

Do you know, how can I fix it?

I developed the following code:

#include <SoftwareSerial.h>

#define TX 8
#define RX 7
int fatura = 415;
int consumo = 876;
char message[180];
String textSms;
char inchar = 0;

SoftwareSerial serialSIM800(TX, RX);

void setup() {


  Serial.begin(9600);
  serialSIM800.begin(2400);
  while (!Serial);

  delay(1000);
  serialSIM800.println("AT+CMGF=1\r\n");
  delay(1000);
    

}

void loop ()
{

  serialSIM800.println("AT+CMGR=1");
  delay(2000);
  inchar = serialSIM800.read();

  if (serialSIM800.available() > 4) {


    if (inchar != ' ')
    {
      Serial.println(inchar);

      serialSIM800.println("AT+CMGS=\"+5531985644009\"\r\n");
      delay(1000);

      //Send SMS content
      serialSIM800.println("Fatura: R$");
      serialSIM800.println(fatura);
      serialSIM800.println("Consumo: kwh");
      serialSIM800.println(consumo);
      delay(1000);

      //Send Ctrl+Z / ESC to denote SMS message is complete
      serialSIM800.println((char)26);
      delay(1000);
      serialSIM800.println("AT+CMGD=1,4");

      Serial.println("SMS Sent!");
    }
  }
}

Good decision - this way you will be in full control and will learn a lot.


serialSIM800.println("AT+CMGF=1\r\n");when you do println() the LN at the end means \r\n so either you do print or you don't add the 2 chars at the end of the string. Here you are sending an empty command to the module right after sending the AT+CMGF=1 one.You should also comment for better explanation what it does.

// sets the GSM modem in SMS Text Mode (In Text Mode, SMS messages are represented as readable text)
serialSIM800.println("AT+CMGF=1");

Note that you don't try to read the answer so you don't know if that worked. A good practice would be to check the returned information and see if you have OK in the message.

Also note that because you don't read back, your serial incoming buffer from the module has something in it.


Your loop then starts always by asking if there is an SMS, waiting for 2s and reading (or trying to) from the module

  // read an SMS message at location 1 of the message storage area. 
  serialSIM800.println("AT+CMGR=1");
  delay(2000);
  inchar = serialSIM800.read();

(I added the comment). One issue is that you wait a bit, and then try to read. You don't know if you waited long enough for something to be there - or too long and plenty of data came back and because the buffer can hold only 64 chars, you might have been loosing some already. Remember you'll receive an answer like this:
{

[color=blue]+CMGR: "REC READ","+5531985644009",,"16/09/16,10:12:05+32"
SMS text body goes here.

OK[/color]

}

without the red brackets which I added just for readability. That is probably more than 64 chars and you might loose the beginning if you don't start reading at the right moment.

So lesson to learn: It's never a good idea to delay() serial communication. Be proactive, check if there is something waiting and if so take action.

Then you wait until 4 chars are in the serial buffer, you don't read any, you just compare the character you had received previously and if it is not a space (why a space??) then you send an SMS.

As there is a huge likelyhood that this first character is not a space - remember you sent in the set up a command to go to SMS text mode and you never read the answer to that command. So you have probably in the buffer already a CR/LF and an "OK" and a CR/LF from that command.

Then you never delete the SMS received after sending yours so as I described before, the next time you go to the top of the loop you send again the read SMS message, you already have all the characters from the previous read that you did not do anything with in the buffer and you add to that again the reading of the SMS... So first char will likely not be a space, and you send again your SMS... And if by chance this is a space, the loop loops and in a blink of an eye (well 2s delay) you read the next char and send again your SMS...

So You need to empty the communication buffer you receive from the GSM, before issueing the next command. And then you need to decide what to check for in the buffer you receive to decide if it is time to send your SMS.

I would strongly advise you read Robin's excellent tutorial on how to deal with Serial input. See Serial Input Basics and write a function you will call after each command sent to the GSM module to read the answer (or timeout after a while).

J-M-L,

Could you please reply with the my code modified with the modification that you would do to solve it?

I am try to fix the code... But to be honest, as I am not very experienced with coding, some things I dont understand.

I am getting desperate with that.

Could you please reply with the my code modified with the modification that you would do to solve it?

Sorry, no that's not the way it works here... I'm happy to contribute a bit of my time to help improve or correct situation, but what you want is a full code from scratch...

I am getting desperate with that.

No one said learning will happen in one day. You are tackling an issue that takes time. You need to be clear in your mind that you'll have to work for months and years to understand programming, computer sciences, etc

if you don't have time to invest in building your own understanding of how to handle the Serial communication from the link above, then you need to consider going to a library again. that will hide/handle things for you.

Hi J-M-L.
I agree with u. However, I was not looking for a complete sketch. I asked just for the part with the correction about the conditional function.

But, Ok.

I followed your suggestion and tried to work with a code using library.
I got the following code which is receiving, sending and deleting the SMS.

I have just one doubt... maybe you can help me like you´re doing.
How can I send a variable instead a text?
I need to send a SMS with the value of the variable fatura. But, as I did I'm receiving a sms writen "i%".

Could u help me once more time?

I would like to thank you for you patience and availability to help.

#include <Sim800l.h>
#include <SoftwareSerial.h> //is necesary for the library!!
Sim800l Sim800l_GSM_Module; ; //to declare the library

String textsms, numbersms;
uint8_t index;
bool error;
int fatura = 1921;





void setup() {



  Serial.begin(9600); // only for debug the results .
  Sim800l_GSM_Module.begin(); // initializate the library.
  //don't forget to catch the return of the function delAllSms!
  error = Sim800l_GSM_Module.delAllSms(); //clean memory of sms;

}

void loop() {
  Sim800l_GSM_Module.delAllSms();
  index = 1;
  textsms = Sim800l_GSM_Module.readSms(index); //read the first sms
  if (textsms.indexOf("OK") != -1) {
    if (textsms.length() > 5) {
      numbersms = Sim800l_GSM_Module.getNumberSms(1); // Here you have the number
      //for debugin
      Serial.println(numbersms);
      Serial.println(textsms);
      textsms.toUpperCase();  // set all char to mayus ;)

      if (textsms.indexOf("FATURA") != -1) {
        Serial.println("VALOR DA CONTA");
        Sim800l_GSM_Module.sendSms("+5531985644009", fatura);
        


      }
      else {
        Serial.println("Not Compatible ...sorry.. :D");
        Sim800l_GSM_Module.delAllSms();


      }
      Sim800l_GSM_Module.delAllSms();
    }
  }

How can I send a variable instead a text?

You can't. You CAN send the contents of a variable AS TEXT.

        char mess[30];
        int variable = 39;
        sprintf(mess, "Variable = %d", variable);
        Sim800l_GSM_Module.sendSms("+5531985644009", mess);

Thanks very much, Paul.

It is working fine.

I have just a doubt.

If my variable is a parameter which changes constantly, for example, temperature.

Could I do something like this?

char mess[30];
        int temperature= AnalogRead(A0);
        sprintf(mess, "temperature= %d", temperature);
        Sim800l_GSM_Module.sendSms("+5531985644009", mess);

Yes of course - sprintf will overwrite the content of the mess variable every time you call it and set the bits the right way

Just make sure your mess buffer is long enough to accommodate the whole message with the largest value that will replace the %d

Hello.

I am just having a small problem when I request an answer from energy meter.

When I send from my mobile phone the word FATURA, the energy meter answer me. However, it answers me with the caracter "?" instead the expected value.

I am using the code below:

if (textsms.indexOf("FATURA") != -1) {
        char mess[100];
        float variable = valor_consumo_acc;
        sprintf(mess, "O Valor da Conta e = %f", variable);
        Sim800l_GSM_Module.sendSms("+5531985644009", mess);
        Serial.println(mess);
        Sim800l_GSM_Module.delAllSms();

The code works fine when I use variable as int number and sprintf(mess, "O Valor da Conta e = %d", variable)
%d instead %f for int number.
But with a float number, I am not getting.

Do you know, what can I do to solve it?

On arduino the sprintf function does not support float

So you have to handle that differently either by multiplying the value by 1000 and store in an int and display in millis whatever (like 0,2 Volt would be 200 mV) or by using the c function dtostrf()

Function dtostrf()
char * dtostrf(
double __val,
signed char __width,
unsigned char __prec,
char * __s)

The dtostrf() function converts the double value passed in val into an ASCII representationthat will be stored under s. The caller is responsible for providing sufficient storage in s.
Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the possible '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign. width is signed value, negative for left adjustment.
The dtostrf() function returns the pointer to the converted string s.