Need help on filtering certain values with sim800L

I am struggling with getting a task done. I have a sim800L module hooked up to an arduino nano. I want to be able to turn on and off a relay when a text is received by the module, but I also want it be happen when I text either "start" or "stop" to the module.

I ran my code using the serial monitor for testing, and it works. The issue is that when I receive a text it comes along with a lot of other information I dont need, and I dont know how to filter it out.

ex) +CMT: "+1xxxxxxxxx","","21/01/04,00:03:17-20"
start

Can anyone help me, like i said I need the words "start" and "stop" to use as my triggers

just focus on the Loop, not the rest of the stuff

#include <SoftwareSerial.h>
SoftwareSerial sim(2,3); // RX, TX

byte outputPin= 5;
byte triggerDelay=2000;
char c;
String readstring="";

void setup() {
  Serial.begin(9600);   //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  sim.begin(9600);      //Begin serial communication with Arduino and SIM800L
  Serial.println("Initializing...");
  delay(1000);

  sim.println("AT");    //Assuring Communication is Succesful
  //updateSerial();
  sim.println("AT+CMGF=1"); // Configuring TEXT mode
  //updateSerial();
  //sim.println("AT+CNMI=1,2,0,0,0"); // Decides how newly arrived SMS messages should be handled
  //updateSerial();
  Serial.println("Waiting for Messages...");

  pinMode(outputPin, OUTPUT);
  digitalWrite(outputPin, LOW);
}

void loop() {
  while(sim.available()){
    c=sim.read();
    readstring+=c;
  }
  Serial.println(readstring);
    if(readstring=="start"){
      digitalWrite(outputPin, HIGH);
      delay(triggerDelay);
      digitalWrite(outputPin, LOW);
      Serial.println("Message Received");
      }
    if(readstring=="stop"){
      digitalWrite(outputPin, HIGH);
      delay(triggerDelay);
      digitalWrite(outputPin, LOW);
      Serial.println("Message Received");
      }
    readstring="";
    delay(500);
    }

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

I'm not familiar with sims. Serial communication is slow so we don't know how your data arrives; maybe one long piece of text or maybe a few lines. Replace your loop() with below and post the output in serial monitor when you send a 'start' to the sim.

void loop()
{
  if (sim.available())
  {
    char c = sim.read();
    if (c < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(c, HEX);
    Serial.print(" ");
  }
}

i suggest reading an entire line of text, presumably terminated with a linefeed or some other character and searching for the substrings you're interested in

consider

// recognize "start" or "stop" in strings such as
//      "ex) +CMT: "+1xxxxxxxxx","","21/01/04,00:03:17-20" start";

char s [80];
int  idx = 0;

void setup (void)
{
    Serial.begin (115200);
}

void start (void)
{
    Serial.println ("start:");
}

void stop (void)
{
    Serial.println ("stop:");
}

void loop (void)
{
    if (Serial.available ())  {
        char c = Serial.read();
        s [idx++] = c;
        if ('\n' == c)  {
            if (strstr (s, "start"))
                start();
            else if (strstr (s, "stop"))
                stop();
            idx = 0;
        }
    }
}

Hey sterretje,

I replaced my loop with yours and this is what I got as a response to the text "start",

0D 0A 2B 43 4D 54 49 3A 20 22 53 4D 22 2C 31 32 0D 0A

What exactly does that mean?

The ascii values of the hex values you received is

+CMTI: "SM",12

The issue is that when I receive a text it comes along with a lot of other information I dont need, and I dont know how to filter it out.
ex) +CMT: "+1xxxxxxxxx","","21/01/04,00:03:17-20"
start

You must have changed the AT+CNMI instructions to the module and the message is now stored in location 12 instead of being forward to the output.

I think that you will find it easier to read the message when received and then parse as suggested with strstr().

Given that the entire message is present when the module reports Serial.available() you can use .readBytes() and then null terminate as in the following example

//+CMT: "+447xxxxxxxx","","18/09/21,20:54:59+04" SITE WHATS HAPPENING
//enter the message from serial monitor for testing
//actual modem rely message begins with<CR><LF>
char Grsp[100];//size for max message
char str1[30];//size appropriately for parsed characters
char str2[30];//size appropriately for parsed characters
boolean newMessage = false;
boolean prefixMatch = false;
void setup()
{
  Serial.begin(115200);
  //set ms timeout for Serial.readBytes() if no data
  Serial.setTimeout(100);
}

void loop() {

  while (Serial.available() > 0)
  {
    //readBytes returns number read not zero referenced
    byte numChars = Serial.readBytes(Grsp, 100);
    Grsp[numChars] = '\0';//null Terminate
    newMessage = true;
    Serial.println(Grsp);
  }
//can define a series of prefix messages for match

  //if (strncmp(Grsp, "+CMT", 4) == 0 && newMessage == true)
  //change to accomodate lead characters <CR> <LF>
  if(strstr(Grsp, "+CMT") != 0 and newMessage == true)
  {
    Serial.println("prefixMatch +CMT");
    prefixMatch = true;
    newMessage = false;
  }
  else if (newMessage == true)
  {
    Serial.println("no prefixMatch");
    newMessage = false;
  }

  if (prefixMatch == true)
  {
    prefixMatch = false;
    char* strtokIndx;
    //find first "
    strtokIndx = strtok(Grsp, " \" ");//need excape for " delimiter
    //find second "
    strtokIndx = strtok(NULL, " \" ");
    strcpy(str1, strtokIndx); //characters between first set of ""
    for (byte i = 0; i < 3; i++) //skip3 " delimiters
    {
      strtokIndx = strtok(NULL, " \" ");
      Serial.println(strtokIndx);
    }
    //find ending character message
    strtokIndx = strtok(NULL, ""); //last " to end of string no delimiter \0 terminator
    strcpy(str2, strtokIndx + 1); //skip space preceding SITE
    
    Serial.print("Number = ");
    Serial.println(str1);
    Serial.print("Ending message = ");
    Serial.println(str2);
  }
}

OK, I actually wanted the result of the text that you have in the opening post :wink:

Not sure why your message starts with a carriage return / line feed (0x0D/0x0A) but it ends with that. The message reads (in ASCII; see e.g. http://www.asciitable.com/)

+CMTI: "SM",12

This is without the newline.

The important part was the line ending 0x0D 0x0A which one usually will not see in e.g. Serial Monitor and hence I requested the hex representation of what you received.

You can now e.g. use the approach with recvWithEndmarker in Robin2's Serial Input Basics - updated to read the received text; replace Any occurrences of Serial in that function by sim for the software serial port.

The below code contains two functions to remove newline characters from the incoming message. It also contains a modified version of showNewData() that makes use of those two function. Note that this is a demo code which contains the message that you posted in reply #3; using Robin's recvWithEndmarker(), the last NL will not be there but that does not affect the functioning of the demo. For the demo, I've hard-coded receivedChars.

const byte numChars = 32;
char receivedChars[numChars] = {0x0D, 0x0A, 0x2B, 0x43, 0x4D, 0x54, 0x49, 0x3A, 0x20, 0x22, 0x53, 0x4D, 0x22, 0x2C, 0x31, 0x32, 0x0D, 0x0A};

boolean newData = false;

void setup()
{
  Serial.begin(57600);
  newData = true;
  showNewData();
}

void loop()
{
  // put your main code here, to run repeatedly:

}

void showNewData()
{
  if (newData == true)
  {
    Serial.print("This just in ... '");
    Serial.print(receivedChars);
    Serial.println("'");

    removeTrailingNL(receivedChars);
    Serial.print("After removing trailing newline ... '");
    Serial.print(receivedChars);
    Serial.println("'");


    removeLeadingNL(receivedChars);
    Serial.print("After removing leading newline ... '");
    Serial.print(receivedChars);
    Serial.println("'");

    Serial.println("You now have a message that you can parse");

    newData = false;
  }
}

/*
   remove leading <CR> and/or <LF> from a text buffer
   In:
    text buffer to clean
*/
void removeLeadingNL(char *ptr)
{
  while (ptr[0] == '\r' || ptr[0] == '\n')
  {
    memmove(&ptr[0], &ptr[1], strlen(ptr));
  }
}

/*
   remove trailing <CR> and/or <LF> from a text buffer
   In:
    text buffer to clean
*/
void removeTrailingNL(char *ptr)
{
  while (ptr[strlen(ptr) - 1] == '\r' || ptr[strlen(ptr) - 1] == '\n')
  {
    ptr[strlen(ptr) - 1] = '\0';
  }
}

Output:

This just in ... '
+CMTI: "SM",12
'
After removing trailing newline ... '
+CMTI: "SM",12'
After removing leading newline ... '+CMTI: "SM",12'
You now have a message that you can parse

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.