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. macsimski

    13 years ago

    is it possible to make the buffer bigger? I was looking in the source, but could not find the place where to or how to do that. i am working on a improvement so you can select 8n1, 7e1, or any arbirtary combination of databits, parity and stopbits and speeds down to 50 BAUD. (remember telexes?)


  2. macsimski

    13 years ago

    found it. buffer settings are in the headerfile…


  3. Sam

    13 years ago

    Hi. I’ve a question about NewSoftSerial10: im’trying to use it for communication between two arduinos but when I read on Serial monitor the characters that I’ve send with anther Serial monitor, I only read “J” with two points over. Why?


  4. Serveurperso

    13 years ago

    Nice work, I need non-standard baud rate:( I need to calculate the DELAY_TABLE values for 100000 bauds on 16MHz 328 Arduino…


  5. Mikal

    13 years ago

    @Sam,

    Make sure you check to make sure a character is available before you try to read:

    if (nss.available())
    c = nss.read();

    You are probably getting a -1 return code, which means “no character available”.

    Mikal


  6. Mikal

    13 years ago

    You can usually support non-standard baud rates by interpolating the values that are already in the table. Be careful about high speeds like 100K baud though. At that speed things get pretty fragile on the poor little Arduino.

    M


  7. Oli

    13 years ago

    Hey,

    I got a little Problem running this library using Linux, although
    it works fine using Windows7:

    In file included from /home/b52/Projekte/Arduino/libraries/NewSoftSerial/NewSoftSerial.cpp:40:0:
    /home/b52/Projekte/Arduino/hardware/arduino/cores/arduino/pins_arduino.h:66:48: error: variable ‘port_to_mode_PGM’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
    /home/b52/Projekte/Arduino/hardware/arduino/cores/arduino/pins_arduino.h:67:49: error: variable ‘port_to_input_PGM’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
    /home/b52/Projekte/Arduino/hardware/arduino/cores/arduino/pins_arduino.h:68:50: error: variable ‘port_to_output_PGM’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
    /home/b52/Projekte/Arduino/hardware/arduino/cores/arduino/pins_arduino.h:70:54: error: variable ‘digital_pin_to_port_PGM’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
    /home/b52/Projekte/Arduino/hardware/arduino/cores/arduino/pins_arduino.h:72:58: error: variable ‘digital_pin_to_bit_mask_PGM’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
    /home/b52/Projekte/Arduino/hardware/arduino/cores/arduino/pins_arduino.h:73:55: error: variable ‘digital_pin_to_timer_PGM’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
    /home/b52/Projekte/Arduino/libraries/NewSoftSerial/NewSoftSerial.cpp:94:34: error: variable ‘table’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’

    avr-gcc: 4.6.1
    avr-libc: 1.7.0

    I got the same problem using NSS 11 beta :/

    Hope someone can help, thanks in advance
    Oli


  8. wolf

    13 years ago

    Hi! I try to fetch an website using NewSoftserial. My problem is, that there is a big header, and about 800 bytes are transmitted. I am interessted in the data after about 300 characters. I changed the buffersize to 256 in NewSoftserial, but that is still too small and I do not have any more memory in my ATMega left.

    Is there a trick, to get all the characters from the website? At the moment I tried to get about 40 chars and then I send a flush(). This enables me to get the section, which I am interessted in. But that’s not a very good way.

    Are there any plans to implement an FIFO buffer?

    Thank you!
    Wolf


  9. Mikal

    13 years ago

    Wolf, the NSS buffer *is* a FIFO.

    You could ignore the first 300 bytes of a stream using a simple technique like this:

    for (int i=0; i<300; ++i)
    {
    while (nss.available()); // wait until character arrives
    nss.read(); // throw it away
    }


  10. Rei Vilo

    13 years ago

    How easy / difficult to port the NewsoftSerial library to the Microchip-based chipKIT UNO32 Arduino-compatible board?

    See
    http://www.chipkit.org/forum/viewtopic.php?f=6&t=303&hilit=newsoftserial
    and
    http://www.chipkit.org/forum/viewtopic.php?f=6&t=281&hilit=newsoftserial


  11. Manfred

    13 years ago

    Hello!
    nice work, but I found a small problem in version 10C:

    In function setTX you set the pin to output before you set it to HIGH,
    this creates a short glitch on the TX pin to LOW.
    Change the order to:
    digitalWrite(tx, HIGH);
    pinMode(tx, OUTPUT);
    ,this will solve it.

    After this change I can connect correctly to an autobauding device.
    (don’t forget the pullup resistors with such devices).
    Manfred


  12. Mikal

    13 years ago

    @Manfred,

    Interesting. Your proposal makes some sense. It goes against conventional programming style, but I see your point. Thanks for sharing.


  13. David

    13 years ago

    How goes the CTS/RTS implementation?

    I’ve got a 328 on a board with a Max232(clone) and I’m banging away at 4800 bps after upping the receive buffer to (I think) 256 bytes. I threw in a CTS toggle to get it to work at 9600, but it’s not in the interrupt service routine. So now, as I’m coding along, I keep thinking… “When will I get back here? Will I lose bytes?”

    Anyhoo…
    Is the receive buffer empty when buffer_head == buffer_tail?
    If so, I could probably modify the .cpp source to lower CTS if the buffer’s empty, and raise it if the buffer’s full… (Just stick another pin in the constructor, I’m thinking…)
    I’m not worried (at the moment) about overflowing the 16550 in the PC with data coming from the 328, but I am worried about bits coming in and going to nirvana.


  14. Ugo

    13 years ago

    Hi,
    I am a very newby on arduino & related.
    I am working with an arduino UNO, a window XP netbook and, finally with a 232-to-USB converter (tested two different brands).
    I simply make a test with your basic example modified in this way:

    quote
    ——
    #include

    NewSoftSerial mySerial(2, 3);

    void setup()
    {
    // set the data rate for the NewSoftSerial port
    mySerial.begin(4800);
    }

    void loop() // run over and over again
    {
    mySerial.println(“Hello, world?”);
    delay(1000);
    }
    ——-
    unquote

    What I receive is a set of unreadable characters only.
    (Yes, I set the correct baud rate on monitor).

    Which could be the problem?
    Thanks in advance,
    Ugo


  15. wibauxl

    13 years ago

    Hi Mikal,
    Very nice work indeed !
    Just a small question after reading your code: what is the purpose of enable_timer0 ? It does not seem to be called from anywhere ?
    Laurent


  16. Rei Vilo

    13 years ago

    Hi!

    Do you plan to be ready for Arduino 1.0 IDE and the new Arduino Due board?

    Best regards,


  17. Marcos

    13 years ago

    Hi…I just add some code to handle the enable pin on RS485 systems and I want to share it…how can I send you for review it…I already tested (OK) but is always better to have a second review…thanks for the code…


  18. erik

    13 years ago

    Mikal, Using the newsoftserial demo with my GPS, I receive data well at 4800bps, but when the data rate is increased to 9600, I start losing characters, and 19200+ is unreadable. The GPS data signal is clean because I can read it with the HW serial port just fine up to 115200. I’m running a Duemilanove ATmega328 16mHz, serial input on pin 7. What could be the problem?


  19. Victor

    13 years ago

    Hello,

    As I understand it, NewSoftSerial gives other pins serial functionality between the Arduino and other devices. Is it possible to allow serial communication between Arduino and computer via USB using pins other than D0,D1 on an UNO? I have a shield that uses those pins to communicate with the Arduino, but I’d like to be able to type in input simultaneously.

    Thank you,
    Victor


  20. Mikal

    13 years ago

    @David,

    I don’t have time to make an RTS/CTS, but I know people have done this successfully. Yes, the buffer is empty when buffer_head == buffer_tail.

    BTW NewSoftSerial is migrating into the Arduino core with 1.0, renamed “SoftSerial”.

    Mikal


  21. Mikal

    13 years ago

    @Ugo,

    Arduino pins use TTL logic levels, not RS-232. You would need a TTL-to-USB converter.

    Mikal


  22. Mikal

    13 years ago

    @wibauxl,

    enable_timer0() is a technique for improving accuracy at very high baud rates where the timer tick attached to timer 0 can skew the data. It’s very rarely used, and will be abandoned completely once Arduino 1.0 comes out.

    Mikal


  23. Mikal

    13 years ago

    @erik,

    The only think I can imagine is that you are doing too much processing in between serial port reads and this causes you to lose characters. Does nss.overflow() return true? If so, then that’s your problem.


  24. Mikal

    13 years ago

    @Victor,

    Yes, but you’d need a TTL-to-USB converter/adapter.

    M


  25. Dmitry

    13 years ago

    I want to compile the program (for example NewSoftSerialTest) to ATMega32, but am getting syntax errors:

    C:\arduino-0022\libraries\NewSoftSerial\NewSoftSerial.cpp: In static member function ‘static void NewSoftSerial::enable_timer0(bool)’:
    C:\arduino-0022\libraries\NewSoftSerial\NewSoftSerial.cpp:520: error: ‘TIMSK0’ was not declared in this scope
    C:\arduino-0022\libraries\NewSoftSerial\NewSoftSerial.cpp:526: error: ‘TIMSK0’ was not declared in this scope

    And indeed, in the ATMega32 no TIMSK0, and there are TIMSK. May be there is a simple solution to this problem?


  26. Mikal

    13 years ago

    @Dmitry,

    That enable_timer0 is an experimental function to help tune very high baud rates. You can safely remove it.

    Mikal


  27. Magnus

    13 years ago

    Hi
    I tried using this library on an atmega8 using the atmega8_noxtal bootloader. For some reason I am not receiving anything at all, when connected to a gps. I have checked the wires and confirmed that everything works if I use a atmega328. Does anyone know what could be wrong when using the atmega8? (I am using the Timer connected to the TCCR2 register for interrupts)

    best
    Magnus


  28. Chab

    13 years ago

    Hello,

    Is it possible with this library to set PARITY, BIT STOP, etc…. on different inputs ?
    And how ?

    Thank you very much !
    Chab.


  29. varn

    13 years ago

    Hi,
    I am newbie to the newSoftSerial library, how can I find the documentation for any of the functions defined in the library ?
    Regards,
    Varn.


  30. Sisco

    13 years ago

    Hi very nice work very impressive.

    I try o use iwith Pololu Micros Servo controler (work nice alone) But when i try to use a second newsoftserial for my gps em406 then servos are jitters.

    An idea?

    Regards

    Sisco


  31. Charles

    13 years ago

    Mikal,

    May I ask where you are with adding parity to NewSoftSerial?


  32. Jorge

    13 years ago

    Hi Mikal,
    just a quick question, is it possible to set the NSS to use arduinos ANALOG ports as RX & TX? I don’t want to share the serial TX/RX with GPS TX/RX and almost all of my Digital PIN are used.

    Thank you!!!


  33. Jorge

    13 years ago

    It worked, just tried the analog ports A0 and A1 following the Digital sequence, once all ports on the atmel are digital, until you tell then they are not.
    I’m using now 14 and 15 pins for RX, TX.

    Thanx!!


  34. Luis

    13 years ago

    Hi there,
    This library works very well, while I’m not handling the output.
    But as soon as I try to develop some code around it (string manipulation, a couple of additional interrupts and whatnot), I start to get a lot of buffer overflows.

    For instance, with a GSM module I’m not being able to read and process a full 160 char SMS.

    I tried to change the buffer to a higher value and also lower the baud rate to 2400 and 4800, but my Arduino behaves erratically when I do any of those, and even freezes most of the time.

    So I’m at a loss here on what I could do to get around this. When receiving an SMS, I need to get the sender’s phone number and message content, that’s easy with strings, but perhaps messing around with strings causes too much delay in the MCU?

    Thanks in advance for your attention.
    Luis


  35. Luis

    13 years ago

    Hello again,
    Regarding my previous post, I believe the errors were due to bad programming on my part.

    To read the characters, I was using:
    // —————-
    char c;
    int dataAvail = sftwr_serial.available();
    if (dataAvail > 0)
    {
    for(int i=1; i 0)
    {
    c = sftwr_serial.read();
    }
    // —————

    At least this modification and setting the buffer to 256 bytes has been working for an hour now, without hiccups :)
    Lowering the baud rate continued to result in strange behavior, however.

    Thanks again!
    Luis


  36. Jay Emell

    13 years ago

    Hi,
    On the topic of multiple instances:
    I have a project that is about combining three, to perhaps four, 4800 baud input streams to one combined 38,400 baud output stream. The 4800 baud input streams are spiky – each transmit some 20 – 100 characters every second and are silent in between. The inputs cannot be synchronised and so will eventually transmit simultaniously at occasions.
    Given an Arduio Uno: Do you believe there is a solution to both use the HW USART in combination with two or three instances of NSS?


  37. luis

    13 years ago

    Hi! congratulations for this library,
    Have you ever proved this library with AtTiny’s using the Arduino plattform (software and hardware) as a programmer?


  38. Mikal

    13 years ago

    @Magnus,

    I don’t think the atmega8 has the necessary interrupt change pins to support RX with NSS.

    Mikal


  39. Mikal

    13 years ago

    @Chab,

    Sorry, no. I’d welcome a patch! :)

    Mikal


  40. Mikal

    13 years ago

    @Sisco,

    Have you tried the PWMServo library? NewSoftSerial is not compatible with the Arduino Servo library.

    Mikal


  41. Mikal

    13 years ago

    @Charles, honestly I doubt I will ever add parity to NewSoftSerial. Perhaps now that it’s heading to the Arduino core (as SoftwareSerial replacement) it will be easier to get someone to work on that.

9 Trackbacks For This Post
  1. Anonymous

    […] Modul per Software-UART? Bitte einen Link oder Hinweis wo ich nachlesen kann. danke Schaust du hier __________________ FHZ1300 | 2x JeeLink | AVR-NETIO | FS20 | 1-Wire | 2x XBEE Pro | 4x XBEE 2.5 […]

  2. Using A Second (Software) Serial USB To Debug Your Arduino | Utopia Mechanicus

    […] actually really easy, using some code called NewSoftSerial (available from this site, at the ‘Download’ subheading). This software is much like your Serial device you use on the Arduino, but it’s in software […]

  3. Kemper LED / Arduino Interface » Powerhouse Electronics

    […] provided by the software library “NewSoftSerial”. The library can be downloaded from:: http://arduiniana.org/libraries/NewSoftSerial/. Since the communications port is created using software any of the Arduino port pins can be used. […]

  4. Android talks to Arduino | ★ Elmindo Blog ★

    […] NewSoftSerial library from Mikal Hart: http://arduiniana.org/libraries/newsoftserial/ […]

  5. Utilizando a Bees Shield em uma Arduino Mega « A arte do hardware

    […] via jumper na própria shield. Para comunicação com essa Bee, é necessário o uso da biblioteca NewSoftwareSerial, permitindo fazer que dois pinos digitais se tornem mais uma […]

  6. Arduino camera and geotagger | jarv.org

    […] NewSoftSerial lib was used for communicating over serial using an IO […]

  7. Bluetooth + Arduino + Android – 1 : Transmettre des données d’un capteur branché sur une carte Arduino vers un Smartphone Android via bluetooth

    […] 1– télécharger la bib­lio­thèque New­Soft­Se­r­ial pour Arduino NewSoftSerial10c.zip. Des expli­ca­tions et exem­ples plus détail­lés con­cer­nant cette bib­lio­thèque sur cette page (http://arduiniana.org/libraries/newsoftserial/). […]

  8. Arduino + fon + OpenWRT + ser2net + NewSoftSerial « sea side she side

    […] そのためソフトウェアシリアルを再現させたライブラリがありますのでそれを利用します。とはいっても標準ライブラリのSoftwareSerialは利用しません。高機能で速度もでるようになったNewSoftSerialを利用します。 […]

  9. David C. Dean Arduino GPS – On the Cheap

    […] NewSoftSerial Library – http://arduiniana.org/libraries/NewSoftSerial/ […]

Leave a Reply