NewSoftSerial Library

NewSoftSerial, by Mikal Hart, emulates an additional serial port, allowing you to communicate with another serial device.

Download: NewSoftSerial10c.zip

Hardware Requirements

UART Serial should always be used, if possible. NewSoftSerial imposes substantial CPU usage requirements. Only use NewSoftSerial when a second serial port is absolutely necessary. Hardware required is the same as if using the UART.


NewSoftSerial requires pin change interrupts for reception, which are only available on certain pins. To receive, you must use one of the compatible pins from this table. Any pin may be used to transmit.

BoardReceive Compatible Pins
Teensy 1.05, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20
Teensy 2.00, 1, 2, 3, 4, 13, 14, 15
Teensy++ 1.020, 21, 22, 23, 24, 25, 26, 27
Teensy++ 2.020, 21, 22, 23, 24, 25, 26, 27

Basic Usage

NewSoftSerial mySerial(ReceivePin, TransmitPin);

Create an instance of NewSoftSerial, using a pair of pins to receive and transmit. The receive pin must be one that supports pin change interrupts. You can create multiple NewSoftSerial ports, each on their own 2 pins, but due to the CPU usage requirements, it's only practical to use one port at a time.

mySerial.begin(baud);

Initialize the port to communicate at a specific baud rate.

mySerial.print(anything);

Print a number or text. This works the same as Serial.print().

mySerial.available();

Returns the number of bytes received, which can be read.

mySerial.read();

Reads the next byte from the port. If nothing has been received, -1 is returned.

mySerial.write(byte);

Transmit a single byte.

mySerial.flush();

Discard any received data that has not be read.

Example Program

The example program below listens for keystokes on any of the three ports, and prints a message to all 3 when any input is received.


USB Serial, as seen by Arduino Serial Monitor


Real (UART) Serial, as seen by GtkTerm


Emulated (NewSoftSerial) Serial, as seen by GtkTerm

Here is the example code.

#include <NewSoftSerial.h>

NewSoftSerial mySerial(0, 1);
HardwareSerial Uart = HardwareSerial();

void setup()  
{
  delay(1000);
  Serial.begin(57600);
  Serial.println("Hello world - USB Port");
  Uart.begin(57000);
  Uart.println("Hello World - Real Serial Port");
  mySerial.begin(57600);
  mySerial.println("Hello World - Emulated Serial Port");
}

void loop()                     // run over and over again
{
  char c;

  if (mySerial.available()) {
    c = mySerial.read();
    print_all_three(c, "NewSoftSerial");
  }
  if (Uart.available()) {
    c = Uart.read();
    print_all_three(c, "HardwareSerial");
  }
  if (Serial.available()) {
    c = Serial.read();
    print_all_three(c, "USB Serial");
  }
}

void print_all_three(char c, const char *mesg)
{
  Serial.print("Char: '");
  Serial.print(c);
  Serial.print("' on: ");
  Serial.println(mesg);
  Uart.print("Char: '");
  Uart.print(c);
  Uart.print("' on: ");
  Uart.println(mesg);
  mySerial.print("Char: '");
  mySerial.print(c);
  mySerial.print("' on: ");
  mySerial.println(mesg);
}
  

CPU Usage and Interrupt Latency Requirements

NewSoftSerial requires nearly 100% CPU time while transmitting or receiving data. Low interrupt latency is also required for reliable reception, which limits all other libraries and code using interrupts. For these reasons, UART Serial should always be used if only a single serial port is needed.

NewSoftSerial should not be used at slow baud rates. Because interrupts are disabled for approximately 9.5 bit times, slow baud rates can impose too much interrupt latency on other code. Baud rates below 4800 can interfere with basic time keeping functions which make millis(), micros(), and delay() function.

Fast baud rates can become unreliable for reception if other interrupt-based libraries impose too much latency, either by using too much CPU time inside their interrupts, or by keeping interrupts disabled. For example, the OneWire library must disable interrupts for 80 us for some operations. The bit time must be more than double the worst case interrupt latency for reliable reception.

Even the timer0 interrupt for time keeping can take as long as 10 us in its worst case (on Teensy, Arduino's code is slower), which means even 57600 could suffer incorrect reception. Other interrupt-based code can further interfere.

Of course, other latency sensitive libraries, like Servo, will not perform reliably if NewSoftSerial is blocking interrupts while other code requires low latency response.

Using UART Serial is always best, but if NewSoftSerial must be used, baud rates between 9600 to 38400 may be the most compatible.

Details

For more details, please refer to the official NewSoftSerial page.