If statement is skipped even though the condition is met!

I have a very long application that deals with a 4G shield and i made a code to parse the incoming data from the shield to the Arduino.
The code is supposed to read what comes from the shield and act upon that.
Reading is done and tested with no problems
The problem is, i have a condition in an if statement that is being met and yet the if statement is being skipped and the software just goes to the else.

Here is the part of the code that parse the data:

SoftwareSerial MYGSM(7, 8); // Define virtual serial port name as MYGSM,Rx is port 7, Tx is port 8

enum parsechecking //PARSING MACHINE WITH DIFFERENT STATES
{
  todetectmessge,
  toignore,
  workwithit,
  nextworkwithit
};

byte parsechecking = todetectmessge; //START HERE

char buffer[256];                     // buffer of character
byte pos = 0; //the current position

uint8_t state; //machine inside the loop to send the command once
const uint8_t START = 0;
const uint8_t tochecknetwork = 1;


void resetBuffer()
{
  memset(buffer, 0, sizeof(buffer));
  pos = 0;
}




void setup()
{
  MYGSM.begin(19200);
  Serial.begin(19200);
}

void loop()
{
  if (state == START)
  {
    Serial.println("we just sent the CSQ");
    MYGSM.println("AT+CSQ");
    //this command is sent to the module to check the connection
    //it return a vule in this form: +CSQ: xx,xx
    // so basically if it's 99,xx OR xx,99 i want to switch to offline
    //because the connection was not established

    state = tochecknetwork;
    Serial.println("WE are reading ");
  }

  else if (state == tochecknetwork)
  {

    while (MYGSM.available())
    {
      const char *checked = MYGSM.read();
      checkparsename(checked); //take the reading from it and parse it
    }
  }



}


void checkparsename(byte b)
{

  buffer[pos++] = b;
  if (pos >= sizeof(buffer))
    resetBuffer(); // just to be safe


  // Detailed debugging
  Serial.println();
  Serial.print("state = ");
  Serial.println(parsechecking);
  Serial.print("pos = ");
  Serial.println(pos);
  Serial.print("buffer = ");
  Serial.println(buffer);

  switch (parsechecking)
  {
    case todetectmessge:
      Serial.println("Detecting");
      if (b == '\n')
        resetBuffer();

      if (pos == 6 && strcmp(buffer, "AT+CSQ") == 0) //this is what was sent
      {
        parsechecking = toignore;
      }

      if (pos == 5 && strcmp(buffer, "+CSQ:") == 0)//this is the responce from the module
      {
        resetBuffer();
        parsechecking = workwithit;
      }

      break;

    case toignore:
      Serial.print("Ignoring echoCSQ:  ");
      Serial.println(buffer);
      resetBuffer();
      parsechecking = todetectmessge;
      break;

    case workwithit:
      if (b == ',')
      {
        Serial.print("The reciecved signal is:");
        Serial.println(buffer);
        if (pos == 4 && strcmp(buffer, " 99,") == 0)
        {
          Serial.println("it's 99");
          // state = nosignalfound;
          resetBuffer();
          parsechecking = nextworkwithit;
        }
        else
        {
          Serial.println("we can go");
          resetBuffer();
          parsechecking = nextworkwithit;
          // state = signalfound;
        }
      }
      break;

    case nextworkwithit:
      if (b == '\n')
      {
        Serial.print("In the nextworkwithit:");
        Serial.println(buffer);
        if (pos == 2 && strcmp(buffer, "99") == 0)
        {
          Serial.println("SIGNAL NOT FOUND");
          // state = nosignalfound;
        }
        else
        {
          Serial.println("signal found;");
          // state = signalfound;
        }
      }
  }
}

And i'm sure the conditions are satisfied accourding to the debugging
here is an example output

4:02:06.883 -> WE are reading
14:02:06.883 ->
14:02:06.883 -> state = 0
14:02:06.883 -> pos = 1
14:02:06.883 -> buffer = A
14:02:06.931 -> Detecting
14:02:06.931 ->
14:02:06.931 -> state = 0
14:02:06.931 -> pos = 2
14:02:06.931 -> buffer = AT
14:02:06.931 -> Detecting
14:02:06.931 ->
14:02:06.931 -> state = 0
14:02:06.931 -> pos = 3
14:02:06.931 -> buffer = AT+
14:02:06.976 -> Detecting
14:02:06.976 ->
14:02:06.976 -> state = 0
14:02:06.976 -> pos = 4
14:02:06.976 -> buffer = AT+C
14:02:06.976 -> Detecting
14:02:06.976 ->
14:02:06.976 -> state = 0
14:02:06.976 -> pos = 5
14:02:06.976 -> buffer = AT+CS
14:02:07.023 -> Detecting
14:02:07.023 ->
14:02:07.023 -> state = 0
14:02:07.023 -> pos = 6
14:02:07.023 -> buffer = AT+CSQ
14:02:07.023 -> Detecting
14:02:07.023 ->
14:02:07.023 -> state = 1
14:02:07.023 -> pos = 7
14:02:07.070 -> buffer = AT+CSQ

14:02:07.070 -> Ignoring echoCSQ: AT+CSQ

14:02:07.070 ->
14:02:07.070 -> state = 0
14:02:07.070 -> pos = 1
14:02:07.070 -> buffer =

14:02:07.070 -> Detecting
14:02:07.115 ->
14:02:07.115 -> state = 0
14:02:07.115 -> pos = 2
14:02:07.115 -> buffer =
14:02:07.115 ->
14:02:07.115 -> Detecting
14:02:07.115 ->
14:02:07.115 -> state = 0
14:02:07.115 -> pos = 1
14:02:07.115 -> buffer = +
14:02:07.161 -> Detecting
14:02:07.161 ->
14:02:07.161 -> state = 0
14:02:07.161 -> pos = 2
14:02:07.161 -> buffer = +C
14:02:07.161 -> Detecting
14:02:07.161 ->
14:02:07.161 -> state = 0
14:02:07.161 -> pos = 3
14:02:07.161 -> buffer = +CS
14:02:07.207 -> Detecting
14:02:07.207 ->
14:02:07.207 -> state = 0
14:02:07.207 -> pos = 4
14:02:07.207 -> buffer = +CSQ
14:02:07.207 -> Detecting
14:02:07.207 ->
14:02:07.207 -> state = 0
14:02:07.207 -> pos = 5
14:02:07.207 -> buffer = +CSQ:
14:02:07.253 -> Detecting
14:02:07.253 ->
14:02:07.253 -> state = 2
14:02:07.253 -> pos = 1
14:02:07.253 -> buffer =
14:02:07.253 ->
14:02:07.253 -> state = 2
14:02:07.253 -> pos = 2
14:02:07.253 -> buffer = 1
14:02:07.298 ->
14:02:07.298 -> state = 2
14:02:07.298 -> pos = 3
14:02:07.298 -> buffer = 10
14:02:07.298 ->
14:02:07.298 -> state = 2
14:02:07.298 -> pos = 4
14:02:07.298 -> buffer = 10,
14:02:07.298 -> The reciecved signal is: 10,
14:02:07.344 -> we can go
14:02:07.344 ->
14:02:07.344 -> state = 3
14:02:07.344 -> pos = 1
14:02:07.344 -> buffer = 9
14:02:07.344 ->
14:02:07.344 -> state = 3
14:02:07.344 -> pos = 2
14:02:07.390 -> buffer = 99
14:02:07.390 ->
14:02:07.390 -> state = 3
14:02:07.390 -> pos = 3
14:02:07.390 -> buffer = 99

14:02:07.390 ->
14:02:07.390 -> state = 3
14:02:07.390 -> pos = 4
14:02:07.390 -> buffer = 99
14:02:07.390 ->
14:02:07.437 -> In the nextworkwithit:99
14:02:07.437 ->
14:02:07.437 -> signal found;
14:02:07.437 ->

You see this singal found, it shouldn't be there!!!!
The buffer contained 99 at Pos=2 just like the condition at the if statement

Can anyone tell what's wrong here?

Also, i tried replacing the strcmp(buffer, "99") == 0 with things like saving the buffer into a const char and then compare that char to the 99, For example:

 case nextworkwithit:
    if (b == '\n')
    {
      Serial.print("In the nextworkwithit:");
      Serial.println(buffer);
      const char *toconcider = buffer;
      Serial.print("the toconcider is:");
      Serial.println(toconcider);
      if (toconcider == '99')
      {
        Serial.println("state = nosignalfound;");
        // state = nosignalfound;
      }
      else
      {
        Serial.println("state = signalfound;");
        // state = signalfound;
      }
    }
  }

i still had the same problem

Just serial print state and start right before the if statement. There doesn’t seem to be enough code for us to work out the values

My problem is right here

as you can see, these outputs match this condition

and yet the program is skipping it and going to the else statement right away

My guess would be that the condition (b == '\n') does not hold. Can you also print this value to your debug log?

Where did the new line come from? Is it in buffer say "99\n" ?

It does, or else this wouldn't be here

buffer is only printing this

I think it should have \n
is there anyway to show that ?

Also i tried changing the code to this:

 case nextworkwithit:
      if (b == '\n')
      {
        Serial.print("In the nextworkwithit:");
        Serial.println(buffer);
        if (pos == 2 && strcmp(buffer, "99\n") == 0)
        {
          Serial.println("SIGNAL NOT FOUND");
          // state = nosignalfound;
        }
        else
        {
          Serial.println("signal found;");
          // state = signalfound;
        }
      }

still same

try:

 if (pos == 2 && strncmp(buffer, "99", 2) == 0)  // strncmp

Which indeed seems to be missing in that iteration.

I see what you mentioned here,

I modified the code with @6v6gt comment

too

So here is the combined one,

 case nextworkwithit:
      Serial.print("In the nextworkwithit:");
      Serial.println(buffer);
      if (pos == 2 && strncmp(buffer, "99", 2) == 0)  // strncmp
      {
        Serial.println("SIGNAL NOT FOUND");
        resetBuffer();
        // state = nosignalfound;
        state = nothing;
      }
      else if (pos == 2 && strncmp(buffer, "99", 2) != 0)  // strncmp
      {
        resetBuffer();
        Serial.println("signal found;");
        // state = signalfound;
      }

My concern now is that both functions are being called, and later i want to act upon one condition only

see the serial output:
17:06:16.281 -> state = 3
17:06:16.281 -> pos = 1
17:06:16.281 -> buffer = 9
17:06:16.281 -> In the nextworkwithit:9
17:06:16.281 ->
17:06:16.281 -> state = 3
17:06:16.327 -> pos = 2
17:06:16.327 -> buffer = 99
17:06:16.327 -> In the nextworkwithit:99
17:06:16.327 -> SIGNAL NOT FOUND
17:06:16.327 ->
17:06:16.327 -> state = 3
17:06:16.327 -> pos = 1
17:06:16.327 -> buffer =

17:06:16.373 -> In the nextworkwithit:

17:06:16.373 ->
17:06:16.373 -> state = 3
17:06:16.373 -> pos = 2
17:06:16.373 -> buffer =
17:06:16.373 ->
17:06:16.373 -> In the nextworkwithit:
17:06:16.420 ->
17:06:16.420 -> signal found;
17:06:16.420 ->
17:06:16.420 -> state = 3
17:06:16.420 -> pos = 1
17:06:16.420 -> buffer =

17:06:16.420 -> In the nextworkwithit:

17:06:16.420 ->
17:06:16.420 -> state = 3
17:06:16.467 -> pos = 2
17:06:16.467 -> buffer =
17:06:16.467 ->
17:06:16.467 -> In the nextworkwithit:
17:06:16.467 ->
17:06:16.467 -> signal found;
17:06:16.467 ->
17:06:16.467 -> state = 3
17:06:16.467 -> pos = 1
17:06:16.467 -> buffer = O
17:06:16.513 -> In the nextworkwithit:O
17:06:16.513 ->
17:06:16.513 -> state = 3
17:06:16.513 -> pos = 2
17:06:16.513 -> buffer = OK
17:06:16.513 -> In the nextworkwithit:OK
17:06:16.560 -> signal found;
17:06:16.560 ->
17:06:16.560 -> state = 3
17:06:16.560 -> pos = 1
17:06:16.560 -> buffer =

17:06:16.560 -> In the nextworkwithit:

17:06:16.560 ->
17:06:16.560 -> state = 3
17:06:16.606 -> pos = 2
17:06:16.606 -> buffer =
17:06:16.606 ->
17:06:16.606 -> In the nextworkwithit:
17:06:16.606 ->
17:06:16.606 -> signal found;
17:06:16.606 -> GOOD JOB
17:06:16.606 -> GOOD JOB
17:06:16.606 -> GOOD JOB
17:06:16.653 -> GOOD JOB

these GOODJOB outputs are coming from state = nothing, i put it up in the loop

but what concerns mee now is that i still get this

Okay settled already, apparently, i just had to add this line only:
parsechecking = todetectmessge;
because the buffer kept sending data and i had to do something with it

Any way, thanks to all for helping
I will post a summary of solution next comment

It is important to analyse the whole feedback coming from the module before designing a parsing function,

The solution to my issue was this:

#include <SoftwareSerial.h>
SoftwareSerial MYGSM(7, 8); // Define virtual serial port name as MYGSM,Rx is port 7, Tx is port 8

//PARSING MACHINE WITH DIFFERENT STATES
enum parsechecking 
{
  todetectmessge,
  toignore,
  workwithit,
  nextworkwithit
};

byte parsechecking = todetectmessge; //START HERE

char buffer[256];                     // buffer of character
byte pos = 0; //the current position

uint8_t state; //machine inside the loop to send the command once
const uint8_t START = 0;
const uint8_t tochecknetwork = 1;
const uint8_t nothing = 2;


void resetBuffer()
{
  memset(buffer, 0, sizeof(buffer));
  pos = 0;
}




void setup()
{
  MYGSM.begin(19200);
  Serial.begin(19200);
}

void loop()
{
  if (state == START)
  {
    Serial.println("we just sent the CSQ");
    MYGSM.println("AT+CSQ");
    //this command is sent to the module to check the connection
    //it return a vule in this form: +CSQ: xx,xx
    // so basically if it's 99,xx OR xx,99 i want to switch to offline
    //because the connection was not established

    state = tochecknetwork;
    Serial.println("WE are reading ");
  }

  else if (state == tochecknetwork)
  {

    while (MYGSM.available())
    {
      const char *checked = MYGSM.read();
      checkparsename(checked); //take the reading from it and parse it
    }
  }
  

  else if (state == nothing) {
    Serial.println("GOOD JOB");
  }



}


void checkparsename(byte b)
{

  buffer[pos++] = b;
  if (pos >= sizeof(buffer))
    resetBuffer(); // just to be safe


  // Detailed debugging
  Serial.println();
  Serial.print("state = ");
  Serial.println(parsechecking);
  Serial.print("pos = ");
  Serial.println(pos);
  Serial.print("buffer = ");
  Serial.println(buffer);

  switch (parsechecking)
  {
    case todetectmessge:
      Serial.println("Detecting");
      if (b == '\n')
        resetBuffer();

      if (pos == 6 && strcmp(buffer, "AT+CSQ") == 0) //this is what was sent
      {
        parsechecking = toignore;
      }

      if (pos == 5 && strcmp(buffer, "+CSQ:") == 0)//this is the responce from the module
      {
        resetBuffer();
        parsechecking = workwithit;
      }

      break;

    case toignore:
      Serial.print("Ignoring echoCSQ:  ");
      Serial.println(buffer);
      resetBuffer();
      parsechecking = todetectmessge;
      break;

    case workwithit:
      if (b == ',')
      {
        Serial.print("The reciecved signal is:");
        Serial.println(buffer);
        if (pos == 4 && strcmp(buffer, " 99,") == 0)
        {
          Serial.println("it's 99");
          // state = nosignalfound;
          resetBuffer();
          parsechecking = nextworkwithit;
        }
        else
        {
          Serial.println("we can go");
          resetBuffer();
          parsechecking = nextworkwithit;
          // state = signalfound;
        }
      }
      break;

    case nextworkwithit:

      Serial.print("In the nextworkwithit:");
      Serial.println(buffer);
      if (pos == 2 && strncmp(buffer, "99", 2) == 0)  // strncmp
      {
        
        resetBuffer();
        // state = nosignalfound;
        parsechecking = todetectmessge; 
//since the buffer might still have data coming, 
//i need to analyse them and hence sending it back to the initial stage to detect the type
        state = nothing; 
        Serial.println("SIGNAL NOT FOUND");
      }
      if (pos == 2 && strncmp(buffer, "99", 2) != 0)  // strncmp
      {
        resetBuffer();
        Serial.println("signal found;");
        // state = signalfound;
      }
  }
}



Just for your future reference, in order to avoid these scenarios, when printing data I would suggest encapsulating the values.
For example, like this:

Serial.printf("buffer = '%s'\n", buffer);

or

Serial.printf("buffer = {%s}\n", buffer);

Whatever you like.

This way, you could catch much earlier that extra new-line character in your buffer :slight_smile:

1 Like

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