Use Serial1 for UNO

Dears,

I'm trying to figure out how a single program can be used on multiple boards (ie. UNO, MEGA etc...). All except declaring the Serial1, Serial2... went fine. On MEGA it compiles fine since the Serial1 is there, but on UNO it fails since it do not have a Serial1. (however it compiles on an ESP with arduino IDE which only have single serial).

Is there a way/trick, so that it can be compiled and uploaded to a UNO board evenif Serial1 is not defined?

Thanks in advance...

Do you want the program to ignore the Serial1 elements when it is compiled for an Uno?

Or do you want to create a SoftwareSerial port and name it Serial1 ?

...R

Hi Robin,

Yes, all other serial ports other than the primary Serial (ie. Serial1, Serial2, Serial3 etc...) is to be ignored if its a board that do not have those ports. I'm currently building a network of single master and many slaves. Only the master will have use with multi serial, all other slaves (consists of both MEGA and UNO boards) will not have a use with other ports. Not trying to create a softwareserial and name it as Serial1.

Thanks,
MR

by the way many thanks for you for the input basics Robin,

It was a great help for me to start from the basics. I'm using your piece of code on my application.
Just realized both are the same person :slight_smile:

Add this to the top of your sketch:

#ifndef HAVE_HWSERIAL1
#define Serial1 if(false)Serial
#endif  //HAVE_HWSERIAL1

That should automatically disable all references to Serial1 in your sketch with no overhead. The compiler sees that the if statement will always be false so it just optimizes out those statements.

If there is other code in your sketch that has no purpose without Serial1 you can save some memory by wrapping it in:

#ifdef HAVE_HWSERIAL1
#endif  //HAVE_HWSERIAL1

HAVE_HWSERIAL1 is a macro that is defined in the Arduino core libraries when Serial1 is available on the selected board.

Hi Pert,

It worked!

I had to slightly change the condition

#ifndef HAVE_HWSERIAL1
#define Serial1 Serial
#endif

Thanks mate!

mithunrockey:
I had to slightly change the condition

#ifndef HAVE_HWSERIAL1
#define Serial1 Serial
#endif

That is going to behave differently. Rather than ignoring the use of Serial1 (which is what you said in Reply #2) it will convert it to use Serial.

...R

If you still want to try to achieve the disabling of Serial1 as you had originally requested I'm sure we could help you get it working if you provide details on why my recommendation didn't work.

While #define Serial1 Serial will cause the sketch to compile, it is a very inefficient solution if your intent is actually to disable the Serial1 code when Serial1 is not available.

Hi Pert, Robin

Sorry for not getting back soon, I was away for a couple of days.

When using the macro #define Serial1 if(false)Serial the following is the error happening

Automation_Arduino_Mega_V4.ino: In function 'void setup()':
Automation_Arduino_Mega_V4:20: error: expected primary-expression before 'if'
#define Serial1 if(false)Serial
^
Automation_Arduino_Mega_V4/Automation_Arduino_Mega_V4.ino:39:13: note: in expansion of macro 'Serial1'
while (!Serial1) { ; }
^
Automation_Arduino_Mega_V4:20: error: expected ')' before 'if'
#define Serial1 if(false)Serial
^
Automation_Arduino_Mega_V4.ino:39:13: note: in expansion of macro 'Serial1'
while (!Serial1) { ; }
^
Automation_Arduino_Mega_V4:39: error: expected ';' before ')' token
while (!Serial1) { ; }
^
exit status 1
expected primary-expression before 'if'

I was looking to use the same sketch on all boards, my current system consists of 1 server node and field nodes, and all are Mega and Uno (atleast for now). The server node and some field nodes will be on Mega. Idea is to write sketch which is common for all boards. Only the server node will use (and will receive data on) the Serial1 port. The group will automatically identify the server node by itself (if any input happening from Serial1, it means it is the server). But for that I will have to read the incoming data on Serial1 on every board to identify if it is the server node.

I see the one I use below now
#define Serial1 Serial
will actually supply Serial when I call Serial1, so it will not work on the case since the Serial1 will give output of Serial I guess.

Can you suggest a solution for this please?

Thanks...

Regards,
Mithun

The construction while(!Serial1){} has no effect on any Arduino. Remove that line.

It's only relevant for the native-USB Arduinos and only on the native USB port, which is always Serial (or a #define which points back to that.)

MorganS already explained it while I was writing this but I'll post anyway in case there is a little extra info:

Your line 39:

while (!Serial1) { ; }

most likely has no purpose even when Serial1 is available. On any standard hardware serial port Serial1 will always be true. The exception would be if you had a board with a USB CDC Serial1 but I'm not aware of any board that has that. The ATmega32U4, and likely some of the more modern non-AVR Arduino boards do have a USB CDC Serial and that is where you will find that:

while (!Serial) { ; }

can be useful to wait until the Serial Monitor has been opened before sending output (see if(Serial) - Arduino Reference).

So unless you have good reason for keeping it, just remove line 39 and your sketch should work fine with my suggested Serial1 disabling code. If for some reason you do need to keep line 39 then you can wrap it in the preprocessor conditional I mentioned previously:

#ifdef HAVE_HWSERIAL1
 while (!Serial1) { ; }
#endif  //HAVE_HWSERIAL1

Thank you for your advice dear Pert,Morgan

I'm really very new to the Micro-controller things.

So I do not need the while (!Serial1) { ; } condition at all.

But unless defining a Serial1 as Serial with Macro it still throw errors with
Serial1.print()
while (Serial.available() > 0) { }

etc etc... correct?

What can we do about it?

Thanks again!

pert:
If you still want to try to achieve the disabling of Serial1 as you had originally requested I'm sure we could help you get it working if you provide details on why my recommendation didn't work.

your cunning idea to do

#ifndef HAVE_HWSERIAL1
#define Serial1 if(false)Serial
#endif  //HAVE_HWSERIAL1

fails in a syntax error the minute the code tries to do anything a bit advanced but very common like

  if (Serial1.available()) {
    Serial.print((char) Serial1.read());
  }

would be transformed into

  if (if(false)Serial.available()) {
    Serial.print((char) if(false)Serial.read());
  }

and then you have missing ; at the end of the statement

mithunrockey:
But unless defining a Serial1 as Serial with Macro it still throw errors with
Serial1.print()
while (Serial.available() > 0) { }

etc etc… correct?

What can we do about it?

Please post your full sketch. If possible you should always post code directly in the forum thread as text using code tags (</> button on the toolbar). This will make it easy for anyone to look at it, which will increase the likelihood of you getting help. If the sketch is longer than the forum will allow then it’s ok to add it as an attachment.

J-M-L:
and then you have missing ; at the end of the statement

Yes, that’s a problem. I adapted this from the system I use for switching on/off debug serial output in all my code:

#define DEBUG false
#define Serial if(DEBUG)Serial

which works great but seems not so well suited for this application. So if anyone has a nifty line of code or two to do this with no overhead I’m sure it would be welcome. Otherwise I would suggest using the other option I provided of wrapping code related to Serial1 in the preprocessor conditional. How much that will clutter the code up will depend on how extensively Serial1 is used. If that’s only a few lines then it’s probably the best approach anyway as it makes the intent of the code very clear.

yeah no perfect answer... if I understood correctly only the master needs to be a MEGA with multiple Serial ports and clients will just use Serial. --> I would create 2 codes, one for the server and one for the clients...

So wrap #ifndef HAVE_HWSERIAL1 around every instance of master code which doesn't need to run on the slaves.

It may be beneficial to put that at the top, for something like...

#ifdef HAVE_HWSERIAL1
  #define MASTER
#endif

....

#ifdef MASTER
  //master code using Serial1 goes here
#else
  //slave code using Serial goes here
#endif

Then you have a little more control over what happens in each instance of master or slave. Because at some point in the future, one of your slaves is going to be a Micro or a Teensy which does have Serial1.

Presumably the existence of HAVE_HWSERIAL1 (and maybe other such beasts) is documented somewhere?

It's open-source. You can read the source code to see it. This kind of stuff shows up in pins.h and boards.txt, which sets the specifics for each board. You can find all sorts of interesting stuff in there like the pin number for the Rx and Tx LEDs on the Arduino Micro, which aren't connected to external pins.

kenwood120s:
Presumably the existence of HAVE_HWSERIAL1 (and maybe other such beasts) is documented somewhere?

Not that I'm aware of and really this is probably not considered part of the public API and thus not something to be relied on, though I doubt they'll change it. If you look at where it is defined in the Arduino AVR Boards core, Arduino/HardwareSerial.h at 1.8.4 · arduino/Arduino · GitHub

#if defined(UBRR1H)
  extern HardwareSerial Serial1;
  #define HAVE_HWSERIAL1
#endif

My thought was that using this macro would make the code more portable between architectures but now that I check Arduino SAM Boards and Arduino SAMD boards it turns out it is not defined so that may not be the case. You could always use a list of the board specific macros for every known board with Serial1 but it would be nice if there was something universal. I'm not aware of anything like that. There are some macros in the variants file that are intended to help with programmatically determining serial resources that I think are intended to be somewhat standardized (e.g. Arduino/pins_arduino.h at 1.8.4 · arduino/Arduino · GitHub):

// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
//
// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
//
// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
//
// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
//
// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
//
// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
//                            pins are NOT connected to anything by default.
#define SERIAL_PORT_MONITOR         Serial
#define SERIAL_PORT_HARDWARE        Serial
#define SERIAL_PORT_HARDWARE1       Serial1
#define SERIAL_PORT_HARDWARE2       Serial2
#define SERIAL_PORT_HARDWARE3       Serial3
#define SERIAL_PORT_HARDWARE_OPEN   Serial1
#define SERIAL_PORT_HARDWARE_OPEN1  Serial2
#define SERIAL_PORT_HARDWARE_OPEN2 Serial3

but I don't see that any of them are useful for this application and they haven't gotten around to documenting them beyond the comments in the code.

Well then #ifdef SERIAL_PORT_HARDWARE1 will reliably detect if there's a hardware serial 1.