NewSoftSerial
A New Software Serial Library for Arduino
NewSoftSerial is the latest of three Arduino libraries providing “soft” serial port support. It’s the direct descendant of ladyada’s AFSoftSerial, which introduced interrupt-driven receives – a dramatic improvement over the polling required by the native SoftwareSerial.
Without interrupts, your program’s design is considerably restricted, as it must continually poll the serial port at very short, regular intervals. This makes it nearly impossible, for example, to use SoftwareSerial to receive GPS data and parse it into a usable form. Your program is too busy trying to keep up with NMEA characters as they arrive to actually spend time assembling them into something meaningful. This is where AFSoftSerial’s (and NewSoftSerial’s) interrupt architecture is a godsend. Using interrupt-driven RX, your program fills its buffer behind the scenes while processing previously received data.
Improvements
NewSoftSerial offers a number of improvements over SoftwareSerial:
- It inherits from built-in class
Print, eliminating some 4-600 bytes of duplicate code - It implements circular buffering scheme to make RX processing more efficient
- It extends support to all Arduino pins 0-19 (0-21 on Arduino Mini), not just 0-13
- It supports multiple simultaneous soft serial devices.*
- It supports a much wider range of baud rates.**
- It provides a boolean overflow() method to detect buffer overflow.
- Higher baud rates have been tuned for better accuracy.
- It supports the ATMega328 and 168.
- It supports 8MHz processors.
- It uses direct port I/O for faster and more precise operation.
- (New with version 10). It supports software signal inversion.
- (New) It supports 20MHz processors.
- (New) It runs on the Teensy and Teensy++.
- (New) It supports an end() method as a complement to begin().
*But see below for an important caveat on multiple instances.
**Be circumspect about using 300 and 1200 baud though. The interrupt handler at these rate becomes so lengthy that timer tick interrupts can be starved, causing millis() to stop working during receives.
Using Multiple Instances
There has been considerable support for an library that would allow multiple soft serial devices. However, handling asynchronously received data from two, three, or four or more serial devices turns out to be an extremely difficult, if not intractable problem. Imagine four serial devices connected to an Arduino, each transmitting at 38,400 baud. As bits arrive, Arduino’s poor little processor must sample and process each of 4 incoming bits within 26 microseconds or else lose them forever. Yikes!
It occurred to me, though, that multiple instances could still be possible if the library user were willing to make a small concession. NewSoftSerial is written on the principle that you can have as many devices connected as resource constraints allow, as long as you only use one of them at a time. If you can organize your program code around this constraint, then NewSoftSerial may work for you.
What does this mean, exactly? Well, you have to use your serial devices serially, like this:
#include <NewSoftSerial.h>
// Here's a GPS device connect to pins 3 and 4
NewSoftSerial gps(4,3);
// A serial thermometer connected to 5 and 6
NewSoftSerial therm(6,5);
// An LCD connected to 7 and 8
NewSoftSerial LCD(8,7); // serial LCD
void loop()
{
...
// collect data from the GPS unit for a few seconds
read_gps_data(); // use gps as active device
// collect temperature data from thermometer
read_thermometer_data(); // now use therm
// LCD becomes the active device here
LCD.print("Data gathered...");
...
}
In this example, we assume that read_gps_data() uses the gps object and read_thermometer_data() uses the therm object. Any time you “use” an object by calling its begin(), available(), read(), or print[ln]() methods, it becomes the “active” object, and the previously active object is deactivated and its RX buffer discarded. An important point here is that object.available() always returns 0 unless object is already active. This means that you can’t write code like this:
void loop()
{
if (device1.available() > 0)
{
int c = device1.read();
...
}
if (device2.available() > 0)
{
int c = device2.read();
...
}
}
This code will never do anything but activate one device after the other.
Signal Inversion
“Normal” TTL serial signaling defines a start bit as a transition from “high” to “low” logic. Logical 1 is “high”, 0 is “low”. But some serial devices turn this logic upside down, using what we call “inverted signaling”. As of version 10, NewSoftSerial supports these devices natively with a third parameter in the constructor.
NewSoftSerial myInvertedConn(7, 5, true); // this device uses inverted signaling NewSoftSerial myGPS(3, 2); // this one doesn't
Upcoming Improvements
- RTS/CTS flow control
- support for Arduino Mega
Library Version
You can retrieve the version of the NewSoftSerial library by calling the static member library_version().
int ver = NewSoftSerial::library_version();
Resource Consumption
Linking the NewSoftSerial library to your application adds approximately 2000 bytes to its size.
Download
The latest version of NewSoftSerial is available here: NewSoftSerial10c.zip
Change Log
- initial version
- ported to Arduino 0013, included example sketch in package
- several important improvements: (a) support for 300, 1200, 14400, and 28800 baud (see caveats), (b) added bool overflow() method to test whether an RX buffer overflow has occurred, and (c) tuned RX and TX for greater accuracy at high baud rates 38.4K, 57.6K, and 115.2K.
- minor bug fixes — add .o file and objdump.txt to zip file for diagnostics.
- etracer’s inline assembler fix to OSX avr-gcc 4.3.0 interrupt handler bug added.
- ladyada’s new example sketch, fix to interrupt name, support for 328p.
- etracer’s workaround is now conditionally compiled only when avr-gcc’s version is less than 4.3.2.
- 8 MHz support and flush() and enable_timer0() methods added
- digitalread/write scrapped in favor of direct port I/O. Revised routines now get perfect RX up to 57.6K on 16MHz processors and 31.25K on 8MHz processors.
- inverted TTL signalling supported. 20MHz processors supported. Teensy and Teensy++ supported. New end() method and destructor added to clean up.
Acknowledgements
Many thanks to David Mellis, who wrote the original SoftwareSerial, and to the multi-talented ladyada, whose work with AFSoftSerial is seminal. Ladyada also provided the “Goodnight, moon” example sketch, fixed a problem with the interrupt naming (see v6) and tested NSS with the 328p.
Thanks also to rogermm and several other forum users who have tested NewSoftSerial and given useful feedback.
The diligent analysis of forum user etracer yielded the root cause of a tricky problem with NSS on OSX. A bug in avr-gcc 4.3.0 causes the compiler to fail to generate the proper entry and exit sequences for certain interrupt handlers. etracer identified the problem and provided an inline workaround. etracer’s fix is in NSS 5.
User jin contributed a large body of work based on NSS and identified a potential problem that could result in data loss (fixed in NSS 5). jin also made a variant of NSS that supports 4-pin serial, with the additional pins providing a very nice RTS/CTS flow control. We may see this in NSS in the near future.
Thanks to Garret Mace, who contributed the delay tables for 20MHz processors and claims that he can send and receive at 115K baud. Cool!
Thanks to Paul Stoffregen, both for his fine work with Teensy and Teensy++, and for contributing some useful suggestions that help NewSoftSerial run on them without modification.
I appreciate any and all input.
Mikal Hart
February 15th, 2009 → 10:04 pm
[...] NewSoftSerial version 5 is available. A lot of people have been using this library — thanks! — but I really need to recognize the exceptional work of two contributors. [...]
February 20th, 2009 → 1:08 pm
[...] I posted the new library. [...]
March 2nd, 2009 → 1:46 pm
[...] ในรอบนี้ผมได้ใช้ newSoftwareSerial3 จะได้ลองด้วยว่า มีปัญหาไหม
March 11th, 2009 → 4:54 pm
[...] of the first things to do is download NewSoftSerial
June 9th, 2009 → 3:21 pm
[...] to the task at hand, which happened to be adding 3 lines of code: declaration of an instance of NewSoftSerial, calling the instance constructor with a baud rate, and a single call to pass the char from the [...]
August 1st, 2009 → 3:00 pm
[...] and the XBee module has a serial interface. So how does this really solve my problem? Enter NewSoftSerial, an updated version of the Arduino software serial library, which basically lets you drive a serial [...]
October 14th, 2009 → 1:38 pm
[...] is probably the coolest gift idea I’ve seen. Mikal, you rock. And also, thank you for NewSoftSerial. [...]
November 19th, 2009 → 3:36 pm
[...] way. Let’s move onto the software. Communication with the DS1616 is established using the NewSoftSerial library. Getting data is essentially a case of lots of bit banging. The DS1616 library [...]
December 14th, 2009 → 8:08 am
[...] So we started looking for a solution to overcome this tiny inconvenience. First we looked into a software serial but this didn’t work out, it was a bit too much for the arduino’s little processor to [...]
December 29th, 2009 → 6:59 am
[...] software serial port. I briefly thought about writing one, but then I found this great libary, the New SoftSerial. It is as simple to use as the original library, but unfortunately once I connect the RF receiver, [...]
January 20th, 2010 → 1:19 am
[...] developers for the great libraries, and to Mikal Hart in particular for his work on the TinyGPS and NewSoftSerial [...]
January 23rd, 2010 → 10:27 am
[...] このソースでは、PS2ライブラリとNewSoftSerialライブラリを利用しています。 コンパイルするには、これらのライブラリを有効にしておく必要があります。 [...]
February 27th, 2010 → 10:19 am
[...] as a well. The shield can be wired to any of the pins on the Arduino. Right now we’re using NewSoftSerial on pins 4 and 5. It can be attached to the hardware RX and TX pins, but interferes with [...]
February 27th, 2010 → 12:18 pm
[...] 急遽、Arduinoでシリアル通信をふたつやる必要が発生してホテルで開発。といっても手元にハードがないので、ほとんど勘でプログラムしているようなもの。 次の日現場で試すも、予想通り動かない。そりゃそうだ。 NewSoftwareSerialなんていう便利なものがあるのを後で知った。 [...]