Missing character when introducing delay in the code

I am using the following code for reading any incoming message, and doing something after decoding the incoming string. There is a delay of 10sec in the code. When this delay is not introduced in the code, it is working nice. In this case, the output is like below.

+CIEV: “MESSAGE”,1

+CMT: “+919080404532”,“2018/02/09,19:30:51+06”
This is an incoming test message

When the delay is introduced, I am unable to see the message on the serial monitor, and subsequent action is not taken by the code. The output is like below.

+CIEV: “MESSAGE”,1
+CMT: “+919080404532”,"2018/02/09,1

It is clear that, I am missing some character in serial monitor. If delay is reduced to 400 ms, the output is like below.

+CMT: “+919080404532”,“2018/02/09,19:30:51+06”
This is an incoI am working other job

I checked the following, but did not get any improvement.

Serial.flush and mySerial.flush

Increased both hardware, and software aerial buffer size

used if (!mySerial.available() before delay

Changed baud rate for both

Instead of of Serial.readString(), I used Serial.read() character by character inside function loop

Without use of the delay, it is working nice. I Think you guys are experienced, and can sort out the problem easily.

//while Introducing any delay in function loop, incoming message cant be read
//working with power failure but with serial monitor
#include <SoftwareSerial.h>
SoftwareSerial mySerial(9, 10); // TX-Pin11, RX-Pin10
String str="";
void updateSerial()
{
delay(2000);
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
}

}

void setup()
{
Serial.begin(9600);
mySerial.begin(9600);
modemsetup();
}

void loop()
{
Serial.println(“I am working other job”);
//delay(10000); //If you give this delay, then incoming message cant be read
smstask();
}

void smstask()
{
if(mySerial.available())
{
str=mySerial.readString();
Serial.println(str);
int bra = str.indexOf(’@’);
int ket = str.indexOf(’#’);
String str1=str.substring(bra+1,ket);

if(str1==“server”)
{
Serial.println(str);
int i=random(1,500);
String str2=(String)i;
String str3="@deviceA#"+str2;
mySerial.println(“AT+CMGF=1”); //Sets the GSM Module in Text Mode
updateSerial();
mySerial.println(“AT+CMGS=”+917602304567"\r"); // Replace x with mobile number
updateSerial();
mySerial.println(str3);// The SMS text you want to send
updateSerial();
mySerial.println((char)26);// ASCII code of CTRL+Z
updateSerial();
mySerial.println(“AT+CMGD=1,4”); // AT Command to receive a live SMS
updateSerial();
}
}

}

void modemsetup()
{
for(int i=0;i<3;i++)
{
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();

mySerial.println(“AT+SNFS=0”); //Adjust to earphone mode(AT+SNFS=1 is microphone mode)
updateSerial();

mySerial.println(“AT+CRSL=2”); //Adjust volume, volume range is 0-15, maximum:15
updateSerial();

mySerial.println(“AT+CMGF=1”);
updateSerial();

mySerial.println(“AT+CMGD=1,4”);
updateSerial();
}

mySerial.println(“AT+CMGS=”+917602304567"\r");
updateSerial();

mySerial.println(“I am SMS from GSM Module”);
updateSerial();

mySerial.println((char)26);// ASCII code of CTRL+Z
updateSerial();

}

Please read the "How to use this forum" post and then reformat your code. If you would like assistance it is helpful to have the code easily accessible for copy/paste.

In the meantime, if you insist on using delay(10000), which essentially tells Arduino to do nothing for 10 seconds, you should investigate the yield() function which is a weak, empty function hidden (not really but not well documented) inside delay. This allows you to do 'stuff' while in the delay, thereby not losing the PC. You may wish to query mySerial.available in yield() to see if anything has come in while delaying and throw it in a buffer.

Is it possible you are overflowing the Serial buffer? It is generally limited to x, I think to 64 bytes /characters, not sure.
Read the message "as it comes" , without the delay and get the number of characters read to make sure.

Actually since most (serial) messages are asynchronous you may as well "wait" for the message start using "Serial.available()" which "counts" the number of characters in Serial buffer.

  • either in if(Serial.available()} or while(Serial.available()).

Thank you for your reply.
I added First two lines inside if(mySerial.available()).

Serial.print("Databytes available on mySerial port= ");
Serial.println(mySerial.available());
str=mySerial.readString();
Serial.println(str);

With introducing delay, I am getting the following message everytime.

Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,11:5
Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,11:5
Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:0

Without delay, I am getting the body part of the message. The output is like these

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:11:15+06"
This is a test message

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:11:56+06"
This is another test message

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:13:36+06"
One more test message. Let us see how many bytes do I receive now?

Why am I getting 5 bytes every time irrespective of what message is received? Also why 63 bytes every time with introducing delay in the code?

Thanks DKWatson.
To use yield() function, I have to import Scheduler.h. I am getting an error as "No such file or directory" during compilation.
It seems that Arduino UNO does not support Scheduler.h

Indeed sounds like buffer overflow.

Read Serial Input Basics to get ideas. Depending on the size of the message, you might have to adjust the buffer.

Thanks DKWatson. Instead of using delay, I created a delay function using millis, and inside that, I continued checking serial input. Now it is working. Instead of calling delay(10000), I am calling wait(10000). Thanks again.

void wait(unsigned int timeout) //It works for timeout time.
{
uint8_t x=0;
char response[100];
unsigned long previous;
memset(response, ‘\0’, 100);
while( mySerial.available() > 0) mySerial.read(); // Clean the input buffer
previous = millis();
do{
smstask();

}

while(((millis() - previous) < timeout));

}

cotsquire:
Thank you for your reply.
I added First two lines inside if(mySerial.available()).

Serial.print("Databytes available on mySerial port= ");
Serial.println(mySerial.available());
str=mySerial.readString();
Serial.println(str);

With introducing delay, I am getting the following message everytime.

Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,11:5
Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,11:5
Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:0

Without delay, I am getting the body part of the message. The output is like these

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:11:15+06"
This is a test message

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:11:56+06"
This is another test message

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:13:36+06"
One more test message. Let us see how many bytes do I receive now?

Why am I getting 5 bytes every time irrespective of what message is received? Also why 63 bytes every time with introducing delay in the code?

cotsquire:
Thank you for your reply.
I added First two lines inside if(mySerial.available()).

Serial.print("Databytes available on mySerial port= ");
Serial.println(mySerial.available());
str=mySerial.readString();
Serial.println(str);

With introducing delay, I am getting the following message everytime.

Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,11:5
Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,11:5
Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:0

Without delay, I am getting the body part of the message. The output is like these

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:11:15+06"
This is a test message

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:11:56+06"
This is another test message

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:13:36+06"
One more test message. Let us see how many bytes do I receive now?

Why am I getting 5 bytes every time irrespective of what message is received? Also why 63 bytes every time with introducing delay in the code?

cotsquire:
Thank you for your reply.
I added First two lines inside if(mySerial.available()).

Serial.print("Databytes available on mySerial port= ");
Serial.println(mySerial.available());
str=mySerial.readString();
Serial.println(str);

With introducing delay, I am getting the following message everytime.

Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,11:5
Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,11:5
Databytes available on mySerial port= 63

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:0

Without delay, I am getting the body part of the message. The output is like these

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:11:15+06"
This is a test message

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:11:56+06"
This is another test message

Databytes available on mySerial port= 5

+CIEV: "MESSAGE",1

+CMT: "+919080404532",,"2018/02/10,12:13:36+06"
One more test message. Let us see how many bytes do I receive now?

Why am I getting 5 bytes every time irrespective of what message is received? Also why 63 bytes every time with introducing delay in the code?

Pretty much what was suspected - you are overfilling your Serial buffer - 64 bytes long while you are stuck in delay(x).
You need to read the Serial buffer as (asynchronous serial ) data comes in , not to wait ANYTIME in your code.

As far as getting message count of 5 you are possibly reading the buffer (64 bits) , Serial is clearing it as it reads and then getting "the rest of the message " of 5 bytes you are then reading.

In short , try this PSEUDOCODE

while(Serial.available()) check the Serial buffer for data
{

have data in Serial buffer , now get it into MyBuffer > 64 bytes long

while(DataCount = Serial.readBytesUntil(character, MyBuffer, length))
{

all data received , now read the Mybuffer and do whatever with the message...

}
}

Here is the basic of readBytesUntil function- check "Resources ->serial" for details.

Serial.readBytesUntil(character, buffer, length)

Parameters
character : the character to search for (char)

buffer: the buffer to store the bytes in (char or byte)

length : the number of bytes to read (int)

When you get this working we could try adding "timeout " later for simple error checking.

PS

I am not sure , it is not well documented, how to pass "null" parameter as stop character.
(I'l check the source code )

Edited

Silly me,
Serial.readBytes(MyBuffer, length) reads Serial buffer until the expected message "length" is reached.
Consequently message length must be known.

Disregard this
You may have to experiment with that such as ( NULL,MyBuffer,ACTUAL length of message expected) to stop checking for terminating character.

Dupe
Of course for now set the "length" to ACTUAL length of message expected, hopefully it is constant.