2 SW_Serial problem

Hey guys I have a little project where one Arduino Nano is plugged in via USB-Mini so the hardware UART pins are already taken. So I use the softwareserial library. In fact I receive data via an XBee module connected to pins 4 and 5 and then forward the data to another device that uses pins 2 and 3. My first try was the following:

#include <SoftwareSerial.h>

//Software-UART Pins for XBee and 2nd device
SoftwareSerial xbee_serial(4, 5); // RX, TX
SoftwareSerial unifi_serial(2, 3); // RX, TX

void setup() {

  xbee_serial.begin(9600);
  unifi_serial.begin(9600);
}

void loop() {

  //Input, which comes via 2nd device and goes to XBee
  if (unifi_serial.available()) {
    xbee_serial.write(unifi_serial.read());
  }

  //Input, which comes via XBee and goes to 2nd device
  if (xbee_serial.available()) {
    unifi_serial.write(xbee_serial.read());
  }
}

I realized tho that only one softwareserial port can be treated at the same time and thus reading and writing at the same time doesn’t work. Next I tried to first read all characters of the incoming data into a buffer and then forward the buffer to the specific destination device. Therefor I tried the following:

#include <SoftwareSerial.h>

//Software-UART Pins für UniFi AC Mesh
SoftwareSerial unifi_serial(2, 3); // RX, TX

//Software-UART Pins für XBee SX 868
SoftwareSerial xbee_serial(4, 5); // RX, TX

String msgBuffer_1 = "";
String msgBuffer_2 = "";
char c = 0;
char d = 0;

void setup() {

  xbee_serial.begin(9600);
  unifi_serial.begin(9600);
}

void loop() {

  //Input, which comes via 2nd device and goes to XBee
  if (unifi_serial.available()) {
    c = unifi_serial.read();

    //when Enter is being hit then send whatever is in the buffer and empty it
    if(c == '\n') {
      xbee_serial.write(&msgBuffer_1);
      msgBuffer_1 = "";
    }
    else {
      msgBuffer_1 += c;
    }
  }

  //Input, which comes via XBee and goes to 2nd device
    if (xbee_serial.available()) {
      d = xbee_serial.read();

      //when Enter is being hit then send whatever is in the buffer and empty it
      if(c == '\n') {
        unifi_serial.write(&msgBuffer_2);
       msgBuffer_2 = "";
      }
      else {
       msgBuffer_2 += d;
      }
    }     
}

I double checked that all RX lead to TX and TX to RX. Does anyone see a problem in the example with the buffer?

I would just receive 1 byte send 1 byte. Don't wait for Enter.

.

ieee488:
I would just receive 1 byte send 1 byte.

That probably won't work. The second byte would be missed while he is forwarding the first byte.

Use Serial for one of the devices (pins 0 & 1). You have to be very selective about debug prints, because everything you print will go to one of the devices. Also, you have to disconnect pin 0 to upload new sketches over the USB port.

Then use AltSoftSerial for the other device (pins 8 & 9). AltSoftSerial and Serial will not interfere with each other.

SoftwareSerial is very iinefficient, because it disables interrupts for long periods of time. It cannot send and receive at the same time, so printing on SoftwareSerial prevents receiving anything. SoftwareSerial interferes with everything.

Using Serial and one softwareserial works perfectly well so far. I only run into troubles when I use 2 softwareSerials at the same time. With your AltSoftSerial I’d also read from Serial and write on SoftwareSerial?

Here a sketch that works perfectly well but uses the hardware UART-pins so when the USB-Mini is connected, then it reads/writes there…

#include <SoftwareSerial.h>

//Software-UART Pins for XBee SX 868
SoftwareSerial xbee_serial(4, 5); // RX, TX

void setup() {

  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  xbee_serial.begin(9600);
}

void loop() {

  //Input, which comes via USB-Mini is transfered to SWSerial
  if (Serial.available()) {
    xbee_serial.write(Serial.read());
  }

  //Input, which comes via SWSerial is transfered to USB-Mini
  if (xbee_serial.available()) {
    Serial.write(xbee_serial.read());
  }
}

Hi,
I wonder if this link will help?

It has an example of using Software Serial for two ports.

google arduino software serial two ports

Tom... :slight_smile:

Thanks for the suggestion. In their example they use "mySerial.listen()" so I'd block the other softwareserial port with that command. I am trying to figure out a way to listen on two softwareserial ports at the same time and if one has available data then it should transfer it to the other one. So fat it's only possible to transfer data to the hardware serial pins

Using Serial and one softwareserial works perfectly well so far.

Use AltSoftSerial instead of SoftwareSerial. But you have to use pins 8 & 9. If you can't use those two pins, try NeoSWSerial instead of SoftwareSerial.

I only run into troubles when I use 2 softwareSerials at the same time.

How many times does it take? YOU CAN'T DO THAT.

With your AltSoftSerial I'd also read from Serial and write on SoftwareSerial?

It's not mine.

You would read from Serial and write to AltSoftSerial. You could also read from AltSoftSerial and write to Serial, even at the same time. This is the BEST choice.

You could try Serial and NeoSWSerial (mine). This is the 2nd best choice.

Serial and SoftwareSerial might work, but SoftwareSerial cannot transmit and receive at the same time. Transmitting a character with SoftwareSerial prevents receiving a character on SoftwareSerial, and vice versa. At 9600, SoftwareSerial stops your Arduino from doing anything else, for 1ms at a time, when it sends or receives 1 character. This is the worst choice.

I tried out AltSoftSerial because it sounds promising to read from alt and write to Serial at the same time but I don't see how to set the Alt RX and TX pins. I saw that they are fix in the echo example but then I also only get weird echos. Is there no option to set the pins yourself? I assume that the Arduino nano uses the same AltSoftSerial pins like the Uno?

I don't see how to set the Alt RX and TX pins. Is there no option to set the pins yourself?

You have to use pin 8 (for RX, connect to device TX) and pin 9 (for TX, connect to device RX). YOU HAVE TO USE THOSE PINS ON A NANO.

I assume that the Arduino nano uses the same AltSoftSerial pins like the Uno?

Yes. The Nano has the ATmega328P chip, just like the Uno. So YOU HAVE TO USE PINS 8 & 9.

I saw that they are fix in the echo example but then I also only get weird echos.

"Weird echos", really?

Show us. Connections, Sketch, and Serial Monitor contents (in code tags!).

I tried it out in the following situation. I have another device that I communicate to via UART so I hook it up to the AltSoftSerial pins 8 and 9 (plus a GND that the device needs). When it boots, it transmitts with the baudrate 115200 to give it’s booting messages. Then once booting is completed, it switches to 9600 and expects the user to hit enter. After that it switches back to 115200 and allows the user to login.
First you’ll see the output when directly using the hardware UART pins of the Nano without any code on it.

U-Boot unifi-v1.6.7.249-gb74e0282 (Apr 25 2017 - 09:18:46)

DRAM:  
sri
ath_ddr_initial_config(278): (ddr2 init)
ath_sys_frequency: cpu 775 ddr 650 ahb 258
.
.
.
(and so on and on till the following comes)

Starting kernel ...

(Then it suddenly changes to baud rate 9600 and waits for me to hit Enter)

[00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]

(When I hit enter with 9600 and change back to 115200, and type anything in the CLI, I get this login window and can successfully use it)

mesh3 login: admin
admin
Password: (not gonna tell you guys, sorry)



BusyBox v1.19.4 (2017-03-22 15:29:31 PDT) built-in shell (ash)
Enter 'help' for a list of built-in commands.

BZ.v3.7.51# ifconfig
ifconfig
ath1      Link encap:Ethernet  HWaddr F0:9F:C2:3E:A1:74  
          UP BROADCAST RUNNING PROMISC ALLMULTI MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
.
.
.
(and so on)

BZ.v3.7.51#

Then I use the following code on the arduino nano to communicate with the device via the AltSoftSerial pins 8 and 9 with this code:

#include <AltSoftSerial.h>

//Software-UART Pins for UniFi AC M
AltSoftSerial unifi_serial; // RX = Pin8, TX = Pin9

//Variable used to measure the time for the UniFi AC M to boot
unsigned long tmp;

void setup() {

  Serial.begin(115200);
  while (!Serial) { } // Wait for Serialport
  unifi_serial.begin(115200);
  Serial.println("Initialize communication. Please wait...");
}

void loop() {

  do{
    
  //Input, that arrives from UniFi AC M is being transmitted to Serial
  if (unifi_serial.available()) {
    Serial.write(unifi_serial.read());
  }
  tmp = millis();
  }while (tmp < 50000); //wait for UniFi to boot

  
  //Change baudrate to 9600
  unifi_serial.flush();
  unifi_serial.begin(9600);

  delay(3000);

  //Sending "Enter"
  unifi_serial.write('\n');

  delay(3000);
    
  //Change baudrate back to 115200
  unifi_serial.flush();
  unifi_serial.begin(115200);
  
  Serial.println("\n\nInitialization completed");

  while (1) {
    
  //Input, that arrives via Serial is being transmitted to UniFi AC M
  if (Serial.available()) {
    unifi_serial.write(Serial.read());
  }

  //Input, that arrives from UniFi AC M is being transmitted to Serial
  if (unifi_serial.available()) {
    Serial.write(unifi_serial.read());
  }
 }
}

It also works somehow but the answer of the device often is some trash. I don’t know why. Maybe the buffer is full or anything? if the changing of the baudrate didn’t work, then I shouldn’t be possible to login at all? Here the output with the AltSoftSerial code:

Initialize communication. Please wait...
€
[0C]
[15]-B`ot u[0E]ifi-v1.6.7.249-gb74e0282 (@Ɂ25 2017 - 09:18:46)

DRAL:  
sri
a[17]ëEDÉ}¤¹¥Ñ¥…±}Œ½¹™¥¡278): (ddr2 init)
ath_pys_frequency: cpu 775 ddr 650 a[08]b 258
.
.
.
(and so on and on till the following comes)

StartZèkernel ...

[00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]

Initialization completed

[0E][00]¡¬X.k[02][00]login:[00]þadmin
admin
[00]áPassword:[00](not gonna tell you guys, sorry)

[00]á
[00]¡ [00]H[15]Íå ¾áÿ²ÁrŠÊr¢[02][00](2[00]Šºj‚šz’’[02][00]15[00]'[00]ÊÒšŠ[02][00]PD\)[00][12]Ô½±Ñ·in she[0C][00][0B]B
4[08]([00]z
Fnter '[00]«[16], [00]ÖK [00]+[00][04]ˆ[08]z™€built-[00]Z[0B][1A]ô¨+뿑̹
[00]¡ [00]Hi¹v3[00]鐩Ž[1A][00] ifconfig
ifconfig
[00]áath1[00][02][00] [00][02][00] [00]
Èk[0B]*äh…p:[00]Q[10]«É¹•Ñ [00]ú[14]‘ɁF0[00]§N”[1A]ÉÒš*é

.
.
(and so on)

Update:
I tried several tests and have to agree that the AltSoftSerial is much much faster than the SoftwareSerial. to transfer a String of 1400 letters the SoftwareSerial must work at 19200 Baud to successfully transfer them. AltSoftSerial managed to do the same task with 57600 Baud.

The problem has been solved so you guys can close this topic. Thanks again for the hint -dev

-dev:
Use AltSoftSerial instead of SoftwareSerial. But you have to use pins 8 & 9. If you can't use those two pins, try NeoSWSerial instead of SoftwareSerial.
How many times does it take? YOU CAN'T DO THAT.
It's not mine.

You would read from Serial and write to AltSoftSerial. You could also read from AltSoftSerial and write to Serial, even at the same time. This is the BEST choice.

You could try Serial and NeoSWSerial (mine). This is the 2nd best choice.

Serial and SoftwareSerial might work, but SoftwareSerial cannot transmit and receive at the same time. Transmitting a character with SoftwareSerial prevents receiving a character on SoftwareSerial, and vice versa. At 9600, SoftwareSerial stops your Arduino from doing anything else, for 1ms at a time, when it sends or receives 1 character. This is the worst choice.