Problem with periodic receiving of serial data

Hello, I am using 2 nos A6 GSM modem with two arduino uno. I already studied serial input basics from arduino forum. Both Arduinos are accepting serial input from gsm only when incoming string has a stating and ending markers. arduino1 will send @start# to arduino2, arduino2 will receive it and will send arduino1 back a message containing a random value, a count value, and device name. I have to send @start# from arduino1 to arduino2 periodically after each 5 min. That can be done by writing a character 'a' on the serial monitor of arduino1 periodically. Writing 'a' in the serial monitor will send sms once. For example, if I write 'a' on the serial monitor of arduino1, after sometime(upon receiving sms from arduino2), I can see deviceA|1|^1345^ which is desired. But it is working only for 3-4 times. Arduino1 code- https://github.com/tansquire/Project/blob/master/Learning/gsm/A6_polling_method_server_side_best

Arduino2 code- https://github.com/tansquire/Project/blob/master/Learning/gsm/A6_polling_method_deviceA_best

After working for random times, I am facing any one of the following problem. 1. Sometime arduino1 is receiving other characters also which are not inside @ and #. This is most surprising to me, as I have used the code from arduino forum which will receive data only which is inside @ and #. Why friends? 2.Sometime arduino1 is providing output from setup() function, i.e. code of function is getting executed though it is inside loop(). Is the arduino getting restarted? Is it an indication of buffer overflow?

3.Sometime arduino1 is sending message, received by 2 but arduino2 is unable to reply. May be arduino2 is not receiving properly.

  1. Sometime after writing 'a' on the serial monitor in arduino1, A6 modem is not responding(no led blink in A6). After that only option is to power off the arduino and power on again. Is it due to buffer overflow?

I am unable to understand whether the problem is with buffer overflow of hardware serial port or with software serial port.If it be the case, then the problem is with which arduino? Will it be solved if the buffer size is increased? How to ensure that the buffer size has been increased? I have one doubt, can buffer overflow occur due to both incoming and outgoing data or only for incoming data? Please suggest me guys whether the problem is with my code.

If you want answers on github, post your question there. If you want answers here, post your code HERE.

PaulS: If you want answers on github, post your question there. If you want answers here, post your code HERE.

The codes are above 250 lines. Will it support?

cotsquire: The codes are above 250 lines. Will it support?

What is "it" that needs to support anything?

There are stickies at the top of this forum that discuss how to post code. You HAVE read them, right? Specifically, the one that is titled "Read this BEFORE posting a programming question".

Arduino1 code

#include <SoftwareSerial.h>
SoftwareSerial mySerial(9, 10);
int8_t answer;
int count_sent_A=0;
int count_sent_B=0;
int count_rcv_A=0;
int count_rcv_B=0;
uint32_t prev_delete_millis;
uint32_t delete_interval=3000000;

void setup()
{
Serial.begin(9600); 
mySerial.begin(9600);    
Serial.println("Starting...");
power_on();

delay(500);

answer = sendATcommand("AT", "OK", 2000); 
if(answer==1)
Serial.println("ok");

delay(500);

answer = sendATcommand("AT+CSQ", "OK", 2000); 
if(answer==1)
Serial.println("good signal quality");

delay(500);

answer = sendATcommand("AT+CCID", "OK", 2000); 
if(answer==1)
Serial.println("SIM is plugged");

delay(500);

answer = sendATcommand("AT+CREG?", "OK", 2000); 
if(answer==1)
Serial.println("Registered to network");

delay(500);


answer = sendATcommand("AT+CNMI=2,2,0,0,0", "OK", 2000); 
if(answer==1)
Serial.println("Received message mode set");

delay(500);

SendMessage();
delay(500);
//SendMessageB();
    
}


void loop()
{
recvOneChar();
recvWithStartEndMarkers();
if(millis() -prev_delete_millis > delete_interval)
{
answer = sendATcommand("AT+CMGD=1,4", "OK", 2000); 
if(answer==1)
Serial.println("All message deleted");
else
Serial.println("Cant delete");
prev_delete_millis=millis();
}
}



 void SendMessage()
{
  Serial.print("Setting SMS mode...");
    answer=sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
    if(answer==1)
    Serial.println("SMS mode set");
    else
    Serial.println("Error setting SMS mode");
    Serial.println("Sending SMS");
    answer = sendATcommand("AT+CMGS=\"+917602304567\"\r", ">", 2000);    // send the SMS number
    if (answer == 1)
    {
        mySerial.println("Test sms-Sketch is ready to run");
        mySerial.write(0x1A);
        answer = sendATcommand("", "OK", 20000);
        if (answer == 1)
        {
            Serial.println("Initial SMS Sent ");    
        }
        else
        {
            Serial.println("Error in sending initial sms--Please check balance");
        }
    }
    else
    {
        Serial.print("error ");
        Serial.println(answer, DEC);
    }
}


void SendMessageA()
{
    
    Serial.print("Setting SMS mode...");
    answer=sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
    if(answer==1)
    Serial.println("SMS mode set");
    else
    Serial.println("Error setting SMS mode");
    Serial.println("Sending SMS to device A");
    answer = sendATcommand("AT+CMGS=\"+917358699052\"\r", ">", 2000);    // send the SMS number
    if (answer == 1)
    {
        mySerial.println("@start#");
        mySerial.write(0x1A);
        answer = sendATcommand("", "OK", 20000);
        if (answer == 1)
        {  
            count_sent_A++;
            Serial.print("Nos of SMS Sent to deviceA = ");
            Serial.println(count_sent_A);    
        }
        else
        {
            Serial.println("Error in sending SMS to deviceA--Please check balance");
        }
    }
    else
    {
        Serial.print("error ");
        Serial.println(answer, DEC);
    }
}







 void SendMessageB()
{
  
  Serial.print("Setting SMS mode...");
    answer=sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
    if(answer==1)
    Serial.println("SMS mode set");
    else
    Serial.println("Error setting SMS mode");
    Serial.println("Sending SMS");
    answer = sendATcommand("AT+CMGS=\"+919080404532\"\r", ">", 2000);    // send the SMS number
    if (answer == 1)
    {
        mySerial.println("@start#");
        mySerial.write(0x1A);
        answer = sendATcommand("", "OK", 20000);
        if (answer == 1)
        {
            count_sent_B++;
            Serial.print("Nos of SMS Sent to deviceB = ");
            Serial.println(count_sent_B);    
        }
        else
        {
            Serial.print("Error in sending SMS to deviceB--Please check balance");
        }
    }
    else
    {
        Serial.print("error ");
        Serial.println(answer, DEC);
    }
}






void recvOneChar() 
{
char receivedChar;
boolean newData = false;
    if (Serial.available() > 0) 
    {
        receivedChar = Serial.read();
        newData = true;
    }
     if (newData == true) 
    {
      if(receivedChar=='a')
      {
      SendMessageA();
      newData = false;
      }
      else if(receivedChar=='b')
      {
      SendMessageB();
      newData = false;
      }
      else
      {
      newData = false;
      return;
      }
    }
}



void recvWithStartEndMarkers() 
{
const byte numChars = 100;
char receivedChars[numChars];
char message[numChars];
boolean newData = false;


    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '@';
    char endMarker = '#';
    char rc;
 
    while (mySerial.available() > 0 && newData == false) 
    {
        rc = mySerial.read();

        if (recvInProgress == true) 
        {
            if (rc != endMarker) 
            {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) 
                {
                    ndx = numChars - 1;
                }
            }
            else 
            {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) 
        {
            recvInProgress = true;
        }
    }


if (newData == true) 
    {
        
        
        if (strstr(receivedChars, "deviceA") != NULL)
        {
        count_rcv_A++;
        Serial.print("SMS No--");
        Serial.print(count_rcv_A);
        Serial.print("---");
        Serial.println(receivedChars); 
        newData = false;
        }
        else if (strstr(receivedChars, "deviceB") != NULL)
        {
        count_rcv_B++;
        Serial.print("SMS No--");
        Serial.print(count_rcv_B);
        Serial.print("---");
        Serial.println(receivedChars); 
        newData = false;
        }

        else
        {
        newData = false;
        return;
        }
    }

}


int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout)
{

    uint8_t x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '\0', 100);    // Initialice the string

    delay(100);

    while( mySerial.available() > 0) mySerial.read();    // Clean the input buffer

    mySerial.println(ATcommand);    // Send the AT command 


    x = 0;
    previous = millis();

    // this loop waits for the answer
    do{
        if(mySerial.available() != 0){    // if there are data in the UART input buffer, reads it and checks for the asnwer
            response[x] = mySerial.read();
            x++;
            if (strstr(response, expected_answer) != NULL)    // check if the desired answer is in the response of the module
            {
                answer = 1;
            }
        }
    }while((answer == 0) && ((millis() - previous) < timeout));    // Waits for the asnwer with time out

    return answer;
}


void power_on()
{

    uint8_t answer=0;

    // checks if the module is started
    answer = sendATcommand("AT", "OK", 2000);
    if (answer == 0)
    {
        
        while(answer == 0){     // Send AT every two seconds and wait for the answer
            answer = sendATcommand("AT", "OK", 2000);    
        }
    }
    Serial.println("modem ready");

}

Sorry guys. This is Arduino2 code. Previous one was arduino1 code

#include <SoftwareSerial.h>
SoftwareSerial mySerial(9, 10);
int8_t answer;
int count_sent_A=0;
uint32_t prev_delete_millis;
uint32_t delete_interval=30000000;
uint32_t prev_power_millis;
uint32_t power_interval=3558000; 


void setup()
{
Serial.begin(9600); 
mySerial.begin(9600);    
Serial.println("Starting...");
power_on();
delay(500);

answer = sendATcommand("AT", "OK", 2000); 
if(answer==1)
Serial.println("ok");
delay(500);

answer = sendATcommand("AT+CSQ", "OK", 2000); 
if(answer==1)
Serial.println("good signal quality");
delay(500);

answer = sendATcommand("AT+CCID", "OK", 2000); 
if(answer==1)
Serial.println("SIM is plugged");
delay(500);

answer = sendATcommand("AT+CREG?", "OK", 2000); 
if(answer==1)
Serial.println("Registered to network");
delay(500);


answer = sendATcommand("AT+CNMI=2,2,0,0,0", "OK", 2000); 
if(answer==1)
Serial.println("Received message mode set");
delay(500);

SendMessage();
delay(500);

}


void loop()
{ 
 sms_task();
 lora();


if(millis() -prev_power_millis > power_interval)
{
power_on();
prev_power_millis=millis();
}
 
}

void power_on()
{

    uint8_t answer=0;

    // checks if the module is started
    answer = sendATcommand("AT", "OK", 2000);
    if (answer == 0)
    {
        
        while(answer == 0){     // Send AT every two seconds and wait for the answer
            answer = sendATcommand("AT", "OK", 2000);    
        }
    }
    Serial.println("modem ready");

}

int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout){

    uint8_t x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '\0', 100);    // Initialice the string

    delay(100);

    while( mySerial.available() > 0) mySerial.read();    // Clean the input buffer

    mySerial.println(ATcommand);    // Send the AT command 


    x = 0;
    previous = millis();

    // this loop waits for the answer
    do{
        if(mySerial.available() != 0){    // if there are data in the UART input buffer, reads it and checks for the asnwer
            response[x] = mySerial.read();
            x++;
            if (strstr(response, expected_answer) != NULL)    // check if the desired answer is in the response of the module
            {
                answer = 1;
            }
        }
    }while((answer == 0) && ((millis() - previous) < timeout));    // Waits for the asnwer with time out

    return answer;
}



void wait(unsigned int timeout)   //It works for  timeout time.
{
uint8_t x=0;  
unsigned long previous;
while( mySerial.available() > 0) mySerial.read();    // Clean the input buffer//If you dont use this line, still working
previous = millis();
do{
       sms_task();
            
  }
    
   while(((millis() - previous) < timeout));   

}

void lora()
{
int m,n;

 wait(10000);            
 Serial.println("I am working other job");
 for(int j=0;j<100;j++)
 for(int k=0;k<100;k++)
 int m=k*j;


 wait(10000);            
 for(int j=0;j<100;j++)
 for(int k=0;k<100;k++)
  m=k*j;


 wait(10000);            
 for(int j=0;j<100;j++)
 for(int k=0;k<100;k++)
 m=k*j;

 
 wait(10000);            
 for(int j=0;j<100;j++)
 for(int k=0;k<100;k++)
 m=k+j;
 
 
 Serial.println("I am working other job");
}







void SendMessage()
{
  Serial.print("Setting SMS mode...");
    answer=sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
    if(answer==1)
    Serial.println("SMS mode set");
    else
    Serial.println("Error setting SMS mode");
    Serial.println("Sending SMS");
    answer = sendATcommand("AT+CMGS=\"+917602304567\"\r", ">", 2000);    // send the SMS number
    if (answer == 1)
    {
        mySerial.println("Test sms-Sketch is ready to run");
        mySerial.write(0x1A);
        answer = sendATcommand("", "OK", 20000);
        if (answer == 1)
        {
            Serial.println("Initial SMS Sent ");    
        }
        else
        {
            Serial.println("Error in sending initial sms--Please check balance");
        }
    }
    else
    {
        Serial.print("error ");
        Serial.println(answer, DEC);
    }
}


void SendMessageA()
{
    char message[100];
    answer=sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
    Serial.println("Sending SMS to device A");
    answer = sendATcommand("AT+CMGS=\"+919940323276\"\r", ">", 2000);    // send the SMS number
    if (answer == 1)
    {   int i=random(1,5000);
        //float f=i/1000;
        count_sent_A++;
        sprintf(message,"@%s|%d|<%d>#","deviceA",i,count_sent_A);
        mySerial.println(message);
        mySerial.write(0x1A);
        answer = sendATcommand("", "OK", 20000);
        if (answer == 1)
        {
            Serial.println("sent");    
        }
        else
        {
            Serial.println("Error in sending initial sms--Please check balance");
        }
        
    }

    else
    {
        Serial.print("error ");
        Serial.println(answer, DEC);
    }
    
    
}






void sms_task() 
{
const byte numChars = 100;
char receivedChars[numChars];
boolean newData = false;


    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '@';
    char endMarker = '#';
    char rc;
 
    while (mySerial.available() > 0 && newData == false) 
    {
        rc = mySerial.read();

        if (recvInProgress == true) 
        {
            if (rc != endMarker) 
            {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) 
                {
                    ndx = numChars - 1;
                }
            }
            else 
            {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) 
        {
            recvInProgress = true;
        }
    }


if (newData == true) 
    {
        
        
        if(strstr(receivedChars, "start") != NULL)
        {
        Serial.println(receivedChars);
        SendMessageA();
        delay(1000);
        delete_sms();
        newData = false;
        }

        else
        {
        newData = false;
        return;
        }
    }

}

void delete_sms()

{
answer = sendATcommand("AT+CMGD=1,4", "OK", 2000); 
if(answer==1)
Serial.println("All message deleted");
else
Serial.println("Cant delete");
}

I see delay(1000) in the middle of one of your programs. The code in Serial Input Basics is written on the assumption that there are no delay()s in the program. Use millis() to manage timing without blocking as illustrated in Several things at a time.

IMHO you fill find the whole business much easier if you don't add parsing code into the function recvWithStartEndMarkers() and if you don't change the name of that function (as you have done in one of your programs). Create a separate function for parsing the received data and make no changes to recvWithStartEndMarkers() apart from changing the marker characters.

I don't understand your description in the first paragraph of the Original Post. You mention SMS messages and the serial monitor and I can't get a clear image of what it all means. Maybe you can write down the series of actions that you want to happen with one action on each line.

...R

Thank robin for your reply. Let me give a clear picture here. Arduino1 is connected to a laptop As well as to gsm modem1 , and is kept inside control room. Arduino-2 is in the field, and is connected to gsm modem2. Therefore, arduino1 is using 2 serial ports, one with the laptop(the hard ware serial port), and the other one is with the gsm modem(the software serial port, called mySerial). If the character 'a' is sent from the serial monitor window of ide software which is in the laptop, that is received by arduino1 through hardware serial port. Upon receiving this character, arduino1 sends AT command to gsm modem1 for sending sms (@start#)to gsm modem-2. After receiving this sms, gsm modem2 immediately sends that to arduino2 through mySerial. Arduino2 can only receive something through mySerial if it is starts with@ and ends with #.Therefore, arduino2 receives "start". If "start" is received by arduino2, it creates a new string containing it's name, sms no to be sent, and a random value. One example of such string is @deviceA|3|^5676^#. Then, arduino2 gives AT command to gsm modem 2 for sending this string as sms to gsm modem1. Therefore, @deviceA|3|^5676^# is received by gsm modem1 as a sms from gsm modem2. @deviceA|3|^5676^# is immediately forwarded to arduino1 by gsm modem1 through mySerial port . Arduino1 can receive characters between @and #. Therefore, Arduino1 displays deviceA|3|^5676^ on the serial monitor window of ide software in the laptop. The whole thing can be assumed as a system whose input is 'a' and output is a string like deviceA|3|^4454^(let x). both input and output are in the serial monitor of ide software in the laptop with a response time =time taken by the whole process as described.(approximately 12 second). I want to apply input after each 5 min to get a valid response. I think, now it should be clear to you. I am facing the problem as described earlier.

Arduino1 is connected to a laptop As well as to gsm modem1

That’s obvious because the name of the SoftwareSerial instance is mySerial. I can’t imagine why Robin2 couldn’t see that.

Well, one of the three of us is doing something stupid, and I don’t think it’s Robin2. And, I’m pretty sure that it isn’t me…

If, anyone has understood my program, and has identified the problem, please suggest me.

cotsquire:
If, anyone has understood my program, and has identified the problem, please suggest me.

Can you post the updated program so we can see where the next problem is?

You cannot expect anyone reading the huge block of text in Reply #7 to be able to make sense of it. See how much esier it is to read when some paragraph breaks are added.

Thank robin for your reply. Let me give a clear picture here.

Arduino1 is connected to a laptop As well as to gsm modem1 , and is kept inside control room.

Arduino-2 is in the field, and is connected to gsm modem2.

Therefore, arduino1 is using 2 serial ports, one with the laptop(the hard ware serial port), and the other one is with the gsm modem(the software serial port, called mySerial).

If the character 'a' is sent from the serial monitor window of ide software which is in the laptop, that is received by arduino1 through hardware serial port. Upon receiving this character, arduino1 sends AT command to gsm modem1 for sending sms (@start#)to gsm modem-2.

After receiving this sms, gsm modem2 immediately sends that to arduino2 through mySerial. Arduino2 can only receive something through mySerial if it is starts with@ and ends with #.Therefore, arduino2 receives "start".

If "start" is received by arduino2, it creates a new string containing it's name, sms no to be sent, and a random value.

One example of such string is @deviceA|3|^5676^#.

Then, arduino2 gives AT command to gsm modem 2 for sending this string as sms to gsm modem1.

Therefore, @deviceA|3|^5676^# is received by gsm modem1 as a sms from gsm modem2. @deviceA|3|^5676^# is immediately forwarded to arduino1 by gsm modem1 through mySerial port .

Arduino1 can receive characters between @and #. Therefore, Arduino1 displays deviceA|3|^5676^ on the serial monitor window of ide software in the laptop.

The whole thing can be assumed as a system whose input is 'a' and output is a string like deviceA|3|^4454^(let x). both input and output are in the serial monitor of ide software in the laptop with a response time =time taken by the whole process as described.(approximately 12 second).

I want to apply input after each 5 min to get a valid response. I think, now it should be clear to you. I am facing the problem as described earlier.

...R

Now that you have explained the requirement more clearly your two programs seem horribly complicated - especially that for Arduino2.

It seems to me that you could reduce the code in loop() in both programs to something like this

void loop() {
  recvOneChar(); // only needed for Arduino1
  checkCommand();
  recvWithStartEndMarkers();
  checkReceivedSMSmessage();
  createAndSendSMSmessage();
}

You must get all the delay()s out of your code - if you don't the Arduino will just be twiddling its thumbs when it should be doing something.

If you have a pair of programs that each depend on the other doing something you need to have code to deal with the situation when an expected message does not arrive. Otherwise you get what is called a deadlock with each waiting for the other to do something.

...R

Is the memory size of my sketch more than what is supported by arduino uno?I think that's why I am getting a restart sometime.

cotsquire: Is the memory size of my sketch more than what is supported by arduino uno?I think that's why I am getting a restart sometime.

Why do I have the impression that you are not taking any notice of my comments?

...R

Robin2: Why do I have the impression that you are not taking any notice of my comments?

...R

Because making intelligent changes to the code/responses requires too much effort, apparently.