Trouble passing Serial, Serial1, Serial2 as a reference

Status
Not open for further replies.

caykroyd

Member
I'm trying to have a single project that can either send/receive strings via USB serial or Bluetooth. I have a command to switch between Serial and Serial2. It doesn't seem to work the way I expect. When I send a "BTON" command, the print statement prints to Serial, switches to Serial2 and properly prints to Serial2. But when I send the "BTOFF" command immediately after "BTON", both print statements print to Serial when I expected the 1st print command to go to Serial2. It seems as though the "Stream& MySerial = Serial2;" does not persist. Can anyone provide help?

Thanks.

Code:
uint8_t argCount;
uint8_t thisArg = 0;
char *argv[30];
bool BT = false;

Stream& MySerial = Serial;

void setup() {
	Serial.begin(115200);
	Serial2.begin(115200);
}
void loop() {

	static char buffer[80];
	if ((readline(Serial.read(), buffer, 80) > 0) || (readline(Serial2.read(), buffer, 80) > 0)) {
		char tmpBuffer[sizeof(buffer)-2];
		strcpy(tmpBuffer, &(buffer[2]));
		cmd_parse(buffer);
		if (!strcmp(argv[0],"BTON")) {
			MySerial.println("Bluetooth Turning on");  // This properly prints to Serial
			Stream& MySerial = Serial2;
			MySerial.println("Bluetooth is turned on");  // This properly prints to Serial2
		}
		else if (!strcmp(argv[0],"BTOFF")) {
			MySerial.println("Bluetooth Turning off");  // THIS DOES NOT PRINT TO SERIAL2
			Stream& MySerial = Serial;
			MySerial.println("Bluetooth is turned off");  // This prints to Serial
		}
	} 
}
 
I am not the greatest c++ expert, but would strongly guess that the MySerial.println("Bluetooth Turning off"); // THIS DOES NOT PRINT TO SERIAL2
Would print to Serial and not Serial2.

Why: as @markonian mentioned, you have defined three different MySerial objects, each have their own scope.
In Particular: Stream& MySerial = Serial;
Has a global scope, so it is valid everywhere in your sketch (after that point it is defined).

And the definition:
Code:
	if (!strcmp(argv[0],"BTON")) {
			MySerial.println("Bluetooth Turning on");  // This properly prints to Serial
			[COLOR="#FF0000"]Stream& MySerial = Serial2;[/COLOR]
			MySerial.println("Bluetooth is turned on");  // This properly prints to Serial2
		}
Is only valid within the code block that it is defined. That is everywhere after where it is defined up till that next }
Within that scope it sort of masks the global definition variable, but when you exit that scope, the global version is again used...

I know that a compiler person could explain this better than I just did, including the proper terms for the scoping...
 
Shoot. Of course... Now I'm not sure how to change the global reference to Serial2. I have read that you cannot change references. Do I understand this correctly or is there a way to change the global reference back and forth between Serial and Serial2?
 
Don't redeclare MySerial. Just assign a new value to it.
Code:
MySerial = Serial2;
.
.
.
MySerial = Serial;

Pete
 
Hmm. I'll have to ponder that.
BTW what is readline? It looks like you are reading a line from Serial and a line from Serial2 into the same buffer. If so, that'll be quite messy.

Pete
 
Try this:
Code:
		if (!strcmp(argv[0],"BTON")) {
			Serial.println("Bluetooth Turning on");  // This properly prints to Serial
			Serial2.println("Bluetooth is turned on");  // This properly prints to Serial2
		}
		else if (!strcmp(argv[0],"BTOFF")) {
			Serial2.println("Bluetooth Turning off");  // THIS DOES NOT PRINT TO SERIAL2
			Serial.println("Bluetooth is turned off");  // This prints to Serial
		}

The usual test for data on a serial port is:
Code:
	if (Serial.available() > 0)
	{
		incomingByte = Serial.read();
                ...
        }
 
I don't think I am able to re-assign the reference that way
Right, references can not be reassigned. This is much easier by using pointers instead of references.

Just declare a global pointer holding the address of the Serial object you want to print to. You can change that at any time.
Since your code snippet does not compile here a simple example which shows the principle by switching the port after each print:

Code:
Stream *mySerial;

void setup()
{
   Serial1.begin(9600);
   Serial2.begin(9600);

   // E.g. assign the address of Serial1 to mySerial for a start
   mySerial = &Serial1;
}

void loop()
{
   // just assign any Stream address (e.g. Serial, Seria1, ....)
   // to mySerial. 
   // Here a simple example which switches ports after each print
   // replace that with your switching code

   if (mySerial == &Serial1)
      mySerial = &Serial2;
   else
      (mySerial = &Serial1);


  // print to the currently selected port
   mySerial->println("Hello");

   delay(100); // don't overrun the receiver
}
 
luni,

Thank you. I have switched to pointers and MySerial->print. This works!!

Elf,
Thank you for the suggestion, but I do not want to print twice everywhere as I have some timing constraints and prints take too much time already.
 
Status
Not open for further replies.
Back
Top