Help me with substring(0) method. GSM Code

Help me with substring(0) method.

I am attaching my gsm.ino file. I am trying to read serial data into a string using serialEvent and I in GSM_Send_Cmd() I am trying to set AT commands and the substring(0) check in if condition is failing. I am using SIM900 and I have tested the working in both Proteus and hardware. I am using UNO R3. The problem is in Proteus I can see that the Arduino is sending ATE0 to GSM and GSM is responding but the response is checked in while(s1.substring(0) != s2) and it is failing and hence Arduino is continuously sending ATE0. I can see that GSM is sending back \r\nOK\r\n on Proteus Virtual Terminal. I also tested in hardware but the same thing is happening.

gsm.ino (4.49 KB)

I think either SerialEvent is not working or substring(0) check is not working.

void serialEvent() {                                        // using serial interrupt to receive data
  while(Serial.available()) {
    // get the new byte:
    uartBuffer += (char)Serial.read();    
  }
  
  uartBuffer += '\0';
}

How many bytes are being read in before you terminate the string ? Serial bytes will be arriving quite slowly at 9600 baud but your code assumes that as soon as one byte is available the whole message is available. Is that really the case ? As a clumsy way of testing this put a short delay() in the while loop and see what happens.

I will be reading 100 to 300 bytes.

Hi

I have re-written the whole code using char arrays and still it is not working. Now I have written my own myStrStr(char *, const char *) function and I have tested it and it works fine, I have used strstr_test.ino to test whether myStrStr() works or not and it works and it finds the string in string. Now my actual project is sim900test.ino. myStrStr() is working by still it is only sending ATE0. What am I doing wrong ?

Can it be that SerialEvent is not firing ?

I confirm that SerialEvent is not firing. I tested both in Proteus and hardware. It is not working. I just added a line of code which makes LED on pin 13 high inside SerialEvent and LED is not turning ON indicating that SerialEvent is not firing. Is it a bug of Arduino 1.5.8 ? I am using HardwareSerial and I have included its header file.

sim900test.ino (10.8 KB)

strstr_test.ino (986 Bytes)

I confirm that SerialEvent is not firing

That would seem to indicate that no serial data is available. I have never really seen the point of it anyway. Why not just check if serial data is available each time through loop() and act on it if it is ?

I made a copy of the serialEvent example and it worked. I added a line to turn on an LED at pin 13 inside serialEvent and it worked. I made a copy of that working .ino and added other code related to my GSM project which sends SMS but in this .ino the serialEvent didn’t trigger. I am frustrated. Please somebody provide me a solution.

I am attaching both the .ino files.

serialEvent.ino (1.5 KB)

GSM_Device_Control.ino (1.51 KB)

The problem is in Proteus

This is NOT the Proteus forum!

I said that I am using both Proteus and hardware to test and in both I am getting the same result. I am also using software serial to debug what is happening. And I see in RealTerm "Sent ATE0..." and it repeats. It doesn't go further. I also see that modem is sending OK response for the command butArduino is not able to receive it using serialEvent. If it receives then the myStrStr() check will pass and it will send the next AT command.

butArduino is not able to receive it using serialEvent.

Then stop using it and do it yourself using Serial.available() to detect incoming serial bytes.

I tries as you said but it works fine for some commands and doesn't work for some others.

Here is the small change I made to the code.

void GSM_Send_Cmd(char *s1, const char *s2, const char *s3, const String s4, int *attempt) {
      while(myStrStr(s1, s2) == 0) {
              Serial.println(s3);
              while(!Serial.available());
              while(Serial.available()) {
                     uartBuffer[index++] = (char)Serial.read(); //read data             
              }
              Serial.flush();
              uartBuffer[index] = '\0';
                 
              
              
              debug.println(s4);
              
              if(*attempt == 3) {
                  GSM_RST = 1;
		  delay(1000);
		  GSM_RST = 0;
		  *attempt = 0;
	      }

              *attempt++;   
      }
  
      debug.println(msg5);
      memset(uartBuffer, '\0', 300);
      index = 0; 
      delay(1000);
}

I can't use the above method because I have to get read new SMS and take actions based on it and I have to wait till +CMTI: "SM",x response is received. So, I need to use serialEvent. I can't use polling because I have to do other things. I can't wait polling for serial data all the time. Why serialEvent works for a small code but not for big code ? Is it a bug of Arduino ?

              while(!Serial.available());
              while(Serial.available()) {
                     uartBuffer[index++] = (char)Serial.read(); //read data             
              }
              Serial.flush();

While there is no serial data to read, spin doing nothing. As soon as a byte arrives, read all of the characters that have arrived. Then, block until all pending data has been sent.

How many bytes to you expect the second while loop to read? If your answer is greater than one, it is wrong.

Why are you waiting for all pending serial data to be sent, when that function does not send any data?

For different AT commands the responses will be different and so I will be reading anywhere between 80 to 300 bytes.

My GSM_Send_Cmd() has to work like this

send an AT Command and if \r\nOK\r\n is not received then resend the command 3 times. If still \r\nOK\r\n is not received after sending commands three times then reset the GSM and start sending the same command another 3 times and repeat this process. On receiving of \r\nOK\r\n (respx) get out of the loop and clear the buffer and buffer index.

The problem is I can’t poll because my system has to be monitoring temperature sensor and other sensors and it also has to monitor incoming SMS. If temperature exceeds threshold value then it has to send SMS to a number stored in eeprom. If new SMS is received (serialEvent will receive “+CMTI: “SM”, x”) then it has to extract the SMS index from +CMTI response and then send AT+CMGR=x command and then read the SMS and extract the SMS removing the SMS header and then based on the SMS it has to take actions like setting the threshold of the temperature sensor, getting the status of lights, electric gate, etc… and send the status as SMS.

As such I can’t use polling. I have done some testing by adding small pieces of my code and I have finally found out that if I include just one GSM_Send_Cmd() function call in my code then serialEvent doesn not work but if I comment out the GSM_Send_Cmd() calls then serialEvent works fine. Is there a chance that GSM_Send_Cmd() function call is overflowing the stack and causing the problem ?

I am attaching my latest .ino and Proteus file. I have tested both in Proteus and hardware and serialEvent works if I don’t call GSM_Send_Cmd() in void setup() or void loop(). Even if I call GSM_Send_Cmd() once anywhere in the code then serialEvent doesn’t fire.

Please somebody give me a solution. In Proteus you can check by sending some characters. The serialEvent will fire and turn LED on pin 13. If ‘X’ is received then in void loop() it will turn ON LED on pin 12.

GSM_DC.zip (36.6 KB)

The problem is I can't poll because my system has to be monitoring temperature sensor and other sensors and it also has to monitor incoming SMS.

You'll need to get over it, then. You need to determine how often you REALLY need to read the temperature sensor and the other sensors. Continuous is almost certainly NOT the correct answer. If the temperature going over a limit will cause you to send a text message, the will POSITIVELY not result in instantaneous improvements in the situation. So, it's far more likely that reading the temperature once every 5 seconds will be often enough.

You CAN poll the phone because serial data arrives SLOWLY. Read and store what is available. Check the sensors. Make some decisions. End loop, and start over.

When the end of the text message arrives, THEN you parse it.

Is there a chance that GSM_Send_Cmd() function call is overflowing the stack and causing the problem ?

Yes. Reduce the amount of memory you are using, in every way possible, to make more room for the stack.

am attaching my latest .ino and Proteus file.

Seems like you forgot the ino file, and you CAN forget about the Proteus crap. This is NOT where you get help with that.

Updated my last post. I have attached the file there.

    if (uartBuffer[0] == 'X') {
      stringComplete = true;
    }

The string is complete because the first character is an 'X'? That's a strange definition of complete.

Have you measured how much free memory you have? All those useless Strings and all those char arrays live in SRAM. Most Arduinos don't have much SRAM.

The ‘X’ was just to test if interrupt is firing. I sent ‘a’ from Termite Serial terminal and LED on pin 13 turned ON. Then I sent ‘X’ and LED on pin 12 turned ON. serialEvent works.

I thought that declaring variables as constants will put it in program memory. How to put const variables in program memory ? Should I use something like this ?

const char cmd1[] PROGMEM = "ATE0";
const char cmd2[] PROGMEM = "AT+CMGF=1";

If yes, can I access variables in program memory for testing in myStrStr() ? I am currently using resp1, resp2, etc… in myStrStr() like this myStrStr(uartBuffer, resp1). If I define resp1 to be in PROGMEM then how can I use it in myStrStr(). I need to check if OK is received for AT Commands sent. Only if OK is received for certain commands and "> " is received for AT+CMGS=number then it should do further work.

I am attaching my latest .ino. Now even cmd’s are not being sent. I know because they are stored in PROGMEM. How to get a certail string from PROMMEM and use it in Serial.println() and also in my myStrStr() function for testing ?

GSM_DC.ino (5.44 KB)

I did something like this to get

const char cmd1 PROGMEM = "ATE0";

from PROGMEM to SRAM and print it but it is not working.

strcpy_P(msg, (char*)pgm_read_word(&(cmd1)));
Serial.println(msg);

but it is not working.

What, exactly, are you reading from program memory? A word. Is that close to what you stored in program memory? Not even.