If only runs once

I have a sketch that receives "stb" from another arduino Nano over Serial when a button is pressed. It seems to send OK repeatedly and is received and displayed on the Serial Monitor. It then satisfies an if statement but only once. It appears to continue to receive the same transmission but it will only satisfy the if statement once.

My intention is for it to run the if statement each time the transmission is received which would then in turn pull a gpio pin HIGH. The pin needs to go LOW after the transmission ceases as well.

Why won't it run through the if statement again? I'm guessing the contents of the variable have changed, maybe? Kind of stumped here.

Thanks for helping. I tried to use code tags, unsure if it is correct.

const byte numChars = 32;
char acbIn[numChars];   // an array to store the received data
boolean newData = false;
char receivedChars[numChars];   // an array to store the received data
char stb[] = "stb";

void setup() {
  // Begin the Serial at 9600 Baud
  Serial.begin(9600);
    Serial.println(__FILE__);
}

void loop() {
  recvWithEndMarker();
  showNewData();
  
  // Manual Steering Input from ACB Base Module
      if(strcmp (acbIn, stb) == 0) {
        Serial.print("received from ACB Base:  ");  Serial.println(acbIn);
        delay(1000);
        Serial.print("                   acbIn is now:  ");  Serial.println(acbIn);
      }
}

void recvWithEndMarker() {
    static byte ndx = 0;      // start with the first element in the array
    char endMarker = '\n';
    char rc;
    
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            // receivedChars[ndx] = rc;
            acbIn[ndx] = rc;            
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            // receivedChars[ndx] = '\0'; // terminate the string
            acbIn[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }

  void showNewData() {
    if (newData == true) {
        Serial.print("This just in ... ");
        Serial.println(acbIn);
        // Serial.println(receivedChars);
        newData = false;
        while (Serial.available() > 0) {    // this clears the Serial input buffer
          Serial.read();
        }

We could follow your code better if it’s posted properly.

Are you really using a 9V PP3 batttery ?

Hello, do yourself a favour and please read How to get the best out of this forum and modify your post accordingly (including code tags and necessary documentation for your ask).

did you print("stb") or println("stb") on the Tx nano ?

println() adds both \r and \n so you won't get an exact match with "stb" if your Rx buffer is "stb\r"

with your reading code the sender should do print("stb\n")


please keep the forum tidy and fix the look of your first post by adding the code tags where necessary

because newData is never reset to false

look this over

void loop ()
{
    if (Serial.available ())  {
        char buf [80];
        int  n = Serial.readBytesUntil ('\n', buf, sizeof(buf)-1);
        buf [n] = '\0';

        if (strcmp (buf, "stb") == 0) {
            Serial.print ("received from ACB Base: ");
            Serial.println (buf);
        }
    }
}

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

Thank you JML, I changed the Sending sketch to " Serial.print("stb\n") ;" as you suggested and now it works. I couldn't understand (still don't) why it would satisfy the if statement the first time but not after that.

Anyway it works now so thanks again.

Jim

That’s because your code is buggy :slight_smile: it will still catch a match the first time if you send stbbbb\n for example

You have a string compare in the loop that is applied at every loop, regardless if the message is ready or not.

A strcmp() requires that the buffer you pass to be null terminated which is only done in your receive function when you get the \n.

The buffer abcIn is a global array and as such is initialized with 0 in every position. so during the first run as you fill in for the first time the array, the loop checksif s matches stb (no) then if st matches stb (no) and then you have received the first letters s t and b the next character in memory is null and so the if strcmp() says it’s a match.

But then you receive the \r and it’s no longer a match and then you receive the \n which sets a null char in the buffer and sets newData to true and the index for storing the next byte you’ll receive is reset to 0.

At that point your buffer holds stb\r followed by a null

(You have not posted the showNewData function but the function gets called and should reset the newData flag).

Then the cycle starts again, say you receive a X which is put in the buffer at index 0 and your loop checks again the compare will see in memory Xtb\r followed by a null.

See the rest of the string is still in memory, it has not been cleaned up and reset to all 0. The trailing null is only added when you get the \n.

So from now on your if in the loop will use whatever null char happend to have been set by a previous receive to compare the string and because of the \r you were failing.

Long story short You can’t do this in the loop

Unless you check first that newData is set - which is ultimately the goal of the function showNewData().

Makes more sense?

Yes, thank you, that makes a lot more sense. Also, I apologize, I didn't realize I left out the showNewData() function. I have added it to the original post. I have a hard time visualizing what is stored in the buffer. It seemed like a good idea to clear it out each cycle.

I'm learning but it's a process.

Good
Stay focused and have fun !