Serial Code works as a infinite loop in loop() but not in a function

Fluxanode

Well-known member
Passing serial data from serial1 to serial2 in an loop endlessly works fine like this;

Code:
/ the setup function runs once when you press reset or power the board
void setup() {
  Serial.begin(9600);
  while(!Serial);              //wait until serial is opened to run
  Serial1.begin(9600);
  Serial2.begin(9600);
}

// the loop function runs over and over again forever
void loop()
{
  if (Serial1.available()) {      // If anything comes in Serial1,

    Serial2.write(Serial1.read());   // read it and send it out Serial2

  }

  if (Serial2.available()) {     // If anything comes in Serial2,

    Serial1.write(Serial2.read());   // read it and send it out Serial1
  }
 
}

but when I call this as a function from the loop() like this - It doesn't send or receive

Code:
/ the setup function runs once when you press reset or power the board
void setup() {
  Serial.begin(9600);
  while(!Serial);              //wait until serial is opened to run
  Serial1.begin(9600);
  Serial2.begin(9600);
}

// the loop function runs over and over again forever
void loop()
{
 Bypass();
 
}

static void Bypass()
{
    Serial.println("in bypass function");
        delay(250);

        while(1); {
         

            if (Serial1.available()) {      // If anything comes in Serial1,

               Serial2.write(Serial1.read());   // read it and send it out Serial2

            }

            if (Serial2.available()) {          // If anything comes in Serial2,

               Serial1.write(Serial2.read());   // read it and send it out Serial1
                  }
        }

}
// End of Bypass

I actually was trying to call the bypass() in a program from a button on a digital input pin that when "on" calls the function and checks to see if the digital pin is still high using the while() but i can't get the basic code to work as a function. I included a debug statement just within the the function and it proves the function is entered but no serial data is sent or received.

Thanks for any help!
 
Last edited:
It's stuck in an infinite loop in:

Code:
while(1);

The semi-colon needs to be removed, as it breaks the statement so the guarded code is not attached to the while. It's effectively the same as if you wrote:

Code:
while(1) {};
{
            if (Serial1.available()) {   
...
}

It would never leave the while(1) statement. Depending on your compiler version, you probably got a warning about that line of code.....
 
I fixed that,that was a stupid mistake.

so I fixed that and it works. I expanded the code to what i need it to do and it still doesn't work. Can you see a reason why this would not work? It jumps in when the pin is high from this call in the loop():

Code:
    if (digitalRead(bypasspin) == HIGH) {
        Bypass();
        delay(250);
    }

and goes here just fine...

Code:
static void Bypass()
{
  Serial.println("in bypass function");
 
    while(digitalRead(bypasspin) == HIGH)
    {

        if (Serial1.available()) {          // If anything comes in Serial1,

            Serial2.write(Serial1.read());  // read it and send it out Serial2
        }


        if (Serial2.available()) {          // If anything comes in Serial2,

            Serial1.write(Serial2.read());   // read it and send it out Serial1
        }
    }

}
// End of Bypass

as before it prints the message but it won't pass the data back and forth.
 
How are you determining one way works fine, and the other doesn't, ie what indications do you get that data is passing back and forth in one way, but not the other? I see no prints, etc. to inform you of that.

Just guessing here, but what is connected to Serial1 and Serial2, and what actually "seeds" the code to start ping-ponging? If nothing is initially written to Serial1 or Serial2, neither of those will have bytes available, so neither of the if statements will do anything.
 
Would bypasspin be connected to a button perhaps? If so you've not debounced it so I'll expect Bypass to often drop out immediately due to bounces.
 
Connection are as follows, serial1 is connected to comm 1 on a computer through a rs232 ic. Serial2 is connected to a secind computer serial port the same way. I am using a switch to bring pin 3 high. Debounce should not be required. As the idea is to leave the main loop to loop in characters from each port as they are send and forward to the other port as long as the switch is on (high). If nothing is sent from one port. then nothing is echoed to the other port, if something is sent then it gets echoed. I have tested this in a separate small program and it works when using term programs on each port. connected to the serial ports on my teensy. It doesn't work when I add it into my larger program with the test of the pin state. When the pin is high it does enter the function and will exit when the pin goes low. The while loop is supposed to stay in the loop until the switch goes low. I was hoping someone could verify my code and help with suggestions.
 
Last edited:
What kind of switch is it, and what duration is it pressed for? If it is a momentary push switch, absolutely the mechanical action could cause it to chatter high/low rapidly as @MarkT suggests, so it could be a rapid high/low that drops into your bypass on high but is low and it will exit, and the delay(250) could likely absorb the rest of the signal. Is the PC constantly transmitting? If so, try removing the while from the bypass function to see if that works at least once when you press the button. Guessing here, not knowing the full operation and components in your system.
 
You may want to consider what should happen if either or both of the other computers are transmitting during intervals when the control switch is not HIGH. I have not looked into Teensy serial buffering in a while so I cannot offer clear suggestions about what to expect if the switch is LOW during the other computers' serial activities.

It may be worth considering always testing for SerialN.available(), accepting the data using SerialN.read(), and only forwarding to its peer when the control switch is HIGH. That way you can be sure that transmission is consistently "current" when transitioning from control switch LOW to control switch HIGH.

If you are interested in something a bit fancier such as ensuring that recent data is buffered while the switch is LOW, you'll need a well-defined FIFO mechanism (including setting policy for how much buffering might be required) for each direction.

One final thought: Consider using the known and understood behavior of performing a limited amount of computation/activity in each iteration of loop(). The Arduino and Teensy environments perform a fair amount of valuable support activity between repetitions of loop().
 
so I fixed that and it works. I expanded the code to what i need it to do and it still doesn't work.
The concept looks right - and this says it works as posted?

So looking at this or making a variation to match not seeing the complete would be expected to work it seems?

There is something in the 'expanded' code that is breaking it? So much unknown - is the Bypass() printing on entry - it seems so to know the switch is read right. Is there something else added taking over one of the Serial UART pins?
 
Lots of ways to improve or do it with some variation. But first step is to see it working.
Question should incoming data be allowed to age and overflow when the switch is not HIGH? Or should that data be discarded to allow reading current data on the flip of the switch?

When T_4.0 and 4.1 released with many added UART ports - they were tested in various ways linking one Tx to another Rx in loops on one board or between two boards at various baud rates to confirm that data moved in a testably reliable way across the various ports.

If the external devices are easily disconnected - a breadboard? - then connect the two UARTS Rx and Tx to each other. When the Bypass() is entered Inject a message to one or both UARTS then enter the while and watch the messages cycle - which would require some feedback to USB Serial or other to observe.
 
@defragster, I replaced the while(digitalRead(bypasspin) == HIGH) with with while(true) or for( ; ; ) it is working as expected in my expanded code with either! It seems to be failing in the digitalRead(bypasspin). So now, how can break out of the endless loop with the pin going low and what is breaking the while with the digitalRead()? Is there a reason for this behavior or another approach to solve the issue?
 
I resolved the issue by doing this...

Code:
static void Bypass()
{
  Serial.println("in bypass function");
 
    //while(digitalRead(bypasspin) == HIGH)
  for (; ; )
  {
      if (Serial1.available()) {          // If anything comes in Serial1,

          Serial2.write(Serial1.read());  // read it and send it out Serial2
      }

      if (Serial2.available()) {          // If anything comes in Serial2,

          Serial1.write(Serial2.read());   // read it and send it out Serial1
      }

      if (digitalRead(bypasspin) == LOW) {
          break;
      }
  }
}
// End of Bypass

Apparently there are problems with while and the digitalRead()

Thanks Guys!
 
DigitalRead works just fine....I also suggested above removing the while loop to see if it functions, as it's obviously related to the read state of the switch.... @MarkT suggested debouncing, which I concur as a good diagnostic option, but you stated "debounce should not be required" when, in fact, it is generally required with mechanical switches, as it can cause exactly the kind of issues you are seeing. What is the reason you think debouncing is not required?

This is what a typical pushbutton switch signal can look like in reality transitioning from off to on, it's not a clean on/off like you'd imagine:

sw-debounce-f12.png


Left side is off, right side is on, stuff in the middle is the result of typical contact bouncing. Imagine how that looks to your app reading the pin at points in that middle part, sometimes high, sometimes low, depending on the physical contact bounce, until eventually setting at high......it's going to be erratic.

Not saying this is your issue, but as it is a common issue in these cases, worth looking at.....
 
Debounce should not be required.
Nope, absolutely required if you're going to bomb out of a tight loop like that on the first state change. Code exceutes way faster than the mechanical world - for each instruction the T4 executes a jet plane might fly about one wavelength of blue light!

Mechanical switch "bounce" behaviour can generate 10's to 100's of pulses on timescales of microseconds to milliseconds, you definitely need debouncing if you are driving your logic's state machine from a physical switch directly. beermat's example above is what you are up against - some of those spikes may have hidden internal structure too on finer timescales.

Typical approches are use a library, or add a short delay on changing state to allow the switch to stabilize. You can debounce in hardware too, but that costs real components.
 
Back
Top