NewSoftSerial

A New Software Serial Library for Arduino

News: NewSoftSerial is in the core!  Starting with Arduino 1.0 (December, 2011), NewSoftSerial has replaced the old SoftwareSerial library as the officially supported software serial library.  This means that if you have 1.0 or later, you should not download this library.  To port your code to 1.0, simply change all NewSoftSerial references to SoftwareSerial.

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:

  1. It inherits from built-in class Print, eliminating some 4-600 bytes of duplicate code
  2. It implements circular buffering scheme to make RX processing more efficient
  3. It extends support to all Arduino pins 0-19 (0-21 on Arduino Mini), not just 0-13
  4. It supports multiple simultaneous soft serial devices.*
  5. It supports a much wider range of baud rates.**
  6. It provides a boolean overflow() method to detect buffer overflow.
  7. Higher baud rates have been tuned for better accuracy.
  8. It supports the ATMega328 and 168.
  9. It supports 8MHz processors.
  10. It uses direct port I/O for faster and more precise operation.
  11. (New with version 10).  It supports software signal inversion.
  12. (New) It supports 20MHz processors.
  13. (New) It runs on the Teensy and Teensy++.
  14. (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
  gps.listen();
  read_gps_data();  // use gps as active device
  // collect temperature data from thermometer
  therm.listen();
  read_thermometer_data(); // now use therm
  // LCD becomes the active device here
  LCD.listen();
  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 call the listen() method, 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()
{
  device1.listen();
  if (device1.available() > 0)
  {
    int c = device1.read();
    ...
  }
  device2.listen();
  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

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: NewSoftSerial12.zip.  Note: don’t download this if you have Arduino 1.0 or later.  As of 1.0, NewSoftSerial is included in the Arduino core (named SoftwareSerial).

Change Log

  1. initial version
  2. ported to Arduino 0013, included example sketch in package
  3. 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.
  4. minor bug fixes — add .o file and objdump.txt to zip file for diagnostics.
  5. etracer’s inline assembler fix to OSX avr-gcc 4.3.0 interrupt handler bug added.
  6. ladyada’s new example sketch, fix to interrupt name, support for 328p.
  7. etracer’s workaround is now conditionally compiled only when avr-gcc’s version is less than 4.3.2.
  8. 8 MHz support and flush() and enable_timer0()  methods added
  9. 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.
  10. inverted TTL signalling supported.  20MHz processors supported.  Teensy and Teensy++ supported.  New end() method and destructor added to clean up.
  11. added listen() method to explicitly activate ports.
  12. warn users about 1.0 conflict

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

Page last updated on July 3, 2013 at 7:37 pm
647 Responses → “NewSoftSerial”

  1. Mikal

    11 years ago

    Mike, yeah, I’m afraid both [New]SoftSerial and the current Servo motor library use interrupts in ways that are not mutually compatible. However, if your design has two or fewer servos and you can tolerate them being fixed to certain pins, the OLD servo library (posted on this site as PWMServo) might solve your problem…


  2. Dave

    11 years ago

    One problem I have been having is an interrupt conflict when trying to use Servos as well as SoftSerial

    Basically I am trying to use an Uno to read a GPS using SoftSerial but also control model Servos.


  3. Mikal

    11 years ago

    @Dave,

    Yeah, that’s a well-known and understood problem. One possible solution is to use the PWMServo variation on the Servo library (on this site). Another is to turn off the Servo when the soft serial device is needed and vice versa.


  4. Victor

    10 years ago

    Hi, How can I communicate with two shields, a GPS using softserial 4,5 and a GSM shield using softserial 2,3. The baud rate for the GPS is 38400 and for the GSM is 9600. Both shields work fine separately.


  5. mehul

    10 years ago

    i have made a program for sending a sms through a gsm module and i am using a SoftwareSerial , but how to include the SoftwareSerial library bcoz in my program when i write #include the SoftwareSerial is not turning orange


  6. Mikal

    10 years ago

    @mehul,

    I think in some versions of Arduino there is an error in the SoftwareSerial keywords.txt file which prevents the keyword from turning orange.


  7. Felix Group

    10 years ago

    I tried the library with a UART crystal at 11.0592MHz. In theory there should be no communication errors. I modified the delay table. My results:

    Serial.print:
    – perfect until 115200baud.

    Serial.read from Arduino terminal input:
    – perfect until 38400baud.
    – At 115200baud I can only read the first 4 characters correctly.

    Serial.read from other Serial port of Arduino:
    – perfect until 57600baud but with an other delay table (not compatible to Serial terminal read)

    Is this baud rate limitation based on the crystal speed, or is my delay matrix not good enough?

    The matrix:
    // baud rxcenter rxintra rxstop tx
    { 115200, 2, 9, 9, 7, }, //puhh
    { 57600, 15, 21, 21, 19, }, //okay
    { 38400, 28, 33, 33, 32, }, //perfect


  8. Mikal

    10 years ago

    @Felix,

    Yeah, unfortunately, it’s not just the precision of the crystal or the accuracy of the delay table that comes into play. It’s the unpredictable timer-tick interrupt–the one that drives millis()–that causes the problem. If that fires just before one of your bits arrives, it can sufficiently delay its apparent arrival so as to corrupt the incoming bit stream.


  9. Bruce Vernham

    10 years ago

    I am trying to use the 1284P with the Soft Serial library. I am using a “Bobdunio” which is using the mighty1284 core. When I compile the sketch wit the UNO I do not have any issue but when I try to compile it with the 1284 board I get:

    C:\Program Files (x86)\Arduino\libraries\SoftwareSerial\SoftwareSerial.cpp: In member function ‘void SoftwareSerial::begin(long int)’:
    C:\Program Files (x86)\Arduino\libraries\SoftwareSerial\SoftwareSerial.cpp:401: error: operands to ?: have different types ‘int’ and ‘uint8_t*’
    C:\Program Files (x86)\Arduino\libraries\SoftwareSerial\SoftwareSerial.cpp:402: error: expected primary-expression before ‘]’ token
    C:\Program Files (x86)\Arduino\libraries\SoftwareSerial\SoftwareSerial.cpp:402: error: operands to ?: have different types ‘int’ and ‘uint8_t*’
    C:\Program Files (x86)\Arduino\libraries\SoftwareSerial\SoftwareSerial.cpp: In member function ‘void SoftwareSerial::end()’:
    C:\Program Files (x86)\Arduino\libraries\SoftwareSerial\SoftwareSerial.cpp:417: error: expected primary-expression before ‘]’ token
    C:\Program Files (x86)\Arduino\libraries\SoftwareSerial\SoftwareSerial.cpp:418: error: expected primary-expression before ‘]’ token
    C:\Program Files (x86)\Arduino\libraries\SoftwareSerial\SoftwareSerial.cpp:418: error: operands to ?: have different types ‘int’ and ‘uint8_t*’

    Any ideas how to fix it.


  10. Sohel Malek

    10 years ago

    Hello everyone…
    I am using Arduino for my project. N i m going to transmit camera images through zigbee module. My problem is that i have already connected 0 and 1 pin (TX, Rx) pins of Arduino with zigbee module and my camera is also UART enabled…so i think i have to use Softwareserial library. So suggest me some idea if any and give me code so that i can get idea. Thank You.


  11. Mikal

    10 years ago

    @Bruce, if the processor is not supported by the official Arduino distribution, this is where you’d first find out. Look in the Arduino forum for guidance. For example: http://forum.arduino.cc/index.php?topic=157297.0.


  12. Mikal

    10 years ago

    There are tons of examples of SoftwareSerial use out there. Try first the example sketches that ship with Arduino (File/Examples/SoftwareSerial).


  13. tack

    10 years ago

    Mikel, I wonder if you could be so kind as to take a look at the following thread

    http://forum.arduino.cc/index.php?topic=157297.0

    A few people are having problems using Software Serial on AtMega1284P, which is becoming more popular.

    I’m sure everyone would be very greatful for any insight you could provide towards resolving.

    Many thanks

    Mick


  14. Pit

    10 years ago

    Hello, I simply want do his:

    while (SoftSerial.available())
    {
    SoftSerial.write(SoftSerial.read());
    }

    But it don’t work like required… OK, it’s a software serial…

    But what I miss is the sei(); in the .write fkt.

    – Pit


  15. Mikal

    10 years ago

    @tack,

    I don’t have experience with that processor, but I feel fairly sure that it could be made to work by making suitable additions to pins_arduino.h and making sure that the pins used support change interrupts. I have a port of SoftwareSerial to the Atmega644p, and the 1284p doesn’t seem that different.


  16. Mikal

    10 years ago

    @Pit,

    I’m afraid that’s not possible with a Software Serial, unless you can guarantee that no characters will arrive during the time you are transmitting a response.


  17. Mike

    10 years ago

    Hi,

    Please could you suggest the best way to add a timeout function to SoftwareSerial ports, in order to avoid lock-up in the event of a missing serial input?

    Thanks, Mike.


  18. Mikal

    10 years ago

    @Mike,

    I don’t think there is any way to “lock up” the library. You shouldn’t ever need to call ss.read() if ss.available() returns 0, but if you do, it instantly returns -1. It doesn’t wait for a character to appear in the stream or anything. I’m afraid that if you’re experiencing a lockup you might need to look elsewhere. Hope that helps.


  19. Mostafa

    10 years ago

    hello , i need your help when i compile the example have error
    (
    In file included from NewSoftSerialExample.pde:1:
    C:\Program Files (x86)\Arduino\libraries\GSM_Shield/NewSoftSerial.h:71: error: conflicting return type specified for ‘virtual void NewSoftSerial::write(uint8_t)’
    C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:48: error: overriding ‘virtual size_t Print::write(uint8_t)’
    )


  20. Mikal

    10 years ago

    @Mostafa,

    You should not use NewSoftSerial in modern Arduino installations, as it has been replaced in the core with SoftwareSerial.


  21. Ron Hackett

    10 years ago

    Hi Mikal,
    Thanks for the great library, especially the inversion feature!

    I’m using the library with an ATtiny84, and I have two questions:
    1. I’m only using Tx, and I would like to not have to dedicate a second pin to Rx. Is there any way to do that?
    2. Also, in order to save space in the ATtiny, is there any way to just install the TX function without the Rx function?

    Thanks… Ron


  22. Mikal

    10 years ago

    @Ron Hackett,

    If you’re only using TX, you can get the RX pin to -1:

    NewSoftSerial port(-1, 12); // for example
    

    To minimize the footprint, you could redefine the size of the RX buffer _NSS_MAX_RX_BUFF to, say, 1. That would save you 63 bytes.


  23. Mike

    10 years ago

    Hello,

    Do you have any plans to add a timeout function to the SoftSerial library? If not, please could you suggest how best to implement this in a sketch?

    Thanks, Mike.


  24. Artur

    10 years ago

    Mikal,
    Have one problem – how to use SoftSerial at 14.7456MHz? Library allow only 8/16/20MHz. I have this quartz for 0% transmissin error (Atmega32 datasheet, page 165).
    So:
    1) how to get DELAY_TABLE PROGMEM table for 14.7456MHz?
    2) does 14.7456MHz is out of mind and should simple use 16MHz?

    Best regards!
    A.


  25. SebastianUF

    10 years ago

    Hello, I am trying to connect a TTL camera to a UdooQuad board. I initially got the code using the NewSoftSerial library but then i switched to the SoftwareSerial lib. I am getting multiple errors one saying “this SoftwareSerial supports only 20 16 and 8Mhz processors.” and a few others that state “error: SREG was not declared.” and “error:cli was not declared”.
    I changed all the newSoftSerial parameters to SoftwareSerial but about 30 of these errors repeat themselves. Any idea on what these errrors mean?


  26. Mikal

    10 years ago

    Artur, it’s possible to modify NewSoftSerial to support non-standard baud rates, but you have to create your own DELAY_TABLE. To start off, take the 16MHz table and multiply each value by 14.7456/16. These values will not be exactly correct, but close enough for low baud rate devices.


  27. Mikal

    10 years ago

    @SebastianUF,

    The UdooQuad is an ARM board and unfortunately, [New]SoftSerial only supports AVR devices at this time.


  28. jinwoo

    10 years ago

    thanks a lot


  29. Mikal

    10 years ago

    If 4 is RX, you need to hook Arduino pin 4 to the pin labeled “TX” on the GPS. That’s my guess.


  30. Bako

    10 years ago

    Hello Mikal iam trying to use two RF modules (CC1101) with two arduinos for sending the value of a potintiometer from one side to control a servo on the other side. the library doesn’t work even if it’s newsoftware or softwareserial . maybe I have some problem with writing the code. Can you help me ?
    Thank you


  31. Mikal

    10 years ago

    @Bako,

    Are your boards sharing a common ground?


  32. Bako

    10 years ago

    that was a problem. I then tried two different boards and it worked thanks Mikal for your help. but still has problem with the code of combining the software serial library code with the code for Knob, check this code out please and feed me back

    #include
    #include
    Servo myservo;
    int potpin=0;
    int val;
    SoftwareSerial mySerial(10, 11); // RX, TX

    void setup()

    {
    myservo.attach(9);
    // Open serial communications and wait for port to open:
    Serial.begin(9600);
    while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
    }

    Serial.println(val);

    // set the data rate for the SoftwareSerial port
    mySerial.begin(9600);
    mySerial.println(val);
    }

    void loop() // run over and over
    {
    val = analogRead(potpin);
    val = map(val, 0, 1023, 0, 179);
    myservo.write(val);
    delay(15);
    if (mySerial.available())
    Serial.write(potpin);
    potpin = mySerial.read();
    if (Serial.available())
    mySerial.write(potpin);
    potpin = Serial.read();
    }


  33. Robin

    10 years ago

    I am using Arduino 1.5.4, but SoftwareSerial seems to use the variant of flush() which was removed from the Arduino libraries such as Stream, Serial etc as from Arduino 1.0. Instead of waiting until any output has been transmitted, it deletes all data which are in the incoming buffer.

    Is this intentional? If not, could it be updated?

    Apart from this, it’s a very nice library!


  34. Mikal

    10 years ago

    Hi Robin–

    Thanks for the note. Flush on output doesn’t make too much sense on SoftwareSerial, because writes are all blocking. Are you suggesting perhaps renaming the flush that flushes the input stream? Removing it?


  35. Robin

    10 years ago

    Hi Mikal,
    In C++, flush() is a standard function for flushing output streams. So it’s really confusing to find a function called flush which flushes input.
    I suggest that the function should have a different name. How about iflush?
    Hopefully this wouldn’t be a big problem for most people, as my guess is that it is not used very much.

    All the best,
    Robin


  36. Core2

    10 years ago

    Mikal,

    First off thanks for sharing your hard work.
    I am not having any luck getting the SoftwareSerial to work with my Fio V3. I am trying to get data from a GP-635T GPS sensor. Every time I use your example “Simple test” I do not receive any data from the sensor when using the Software Serial library on pins 4(RX), and 3(TX). But if I modify the code to use the hardware serial instead, and hook the GPS up to that I do get some data in. Although it is not good data it appears I am not getting a lock. But for now I am focusing on the Software Serial issue. Have you or anyone else had any success using the Arduino Fio V3 and Software Serial? Any suggestions you or anyone else could provide would be great. Thanks for your time.


  37. Martin

    10 years ago

    Hi Mikal:

    Great library, but reading through the code .. the ring buffer is updated from an ISR so shouldn’t all methods that access the ring buffer (like read(), available(), etc.) disable interrupts while processing?

    Regards,

    Martin


  38. Mikal

    10 years ago

    Hi Core2–Since the Fio is based on the 328P, I’m pretty sure it will work the same. Have you got your RX/TX crossed? Remember TX on GPS should be connected to RX on Arduino.


  39. Mikal

    10 years ago

    @Martin–

    I understand your point, but I think I’ve convinced myself that there is no danger of read(), available(), etc., producing an erroneous result, no matter when an interrupt arrives. And I don’t want to delay any incoming interrupt–that’s very important, especially at high speeds.

11 Trackbacks For This Post
  1. Please wait your turn! Stratoballoon GPS Sensor Sketch « Mark Gilbert's Blog

    […] to the GPS receiver, I’d be writing to the data logger serially.  I found information here about running multiple devices serially – the short answer is that you have to access the serial […]

  2. Going to Arduino from C#, Java, … string trouble | Hydroinformatix the Gaul

    […] kB). I used this method and solved my intermitting (and making me crazy…) problems 2) Using PString library, added by NewSoftSerial and put in official version of Arduino. It is very handy: it hands you a […]

  3. The Frustromantic Box, Part 4: Software | New Bright Idea

    […] developers for the great libraries, and to Mikal Hart in particular for his work on the TinyGPS and NewSoftSerial […]

  4. Le Dan-TECH » 2ème Partie : Reconnaissance vocale avec Arduino

    […] , les ports 12 & 13 de l’arduino sont utilisés (liaison arduino-module via la classe newSoftSerial) et ne permettent pas l’emploi du shield Ethernet sur une platine « arduino […]

  5. on the trail of the elusive Power Cost Monitor signal | We Saw a Chicken …

    […] I rewrote the logger to use the Arduino’s internal UART, since — lovely though NewSoftSerial may be — it causes millis() to report wildly inaccurate times at low bit rates. I recorded a […]

  6. 86duino

    […] require that protocol. The version of SoftwareSerial included in 1.0 and later is based on the NewSoftSerial library by Mikal […]

  7. 86duino

    […] This requires the TinyGPS and NewSoftSerial libraries from Mikal Hart: http://arduiniana.org/libraries/TinyGPS and http://arduiniana.org/libraries/newsoftserial/ […]

  8. Kerry D. Wong » Blog Archive » RF Data Link Using Si4021 And Si4311

    […] BT1 pin settings (which are done in hardware), the receiver is totally configuration free. I used NewSoftSerial library in the code below. The main loop simply print out the incoming bit stream. You may also use […]

  9. how to set up arduino + pololu mini maestro (for an 18 servo hexapod) | orange narwhals

    […] newsoftserial should be downloaded from the internet and the folder inside the zip put in (path to where you […]

  10. Starter Kit Sonar » Starter Kit

    […] szczęście jest jeszcze jedna biblioteka „NewSoftSerial”, która jest pozbawiona tych wad i na dodatek obsługuje zanegowany sygnał […]

  11. Twitter Poem Box -Use Arduino for Projects

    […] Download the TrueRandom http://code.google.com/p/tinkerit/wiki/TrueRandom, NewSoftSerial http://arduiniana.org/libraries/newsoftserial/, and Twitter […]

Leave a Reply