I am reading two identical sensors via two hardware ports on a due (Serial1 and Serial2). Is there an elegant way to create a single loop to read both sensors?
Maybe, post your code and we can discuss?
You have void loop() as that main loop over all.
So simply read in sensor 1 from serial 1
then
read in sensor 2 from serial 2
Without seeing your code it is impossible to give more advice on how this could be done more elegant.
best regards Stefan
I am using something like below. I am just trying not to duplicate code just to write Serial1 or Serial2. I feel like there is a very easy way that is on the tip of my tongue.
int msg_length = Serial2.available();
if (msg_length > 0) {
byte msg[msg_length];
for (byte i = 0; i < msg_length; i++) {
msg[i] = Serial2.read();
}
}
Nonsense! Just read a single byte as it becomes available and store in it's buffer. Do for each serial connection. Your loop() runs plenty fast to catch all the incoming bytes, and then some!
There is not much to reduce in this case.
You could use a pointer-variable that then will point to serial1 / serial2
so this
becomes similar to this
int msg_length = pointerToSerial.available();
if (msg_length > 0) {
byte msg[msg_length];
for (byte i = 0; i < msg_length; i++) {
msg[i] = pointerToSerial.read();
}
}
Without showing your complete sketch it is impossible to write more of the code.
The code above would enable to call one function
with pointer to serial1
or
with pointer to serial2
but you still have to store the incoming bytes into their bytearray
or
maybe not
depends on the rest of your code
If you post code you should always post the complete sketch.
It is just a waste of time to not post the complete sketch.
The second thing that you should post is how the data looks like that you receive from the sensors
best regards Stefan
not sure what you are asking
the following eSP32 code polls hardware ports Serial1 and Serial2 using loop()
if any data is received it is displayed on serial monitor
// ESP32 serial1 and serial2 hardware loop back test
// see https://circuits4you.com/2018/12/31/esp32-hardware-serial2-example/
/* There are three serial ports on the ESP known as U0UXD, U1UXD and U2UXD.
*
* U0UXD is used to communicate with the ESP32 for programming and during reset/boot.
* U1UXD is unused and can be used for your projects. Some boards use this port for SPI Flash access though
* U2UXD is unused and can be used for your projects.
*/
#define RXD1 12 // for loopback jumper these pins
#define TXD1 13
#define RXD2 16
#define TXD2 15
void setup() {
// Note the format for setting a serial port is as follows: Serial2.begin(baud-rate, protocol, RX pin, TX pin);
Serial.begin(115200);
Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1);
Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
Serial.println("ESP32 hardware serial test on Serial1 and Serial2");
Serial.println("Serial Txd is on pin: "+String(TX));
Serial.println("Serial Rxd is on pin: "+String(RX));
Serial.println("Serial1 Txd1 is on pin: "+String(TXD1));
Serial.println("Serial1 Rxd1 is on pin: "+String(RXD1));
Serial.println("Serial2 Txd2 is on pin: "+String(TXD2));
Serial.println("Serial2 Rxd2 is on pin: "+String(RXD2));
}
void loop() { //Choose Serial1 or Serial2 as required
while (Serial2.available()) {
Serial.println("Serial2 = " + Serial2.readStringUntil('\n'));
}
while (Serial1.available()) {
Serial.println("Serial1 = " + Serial1.readStringUntil('\n'));
}
while (Serial.available()) {
String s = Serial.readStringUntil('\n');
if(s.charAt(0)=='1') Serial1.print( s);
else Serial2.print( s);
}
}
a text string can be sent to either port from the serial monitor by prefixing the string with '1' or '2'
I would write the common code as class and just create two objects, one for Serial1, the other for Serial2.
You haven't told what sensor you are using, have not linked to the datasheet, nor haven't posted a full sketch. So I don't know if my A02YYUW example fits exactly, but it will show you how to create a class for the serial receiver.
You just have to create a second receiver object and handover Serial2.
Hi, @lowriderdog37
What model Arduino are you using.
Have you got two sets of code, one for each serial port.
Have you got them each working before you put them together?
What I am trying to say is, write code for one of your sensors first to prove you can communicate with them.
Can you please post a link to data/specs of the sensors?
Is their outputs, TTL or real RS232 levels.
Thanks.. Tom..
![]()
you msg buffer being local to the if (msg_length > 0) it's gone as soon as you exit the if.
it's also known as being a bad way to read the Serial input buffer and you are not guaranteed that everything has been received
I would suggest to study Serial Input Basics to better understand how to deal with asynchronous data input.
what about
HardwareSerial serial [] = { Serial1, Serial2 };
const int Nserial = 2;
void loop ()
{
for (int n = 0; n < Nserial; n++) {
if (serial [n].available ()) {
char buf [80];
int i = serial [n].readBytesUntil ('\n', buf, sizeof(buf)-1);
buf [i] = '\0';
Serial.println (buf);
}
}
}
void setup ()
{
Serial.begin (9600);
for (int n = 0; n < Nserial; n++)
serial [n].begin (9600);
}
- generically handles multiple Serial I/Fs
don't know about msg format
- don't know if it's an ASCII string terminated by a newline or prefaced by a specific hex value which needs to be recognized before reading specific msg length
- don't know what you want to do with received data, whether it needs to be capture or simply processed as received
that could work indeed. (within the limits of readBytesUntil and its timeout)
One challenge with this approach is that you are stuck with reading one Stream completely and during that time you ignore what's going on with the other one which could overflow its buffer...
To avoid repeating code, I would create a class (with its Stream reference) and with its own extra buffer and receive asynchronously in two instances and trigger then action when the end marker is received
once the transmission of a msg is started, isn't it likely to be transmitted completely?
So little is known, conjecture reigns supreme. If the sensor sends a single n-char value, once per second, the code needs are significantly different than a near-continuous stream from two sensors. We also don't know the use case - is the expectation to write paired values to an output stream or storage, or is it just for LCD display, in which case synchronicity, and continuity, are superfluous.
The OP should come clean on this, to avoid wasting everyone's time.
Seems foolish to make this assumption.
"Likely" is not strong enough to code this way.
"Guaranteed" might not even convince me to use a blocking call.
a7
form receiver side I would never trust an external device.
Imho a code should handle interruptions and it should be hardened against flooding of transmission.
the primary purpose of the code demonstrate s how multiple Serial can be handled using arrays.
if i readBytesUntil() works for this hobbyist case, why not use it. plenty of examples of reading bytes individually.
i've already specified some caveats
Sure but it can take time and you don’t know what’s happening to the other stream.
the code i posted demonstrated a way to read using arrays in a loop -- regardless of whether the complete msg or a single byte is read each iteration.