Multiple software serial ports does not works on Yún

I'm trying to run multiple software serial ports on Yún. My code looks like that so far:

#include <SoftwareSerial.h>

SoftwareSerial serial1(8, 9);
SoftwareSerial serial2(10, 11);

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  serial1.begin(9600);
  serial2.begin(9600);
}

void loop() {
  uint8_t buf1[1] = {0x01};
  uint8_t buf2[3] = {0xC0, 0xFF, 0xEE};
  uint8_t buf3[2] = {0xBA, 0xBE};

  Serial1.write(buf1, 1);
  serial1.write(buf2, 3);
  serial2.write(buf3, 2);

  while(Serial1.available()) {
    Serial.print(Serial1.read(), HEX);
    Serial.print(' ');
  }

  serial1.listen();
  while(serial1.available()) {
    Serial.print(serial1.read(), HEX);
    Serial.print(' ');
  }

  serial2.listen();
  while(serial2.available()) {
    Serial.print(serial2.read(), HEX);
    Serial.print(' ');
  }

  delay(1000);
}

For testing purposes, I connected every following pair of pins together with cable (to create loopback):
1 to 2 => Serial1 (sending 0x01)
8 to 9 => serial1 (software port, sending 0xC0, 0xFF, 0xEE)
10 to 11 => serial2 (software port, sending 0xBA, 0xBE)

Refering to documentation, these pins should work:

Not all pins on the Leonardo and Micro support change interrupts, so only the following can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).

Unfortunately, only Serial1 is working (you should se recieving 0x01 in serial console).

Anybody knows where the problem could be? Thank you.

Edit:
There is probably an bug in SoftwareSerial library.
AltSoftSerial works great, but I need two software serials.

Plan B:

Yun shield + Arduino Mega

Serial: 0 (RX) and 1 (TX); Serial 1: 19 (RX) and 18 (TX); Serial 2: 17 (RX) and 16 (TX); Serial 3: 15 (RX) and 14 (TX). Used to receive (RX) and transmit (TX) TTL serial data. Pins 0 and 1 are also connected to the corresponding pins of the FTDI USB-to-TTL Serial chip.

https://www.arduino.cc/en/Main/arduinoBoardMega

4 (full speed) hardware serial ports!

Multiple SoftwareSerials don't work well anywhere.

You may be able to get my yet another software serial to work alonside regular Software Serial but I have not tried it on a Leonardo or a Yun.

You can get external UARTs that communicate with I2C - might be cheaper than a Mega.

...R

Robin2:
Multiple SoftwareSerials don't work well anywhere.

::::SNIP::::

@Nutelac,
I agree with Robin2. Even with our best processors in the1980 and 1990, it was always required to have at least a hardware buffer. It was just too hard to do software serials even with protocols like Xmodem.

Jesse

Nutelac:
Edit:
There is probably an bug in SoftwareSerial library.

Probably not, it's more likely improper use. You can't do what you want to do with SoftwareSerial.

Take a look at the information page for NewSoftSerial (the current SoftwareSerial in Arduinio.) It has a lot more information than the Arduino reference pages. There is a section on using multiple instances, including an example of usage. It also has this example, which it states will never work, and will just enable one port after another without actually accomplishing anything:

void loop()
{
  device1.listen();
  if (device1.available() > 0)
  {
    int c = device1.read();
    ...
  }
  device2.listen();
  if (device2.available() > 0)
  {
    int c = device2.read();
    ...
  }
}

This looks very much like your code, so it shouldn't be a surprise that it doesn't work. Read that page carefully, and understand the implication of this statement: Any time you call the listen() method, it becomes the “active” object, and the previously active object is deactivated and its RX buffer discarded.

In your code, you're setting serial1 to listen, which discards the active receive buffers and starts listening on the selected port. Microseconds later, before there has been a chance for any data to come in, you've moved past the while (available) loop, and on to the serail2 port. You set that one to listen, which resets the receive buffer, and microseconds later you move on. At that point, you have a one second delay, which might actually give time to receive something on serial2, but once you loop around, and before you have a chance to read that incoming data, you call serial1.listen() which dumps any received data from serial2 and the whole process repeats.

Once you select an active port with listen(), you have to give it time to actually receive something.

A final comment: yes, Serial1 (hardware) and serial1 (your first SoftwareSerial port) are distinct objects, and the compiler has no trouble keeping track of them. However, personally, I feel that it's bad form to have two global objects like that with such similar names - the potential for a mistake is too great. I think it would've been better to call you software ports serial2 and serial3.

@ShapeShifter

Thank you for response. Unfortunately, I can't get it working even with only one software serial port. I just don't know what I'm doing wrong. I beleive, it's not necessary to use .listen() method with one software serial. Here is my sketch:

#include <SoftwareSerial.h>

SoftwareSerial serial2(8, 9);

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

void loop() {
 uint8_t buf[3] = {0xC0, 0xFF, 0xEE};
 serial2.write(buf, 3);
 while(serial2.available()) {
   Serial.print(serial2.read(), HEX);
   Serial.print(' ');
 }

 delay(2500);
}

Even SoftwareSerialExample does not work.

@jessemonroy650

That would be probably the best solution. Can you please provide link to some external uart?

Nutelac:
...
There is probably an bug in SoftwareSerial library.
AltSoftSerial works great, but I need two software serials.

At deadly slow speed even at single port only? try to push it to 500 k?

Robin2:
You can get external UARTs that communicate with I2C - might be cheaper than a Mega.

I was doing a bit of Googling yesterday and it looks like the cheapest source for an external I2c UART might be an .... Atmega 328

...R

@sonnyyu

I tried every baud rate mentioned here, but nothing worked.

I mean software serial port only support slow speed, single port.

Yup, that's exactly what I tried. Single serial port and 300 bauds. No luck.

Looking at your code in Reply #5 and your Original Post ...
Are you trying to do a loop-back test with SoftwareSerial (Tx connected to Rx)?
I don't think that will work because it cannot listen and transmit at the same time.

If you are doing something else please tell us what is connected to SoftwareSerial.

...R

Yes, I'm doing a loopback test. On the other hand, this loopback test works well with AltSoftSerial.

Nutelac:
Yes, I'm doing a loopback test. On the other hand, this loopback test works well with AltSoftSerial.

Sounds like you have an answer :slight_smile:

...R