"if Serial.available" inside another "if serial available"

Hello
I've written a program where the arduino DUE recieves serial data, reads an analog pin and then sends what it read back into the serial. This program works perfectly:

int ThisStationNumber = 01;                                                                             //Example Station Number.

void setup(){
 Serial.begin(9600);
   char number1[2] = {0,0};                                                                             //Resets
   char number2[2] = {0,0};
   char number3[2] = {0,0};
   char number4[2] = {0,0};
   analogReadResolution(12);                                                                            //Changes the resolution from 10bits to 12bits. CAUTION: WONT WORK WITH OTHER ARDUINOS BUT DUES
  }

void loop(){
     if (Serial.available() >= 9){                                                                          //Reads buffer only when there's 9 or more bits stored.
       char number1[2] = { Serial.read(), Serial.read() };
       char number2[2] = { Serial.read(), Serial.read() };
       char number3[2] = { Serial.read(), Serial.read() };
       char number4[2] = { Serial.read(), Serial.read() };
       int barraene = Serial.read();
       int CommandToStation = atoi(number1), StationNumber = atoi(number2), Instruction = atoi(number3), Channel = atoi(number4);

                      
                      if (CommandToStation == 00) {                                                      //Verifies if package starts with Command To Station
                            if (StationNumber == ThisStationNumber){                                     //Verifies if Station Numbers match
                                switch (Instruction){                                                    //Verifies witch instruction to follow
                                    case 0x0:
                                          break;
                                    case 0x1:
                                          break;      
                                    case 0x2:
                                          break;
                                    case 0x3:
                                          break;
                                    case 0x4:
                                          break;
                                    case 0x5:
                                          break;
                                    case 0x6:{
                                          
                                          int sensor = analogRead(Channel);                             //Reads AD pin
                                          int Voltage = map(sensor, 0, 4095, 0, 3300);                  //Converts the read voltlage, from 0 - 4095 to 0 3300 (max voltage 3.3 on due)
                                          char SVoltage[4];
                                          itoa(Voltage, SVoltage, 10);
                                          char answer[7] {'0','1',SVoltage[0],SVoltage[1],SVoltage[2],SVoltage[3],'\n'};
                                          Serial.write(answer);
                                          }   
                                          break;
                                    case 0x7:
                                          break;
                                    case 0x8:
                                          break;
                                    case 0x9:
                                          break;
                                    case 0xA:
                                          break;
                                    case 0xB:
                                          break;
                                    case 0xC:
                                          break;
                                    case 0xD:
                                          break;
                                    case 0xE:
                                          break;
                                    case 0xF:
                                          break;
                                    case 0x10:
                                          break;
                                    case 0x12:
                                          break;
                                    case 0x13:
                                          break;
                                    case 0x14:
                                          break;
                                    case 0x15:
                                          break;
                                    case 0x16:
                                          break;
                                    case 0x17:
                                          break;
                                    case 0x18:
                                          break;
                                    case 0x19:
                                          break;
                                    case 0x1A:
                                          break;
                                    case 0x1B:
                                          break;
                                } 
                            }
                      }
     }
}

If it recieves "00010601\n" it will go to case 6, read the analog pin 01 and then answer.

Problem is, I need to separate that "if (Serial.available() >= 9)" into different smaller "serial.availables". As you can see, there are many cases I haven't completed, but some of them will receive more than the 9 bits required for the case 6, so i'm trying to separate eatch "serial.available" inside it's own case. Something like this:

int ThisStationNumber = 01;                                                                             //Example Station Number.

void setup(){
 Serial.begin(9600);
   char number1[2] = {0,0};                                                                             //Resets
   char number2[2] = {0,0};
   char number3[2] = {0,0};
   char number4[2] = {0,0};
   analogReadResolution(12);                                                                            //Changes the resolution from 10bits to 12bits. CAUTION: WONT WORK ON THE OTHER ARDUINOS BUT DUES
}

void loop(){
 if (Serial.available() >= 2){                                                                          //Reads buffer only when there's 9 or more bits stored.
   char number1[2] = { Serial.read(), Serial.read() };
   int CommandToStation = atoi(number1);

                      
                      if (CommandToStation == 00) {                                                      //Verifies if package starts with Command To Station                        
                         if (Serial.available() >= 2){
                            char number2[2] = { Serial.read(), Serial.read() };
                            int StationNumber = atoi(number2);
                            
                            if (StationNumber == ThisStationNumber){                                     //Verifies if Station Numbers match                           
                            if (Serial.available() >= 2){       
                                char number3[2] = { Serial.read(), Serial.read() };
                                int Instruction = atoi(number3);
                                
                                switch (Instruction){                                                    //Verifies witch instruction to follow
                                    case 0x0:
                                          break;
                                    case 0x1:
                                          break;      
                                    case 0x2:
                                          break;
                                    case 0x3:
                                          break;
                                    case 0x4:
                                          break;
                                    case 0x5:
                                          break;
                                    case 0x6:{
                                          if (Serial.available() >= 3){    
                                          char number4[2] = { Serial.read(), Serial.read() };
                                          int barraene = Serial.read();
                                          int Channel = atoi(number4);
                                          
                                          int sensor = analogRead(Channel);                             //Reads AD pin
                                          int Voltage = map(sensor, 0, 4095, 0, 3300);                  //Converts the read voltlage, from 0 - 4095 to 0 3300 (max voltage 3.3 on due)
                                          char SVoltage[4];
                                          itoa(Voltage, SVoltage, 10);
                                          char answer[7] {'0','1',SVoltage[0],SVoltage[1],SVoltage[2],SVoltage[3],'\n'};
                                          Serial.write(answer);
                                          }
                                          }   
                                          break;
                                    case 0x7:
                                          break;
                                    case 0x8:
                                          break;
                                    case 0x9:
                                          break;
                                    case 0xA:
                                          break;
                                    case 0xB:
                                          break;
                                    case 0xC:
                                          break;
                                    case 0xD:
                                          break;
                                    case 0xE:
                                          break;
                                    case 0xF:
                                          break;
                                    case 0x10:
                                          break;
                                    case 0x12:
                                          break;
                                    case 0x13:
                                          break;
                                    case 0x14:
                                          break;
                                    case 0x15:
                                          break;
                                    case 0x16:
                                          break;
                                    case 0x17:
                                          break;
                                    case 0x18:
                                          break;
                                    case 0x19:
                                          break;
                                    case 0x1A:
                                          break;
                                    case 0x1B:
                                          break;

                                } 
                            }
                      }
                    }
                  }
 }
}

but this second code won't work :frowning:
the arduino just doesnt answer at all.

Would you be able to read all of the Serial data and then decide what to do with it? Also, you can allow case statements to "fall through" if you wish:

                                switch (Instruction){        //Verifies witch instruction to follow
                                    case 0x0:
                                    case 0x1:
                                    case 0x2:
                                    case 0x3:
                                    case 0x4:
                                    case 0x5:      // Now 0 - 5 will break
                                        break;

                                    case 0x6:{
                                          if (Serial.available() >= 3){

This:

  char number1[2] = { Serial.read(), Serial.read() };

don't do what you think it do. It's just a piece of garbage.

what you should do is:

   char number1[2];
   number1[0] = Serial.read();
   number1[1] = Serial.read();

as you need a terminated string to make the conversion in the atoi() function, you need to add an extra (null) character at the end. So the las example will turn in:

   char number1[3];
   number1[0] = Serial.read();
   number1[1] = Serial.read();
   number1[2] = '\0';
   char number1[2] = {0,0};                                                                             //Resets
   char number2[2] = {0,0};
   char number3[2] = {0,0};
   char number4[2] = {0,0};

These local variables go out of scope immediately. They are, therefore, useless. Get rid of them.

if (Serial.available() >= 2){                                                                          //Reads buffer only when there's 9 or more bits stored.
   char number1[2] = { Serial.read(), Serial.read() };
   int CommandToStation = atoi(number1);

number1 is NOT a string. Do not pass it to a function that expects a string.

                     if (CommandToStation == 00) {                                                      //Verifies if package starts with Command To Station                        
                         if (Serial.available() >= 2){

If you need to wait for data, wait. Do not assume that there is data.

but this second code won't work

Nonsense. The code is working perfectly. That it does not do what you expect says more about your expectations than about the code.

Implementing what I suggest in the reply #3, I end with this:

int ThisStationNumber = 01;                                                                             //Example Station Number.

void setup(){
  Serial.begin(9600);
  //analogReadResolution(12);                                                                            //Changes the resolution from 10bits to 12bits. CAUTION: WONT WORK ON THE OTHER ARDUINOS BUT DUES
}

void loop(){
  if (Serial.available() != 0){                                                                          //Reads buffer only when there's 9 or more bits stored.
    Serial.print("Serial.available(): ");
    Serial.println(Serial.available());
  }
  
  if (Serial.available() >= 2){                                                                          //Reads buffer only when there's 9 or more bits stored.
    char number1[3];
    number1[0] = Serial.read();
    number1[1] = Serial.read();
    number1[2] = '\0';
    int CommandToStation = atoi(number1);
    Serial.print("CommandToStation: ");
    Serial.println(CommandToStation);


    if (CommandToStation == 0) {          //Verifies if package starts with Command To Station                       
      Serial.print("Serial.available(): ");
      Serial.println(Serial.available());
      if (Serial.available() >= 2){
        char number2[3];
        number2[0] = Serial.read();
        number2[1] = Serial.read();
        number2[2] = '\0';
        int StationNumber = atoi(number2);
        Serial.print("StationNumber: ");
        Serial.println(StationNumber);

        if (StationNumber == ThisStationNumber){                                     //Verifies if Station Numbers match                           
          Serial.print("Serial.available(): ");
          Serial.println(Serial.available());
          if (Serial.available() >= 2){       
            char number3[3];
            number3[0] = Serial.read();
            number3[1] = Serial.read();
            number3[2] = '\0';
            int Instruction = atoi(number3);
            Serial.print("Instruction: ");
            Serial.println(Instruction);

            switch (Instruction){                                                    //Verifies witch instruction to follow
            case 0x0:
              break;
            case 0x1:
              break;     
            case 0x2:
              break;
            case 0x3:
              break;
            case 0x4:
              break;
            case 0x5:
              break;
            case 0x6:
              {
                Serial.print("Serial.available(): ");
                Serial.println(Serial.available());
                if (Serial.available() >= 3){   
                  char number4[3];
                  number4[0] = Serial.read();
                  number4[1] = Serial.read();
                  number4[2] = '\0';
                  int barraene = Serial.read();
                  int Channel = atoi(number4);

                  Serial.print("Channel: ");
                  Serial.println(Channel);

                  Serial.print("barraene: ");
                  Serial.write(barraene);
                  Serial.println();
                  Serial.println("END OF DECODING MESSAGE...");

                  int sensor = analogRead(Channel);                             //Reads AD pin
                  int Voltage = map(sensor, 0, 4095, 0, 3300);                  //Converts the read voltlage, from 0 - 4095 to 0 3300 (max voltage 3.3 on due)
                  char SVoltage[4];
                  itoa(Voltage, SVoltage, 10);
                  char answer[7] {
                    '0','1',SVoltage[0],SVoltage[1],SVoltage[2],SVoltage[3],'\n'                                                                        };
                  Serial.write(answer);
                  //000106011
                }
              }   
              break;
            case 0x7:
              break;
            case 0x8:
              break;
            case 0x9:
              break;
            case 0xA:
              break;
            case 0xB:
              break;
            case 0xC:
              break;
            case 0xD:
              break;
            case 0xE:
              break;
            case 0xF:
              break;
            case 0x10:
              break;
            case 0x12:
              break;
            case 0x13:
              break;
            case 0x14:
              break;
            case 0x15:
              break;
            case 0x16:
              break;
            case 0x17:
              break;
            case 0x18:
              break;
            case 0x19:
              break;
            case 0x1A:
              break;
            case 0x1B:
              break;

            }
          }
        }
      }
    }
  }
}

I add too a few debugging lines. For the incoming message "000106011" I receive in the Serial monitor:

Serial.available(): 1
Serial.available(): 1
Serial.available(): 2
CommandToStation: 0
Serial.available(): 7
StationNumber: 1
Serial.available(): 5
Instruction: 6
Serial.available(): 3
Channel: 1
barraene: 1
END OF DECODING MESSAGE...
01432

BTW, this point

PaulS:
(...)
If you need to wait for data, wait. Do not assume that there is data.
(...)

is very important too.

Okay, I made what luisilva said on reply#3 and got this:

int ThisStationNumber = 01;                                                                             //Example Station Number.

void setup(){
 Serial.begin(9600);
   analogReadResolution(12);                                                                            //Changes the resolution from 10bits to 12bits. CAUTION: WONT WORK ON OTHER ARDUINOS BUT DUES
}

void loop(){
 if (Serial.available() >= 2){                                                                          //Reads buffer only when there's 9 or more bits stored.
   char number1[3];
   number1[0] = Serial.read();
   number1[1] = Serial.read();
   number1[2] = '\0';
   int CommandToStation = atoi(number1);

                      
                      if (CommandToStation == 00) {                                                      //Verifies if package starts with Command To Station                        
                         if (Serial.available() >= 2){
                            char number2[3];
                            number2[0] = Serial.read();
                            number2[1] = Serial.read();
                            number2[2] = '\0';
                            int StationNumber = atoi(number2);
                            
                            if (StationNumber == ThisStationNumber){                                     //Verifies if Station Numbers match                           
                            if (Serial.available() >= 2){       
                                char number3[3];
                                number3[0] = Serial.read();
                                number3[1] = Serial.read();
                                number3[2] = '\0';
                                int Instruction = atoi(number3);
                                
                                switch (Instruction){                                                    //Verifies witch instruction to follow
                                    case 0x0:
                                          break;
                                    case 0x1:
                                          break;      
                                    case 0x2:
                                          break;
                                    case 0x3:
                                          break;
                                    case 0x4:
                                          break;
                                    case 0x5:
                                          break;
                                    case 0x6:{
                                          if (Serial.available() >= 3){    
                                          char number4[3];
                                          number4[0] = Serial.read();
                                          number4[1] = Serial.read();
                                          number4[2] = '\0';
                                          int barraene = Serial.read();
                                          int Channel = atoi(number4);
                                          
                                          int sensor = analogRead(Channel);                             //Reads AD pin
                                          int Voltage = map(sensor, 0, 4095, 0, 3300);                  //Converts the read voltlage, from 0 - 4095 to 0 3300 (max voltage 3.3 on due)
                                          char SVoltage[4];
                                          itoa(Voltage, SVoltage, 10);
                                          char answer[7] {'0','1',SVoltage[0],SVoltage[1],SVoltage[2],SVoltage[3],'\n'};
                                          Serial.write(answer);
                                          }
                                          }   
                                          break;
                                    case 0x7:
                                          break;
                                    case 0x8:
                                          break;
                                    case 0x9:
                                          break;
                                    case 0xA:
                                          break;
                                    case 0xB:
                                          break;
                                    case 0xC:
                                          break;
                                    case 0xD:
                                          break;
                                    case 0xE:
                                          break;
                                    case 0xF:
                                          break;
                                    case 0x10:
                                          break;
                                    case 0x12:
                                          break;
                                    case 0x13:
                                          break;
                                    case 0x14:
                                          break;
                                    case 0x15:
                                          break;
                                    case 0x16:
                                          break;
                                    case 0x17:
                                          break;
                                    case 0x18:
                                          break;
                                    case 0x19:
                                          break;
                                    case 0x1A:
                                          break;
                                    case 0x1B:
                                          break;

                                } 
                            }
                      }
                    }
                  }
 }
}

But still, no answer from the arduino.

I tried luisilva's #5 reply code, and this one works, but I don't know why his does and mine doesn't. If I erase this part of his code, it stops working too.

if (Serial.available() != 0){                                                                          //Reads buffer only when there's 9 or more bits stored.
    Serial.print("Serial.available(): ");
    Serial.println(Serial.available());
  }

I tried adding an "if (Serial.available() != 0);" in the beggining of my loop, out of curiosity, but still no answer.

btw, what do you mean? I thought a "if (Serial.available () >=2)" would be enough to wait for de data.

PaulS:
If you need to wait for data, wait. Do not assume that there is data.

EDIT:
By adding to the beggining of my loop a

  if (Serial.available() != 0){                                                                          //Reads buffer only when there's 9 or more bits stored.
    delay(10);
  }

it works :slight_smile:

But still, why do I need this?

I think the correct way will be to replace the first:

 if (Serial.available() >= 2){                                                                          //Reads buffer only when there's 9 or more bits stored.

by:

 if (Serial.available() >= 9){                                                                          //Reads buffer only when there's 9 or more bits stored.

Actually is that what you're saying in the comment.

The problem is, some cases will receive more than 9 bits, others less, so I can't work with a static value.
Maybe the best solution is to have that delay.

Try the appropriate example from serial input basics - simple and reliable.

Just receive all the data and subsequently figure out what is in it.

...R

If the serial data is always terminated by a newline, as in "00010601\n", why not read the entire stream and then decide what to do:

   char msg[15];
   int charsRead;
   int length;

   if (Serial.available() > 0) {
      charsRead = Serial.readBytesUntil('\n', msg, sizeof(msg) - 1);  // read to newline or msg minus 1
      msg[charsRead] = '\0';      // Now it's a string
      length = strlen(msg);
      switch (length) {
         case 0:
         // ...and so on
      }
   }

Thank you all for your help :slight_smile:
I'll try that later, when I have the time. Btw, +1 karma for all of u

But still, why do I need this?

Because more data arrives while you are twiddling your thumbs.

If you need to read two bytes, the proper way is NOT to use delay(). Rather, use a while loop that terminates as soon as the second byte arrives.

while(Serial.available() < 2)
{
   // Do nothing
}