append String object, global vs local

I want to append text received from different channel of serial port. just as a trial, (not yet including the mux and stuff) i try a simple text append. the code is below.

#define NumOchan 8
#define trimStart 0
#define trimEnd 2
#define texLen 20

byte i=0;
byte chan =0;
char joinChar[texLen];
String strOut;

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

void loop()
{
  strOut = String("blah "); //empty main string container
  while(chan < NumOchan){
    while(Serial.available()){
      char inChar = Serial.read();   //receive char stream from serial
      if(trimStart<=i){ //select wanted text
        joinChar[i-trimStart]=inChar;
      }
      i++;
      if(inChar==10){ //reached LF, remove tail
        for (byte j=i-trimStart-trimEnd; j<=texLen; j++){
          joinChar[j]= 0;
        }
        String strJoin = String(joinChar);
        Serial.println(strJoin);
        for(i=0; i<=texLen; i++){ //clear joinChar
          joinChar[i]=0;
        }
        String strBuf = strOut; // copy to buffer
        strOut = strBuf + strJoin +","; //append text
        Serial.println(strOut); //test if its properly appended
        i=0; //reset char counter to 0
        chan++;
      }
    }
  }
  //all channel read, output and reset ch counter to 0
  Serial.println(strOut);
  chan =0;
}

it doesn’t perform as expected.
then i move the string declaration from top to the inside of void loop. then it works as expected. Can someone explain to me why?
I also had to copy strOut to another string container (strBuf here) before appending the next data. So the operator += just simply doesn’t work for string?

oh, i send the word using both CR and LF, and detect LF as the word end. any smarter method?

then i move the string declaration from top to the inside of void loop. then it works as expected

Care to share what "as expected" means to you here?

when it was declared outside void, i meant it to be global variable, it appended the text i send thru serial with gibberish letter, and it works only until the third word i sent. none of them appended properly. the 4th and next gave no respond at all, just like a computer in crash.

as expected means it appended the text properly, without gibberish letter, and without hang. after the 8th word was sent, it was able to repeat the cycle. just as how i intented the sketch to be. in short, problem solved. But i just dont understand the logic behind.

when it was declared outside void, i meant it to be global variable

What does "it" refer to?

There is no "outside void". There is a function, called loop() whose return type is void. If it's return type was int, you would say "when it was declared outside int..." would you?

it appended the text i send thru serial with gibberish letter

I'm pretty sure that the Arduino doesn't understand gibberish any more than we do. There's that "it" again, with no clue as to what "it" is.

You can use Serial.print() to print the arrays and Strings at any time. Of course, if you are stuffing characters in an array, and expecting to use that array as a string (lower case s), you must keep the array of characters NULL terminated, which you aren't bothering to.

ooh, sorry. haha as always i’m having a hard time expressing my mind.

i mean the 9th line of my code.

String strOut;

i moved it to inside void loop{} then the program works.

#define NumOchan 8
#define trimStart 0
#define trimEnd 2
#define texLen 20

byte i=0;
byte chan =0;
char joinChar[texLen];
String strOut;

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

void loop()
{
  strOut = String("blah "); //empty main string container

becomes

#define NumOchan 8
#define trimStart 0
#define trimEnd 2
#define texLen 20

byte i=0;
byte chan =0;
char joinChar[texLen];

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

void loop()
{
  String strOut = String("blah "); //empty main string container

as for the second “it”, i mean arduino, or the result that i receive from the serial monitor.

Of course, if you are stuffing characters in an array, and expecting to use that array as a string (lower case s), you must keep the array of characters NULL terminated, which you aren’t bothering to.

oh really? i thought i did.

      if(inChar==10){ //reached LF, remove tail
        for (byte j=i-trimStart-trimEnd; j<=texLen; j++){
          joinChar[j]= 0;
        }

i filled the rest of the array joinChar[j] with null. also to remove CR LF.

oh really? i thought i did.

I prefer to add a NULL after each character is added to the array. That way, at all times the array is NULL terminated. And, one NULL is sufficient. Filling the rest of the array with NULLs is a waste of effort.

  //all channel read, output and reset ch counter to 0
  Serial.println(strOut);
  chan =0;
}

This comment is wrong, and the action taken is also wrong. You are assuming that all the serial data has arrived for all channels before you start reading anything. Lousy assumption.

And, one NULL is sufficient. Filling the rest of the array with NULLs is a waste of effort.

i see. noted.

You are assuming that all the serial data has arrived for all channels before you start reading anything.Lousy assumption.

oh, how is that?
i defined the counter chan to be zero at first. the while(chan <= 7) wont exit until the counter chan go past 7. And the counter wont go up until there is any LF string received.

btw, that was not the question here. the same sketch, with all the lousy assumption works just fine, as long as i move the code
String strOut;
from the ninth line to inside void loop{}
so what lousier assumption did i make?

i defined the counter chan to be zero at first. the while(chan <= 7) wont exit until the counter chan go past 7.

My apologies. I missed that.

How about if you show some sample output when strOut is a global variable?

  strOut = String("blah "); //empty main string container

What happens if you simply assign "blah " to strOut, without converting it to a String object first? Perhaps the copy operator is causing your issues.

What happens if you simply assign "blah " to strOut, without converting it to a String object first?

the same. i didn’t think that the problem was setting strOut as global variable, so i added the String("blah ") just to test.

The first attached, is how i want the sketch to perform. Done by putting String strOut = … inside void loop{}

The second attached is what happen when i put strOut as global variable. I sent up to abc8 just as the first. But this is what i got instead.

Image_000018.jpg

Image_000019.jpg

Seems like there's no explanation :disappointed_relieved: Then, I'll just take note that the object String should never be declared as a global variable, just because...