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

    16 years ago

    @Prune, do you get the same values every time you type “a” on the softserial console? Are all the grounds tied together? Is that Serial-to-USB cable operating at TTL levels? If it’s RS-232 it won’t work.

    Mikal


  2. Prune

    16 years ago

    Mikal,

    Thanks for pointing that out. I seriously did not check !!!
    You should put this link (or a better one if you have) in a warning at the start of this page : http://www.seattlerobotics.org/encoder/aug97/cable.html

    I’m taking the adaptor apart, but i’m sure this is the root of all my problems.
    Wil let you know.
    Many thanks


  3. Jerry

    16 years ago

    Getting these errors when I try to compile your latest code:

    C:\dev\Arduino\arduino-0017\hardware\libraries\NewSoftSerial\NewSoftSerial.cpp: In member function ‘void NewSoftSerial::begin(long int)’:

    C:\dev\Arduino\arduino-0017\hardware\libraries\NewSoftSerial\NewSoftSerial.cpp:412: error: invalid type argument of ‘unary *’

    C:\dev\Arduino\arduino-0017\hardware\libraries\NewSoftSerial\NewSoftSerial.cpp:413: error: invalid type argument of ‘unary *’

    C:\dev\Arduino\arduino-0017\hardware\libraries\NewSoftSerial\NewSoftSerial.cpp: In member function ‘void NewSoftSerial::end()’:

    C:\dev\Arduino\arduino-0017\hardware\libraries\NewSoftSerial\NewSoftSerial.cpp:429: error: invalid type argument of ‘unary *’


  4. Mikal

    16 years ago

    Jerry, what kind of AVR processor are you compiling for?

    Mikal


  5. keywon

    16 years ago

    Hello Mikal, thank you for this lib, I’ve been using it for two months on a thesis project :)

    Sadly, it suddenly stopped working for me today and I was wondering how to troubleshoot it.

    I’ve been using this to communicate with a UART RFID reader @19200, and then pass it onto a python program via hardware serial @9600.

    When I run the test program that comes with the download (NewSoftSerialTest.pde), the soft serial doesn’t print the “Hello World” message it should. All I get in the serial monitor @4800 is one broken character like à or Ó. It prints “Goodnight moon” when I switch to the hardware serial @57600. When I send “a” etc. to the monitor, it doesn’t print anything at either 57600 or 4800.

    My RFID readers used to send a broken character (int value -1) when there is no tag present, and print ‘*’ + 16-byte tag ID when there’s one. Now all it’s sending is a broken character.

    I am assuming this is a problem with the Soft Serial communication because the RFID readers are printing the tag well over hardware serial when monitored in Terminal > Screen, with the ATMEGA chip removed. I have also re-installed the lib, Arduino 017 and the FTDI driver, and tried two different RFID readers as well. On a potentially related note, Arduino seems to forget to refresh Tools > Serial Port list half of the times when I plug in different boards, which also started today.

    How would you go about troubleshooting this? I am using it with Arduino Pro Mini 5v w/ATMEGA 328 16HMz, on Snow Leopard. I appreciate your help.


  6. Mikal

    16 years ago

    Keywon–

    Gosh, that’s a tough one. It was working previously? Are all the devices still grounded together?
    If you didn’t change anything with the software, I have to assume that something came loose. You’ve hooked the RFID RX pin to the NSS TX pin and vice versa?

    Mikal


  7. Denis

    16 years ago

    Hello.

    How i can configure start/stop with it’s library? Or it’s only planned feature?


  8. Mikal

    16 years ago

    Hi Denis–

    With NewSoftSerial 10, when you have finished with your communication, you can cease with

    nss.end();

    Does that answer your question?

    Mikal


  9. keywon

    16 years ago

    Mikal — thanks for the reply.

    I believe it’s grounded properly. Tried switching rx/tx as well :) Also tried:

    Watching the NSS rx/tx pins on oscilloscope: the pins are sending and receiving, we see the dense square wave, and they both read 5v when idle.

    Pull up resistor on NSS RX pin as suggested here http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1256934324: Makes no difference

    Using pins 0,1 for NSS like you suggested here http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1252024653/4: worked as is, without NSS.available() or NSS.read()

    So we think that NSS is transmitting but not receiving. NSS.available() or NSS.read() isn’t working, as if there is nothing in the buffer.

    We tried same Arduino code and circuit on two Snow Leopard Macs, one Linux machine, one Windows (via VMware Fusion), and it only works on Windows now. All running Arduino 017, two Arduino mini pro 328 16mhz boards.

    I don’t have a good hypothesis. Does this ring any bell?
    Much appreciated —


  10. Mikal

    16 years ago

    Keywon, do I understand correctly?

    Working configurations: NSS on pins 0/1, or on other pins when serial partner is Windows.
    Not working (but did work previously): NSS on other pins when partner is Mac or Linux

    What version of NewSoftSerial are you using? Are those 3.3V Arduinos Pros? Is it possible that you have a voltage mismatch problem?

    This is a most curious issue.

    Mikal


  11. 3dotter

    16 years ago

    Hi Mikal,

    I am a newbie in using Arduino. I tried already some codes with the Lilypad and a boardino and was able to make some code which worked. In a next step I also want to use your library to connect and “talk” to a GSM modem with AT commands, but it has not become clear to me which softserial port will become the Rx and which the Tx port in the following pin selection: e.g. NewSoftSerial gps(4,3); Is the 1st position, here 4, the Rx or the Tx? Thanks in advance for your answer!


  12. Mikal

    16 years ago

    Hi 3dotter, and welcome to the great world of Arduino. The prototype for NewSoftSerial’s constructor is:

    NewSoftSerial(int rx, int tx);

    So you can see the first pin is RX. Make sure you realize that that’s RX from the Arduino’s point of view. To connect a GPS, you’d connect the GPS’s TX line to NewSoftSerial’s RX line. Don’t let that confuse you. :)

    Mikal


  13. 3dotter

    16 years ago

    Hi Mikal,

    Thanks for the swift answer. Understood! Yes, arduino rocks :) It is great.

    Best wishes,
    3dotter


  14. NSR

    16 years ago

    Hi Mikal,

    I’m working with Keywon on her project, and I’ve found the issue. I’m posting it because I think it’s worth knowing. It appears the Windows machine had a /slightly/ older version of the version 10 library. In the newest version of the library, there is a segment in lines 45-57 that is supposed to define a mapping from pin numbers to PCICR/PCMSK variables. In the slightly older version, it works as intended, but in a fresh download the #if, #else, and #endif statements are commented out. This results in the macros being defined as NULL for every type of processor.


  15. Mikal

    16 years ago

    Ouch. Most embarrassing. Thank you both very much. Sorry for the errant post. The correct version (10C) is now posted.

    Mikal


  16. Markham

    16 years ago

    Hi Mikal,
    Love your work. I have a simple question which I think based on the responses above, I may already now the answer.

    Are there any problem with NewSoftSerial and version 0017?

    The reason I ask, is that I have it working perfectly for transmitting data, but I get nothing when receiving.
    I started with my GPS project which worked perfectly with the hardware serial, transferred it to NewSoftSerial and I didn’t receive anything. e.g. gps.available() always return 0. Transmitting beautifully at high speed but nothing in return.
    I then went to the simple example where I echoed to the hardware serial and the NewSoftSerial (reverse wiring on pins 0,1 & 2,3), same thing happened , NewSoftSerial transmitted data ok but nothing in return. I tried all speeds from 4800 to 56900. Yes, I’ve wired it properly and yes I’m using the same speed for both ports. I know the information is being transmitted from the device because I’m remotely monitoring the signal and see it going there but NewSoftware is not picking it up.

    I’m using the latest Arduino Duemilanove with ATMega328 and version 0017 loaded on a XP windows platform.

    Thanks


  17. Mikal

    16 years ago

    Hi Markham,

    NewSoftSerial 10b which was briefly posted here had a defect which broke it for receives on Duemilanove. Please discard that and grab 10c which is now posted. If you continue to have trouble, would you mind downgrading to version 9 to see if that works? It’s at http://arduiniana.org/NewSoftSerial/NewSoftSerial9.zip.

    There should be no incompatibility between NewSoftSerial and Arduino 0017, except for the servo library.

    Mikal


  18. cTiger

    16 years ago

    quickly scanning through the code of the library it seems this library does not support very well 1200 bauds and even worse in my case with 7bits data word.

    could someone confirm ?

    cheers
    cTiger


  19. Mikal

    16 years ago

    cTiger,

    1200 baud is supported, but not yet 7-bit data words.

    Mikal


  20. mango

    16 years ago

    Hi,

    I am trying the “NewSoftSerialTest” example code and it’s not working for me. I have pins 2 and 3 connected to each other and have set all baud rates to 9600. I’m using the Arduino Duemilanove 328. In the terminal I get “Goodnight moon!” and nothing else. I am expecting to see “Hello, world?”. Has anyone else run into this problem or know how I can continue trouble shooting (I’ve tried checking mySerial.available()>0)?

    Here is the code:

    #include

    NewSoftSerial mySerial(2, 3);

    void setup()
    {
    Serial.begin(9600);
    Serial.println(“Goodnight moon!”);

    // set the data rate for the NewSoftSerial port
    mySerial.begin(9600);
    mySerial.println(“Hello, world?”);
    }

    void loop() // run over and over again
    {

    if (mySerial.available()) {
    Serial.print((char)mySerial.read());
    }
    if (Serial.available()) {
    mySerial.print((char)Serial.read());
    }
    }


  21. Mikal

    16 years ago

    Mango, you shouldn’t connect the two pins together. That sketch is not designed to be a “loopback” test. It assumes that a console or some serial device is physically connected to pins 2 and 3 on the Arduino.

    To explain it another way, since software serial libraries require 100% of the CPU to transmit or receive a byte, they can’t do both at the same time.

    Connect a serial device like a GPS to those pins and watch the data fly on the Arduino serial console.

    Mikal


  22. mango

    16 years ago

    Mikal,

    I forgot to mention with my previous quote that I am working on Mac OS X 10.5, Arduino 0017, and have also tried NewSoftSerial 9 as you suggested to Markham.


  23. mango

    16 years ago

    Thanks for the explanation. It works just fine now!


  24. Markham

    16 years ago

    Thanks Mikal, version 10C works a whole lot better. However I did find out some interesting limitations.I also tried ver9 and it did the same thing.
    I have a number of GPS units and there are two which I love the most, being;
    -32 Channel San Jose Navigation GPS 5Hz Receiver with Antenna.
    -Venus GPS Logger with SMA Connector.

    Both can be programmed to output the exact same NMEA sentences, position update rate and communicate on 3.3V TTL serial.
    The interesting thing is that NewSoftSerial communicates almost flawlessly with the Venus GPS from speeds of 9600 to 115200 (fantastic). However the San Joes unit has a number of communications problems with NewSoftSerial (incorrect data determination, not necessarily just data lost). The San Joes unit works perfectly at 9600. At 38400, data is lost and incorrect characters generated but just readable. At speeds higher than 38400, data is unreadable.

    Clearly the two different units, although supposedly communicating at the same speed, their timings are microseconds slightly different. Clearly the hardware serial can read both units at any speed because it can buffer more information and adjusts itself accordingly. Unlike NewSoftSerial which has hardwired timings. I could play with the timings table and get the San Joes working perfectly but then I would suspect that my Venus unit would be affected.

    Mikal what would be an excellent tool, is a small program that can generate the timings table for any device. e.g. use the hardware serial in parallel and adjust the timings until the same data is read with the NewSoftSerial program. Only one problem would be different units requiring different timings being used together.

    Again Thanks Mikal.


  25. David McCallum

    16 years ago

    Hi Mikal,

    Thanks for the great library!

    I’d like one clarification, with respect to the “active” serial object, and how switching to a new active object clears the previous object’s RX buffer.

    Does this mean that when we create a function to deal with a serial input, it should loop “.available() > 0” until it’s !> 0 before moving on to the next serial object, to make sure no incoming data is lost?

    I hope this makes sense…

    Thanks!
    D!


  26. Mikal

    16 years ago

    Hi David, and thanks for the good question.

    To save space, there is internally only one 64-byte RX buffer, which is shared between all NewSoftSerial objects in a sketch. Whichever one is the “active” one has custody of the buffer, meaning that if a byte arrives for that object it is placed into the buffer. Bytes arriving from inactive devices are simply discarded and lost. The buffer is cleared each time the active device changes.

    So if you’re thinking of activating an inactive device, is probably is a good idea to process whatever bytes are currently in the buffer before “moving on”. But make sure you’re aware that this won’t prevent future data from being lost if it arrives while the device is inactive.

    Does that make sense?

    Mikal


  27. Stanislav

    16 years ago

    Hi Mikal,
    Its me again :) so.. i still have same problem with BMW IBUS connection – i’m using adapter from Rolf Resler and reading on pc data from ibus, and at the same time i’m reading same data via arduino\NSS.
    Problem is: i’m getting about 1-3 bytes of “right” data and then ~ 3-6 bytes of mess…(typical message size on IBUS is about 8-10 bytes) so i’m usualy getting normal only few first bytes of almost every message….then wrong bytes till end of message, then again good few bytes etc…(i’m reading reference data via Rolf Resler adapter and comparing it with data coming from arduino)
    I’m using arduino nano duo ( ATmega328 16 Mhz).

    I think its because of timers in NSS, is there any way to adjust them(how to calculate right timers) ? What rxcenter rxintra rxstop tx means in NSS ?

    By the way is it possible to implement more RX buffers at cost of memory space for more than 1 NSS device ? (ie change NSS so it will be possible set num of buffers in setup section of sketch)

    p.s. sorry for my bad english.


  28. Mikal

    16 years ago

    Stanislav, what baud rate are you connecting at?

    You certainly could rewrite the serial code so that each object had its own buffer, but that wouldn’t change the fact that two objects cannot receive data (safely) at the same time, so doing so would be pointless.

    Mikal


  29. Stanislav

    16 years ago

    Mikal, 9600.


  30. Hafiz

    16 years ago

    Hi Mikal. noob question here…i’m using sparkfun’s 16×2 LCD (http://www.sparkfun.com/commerce/product_info.php?products_id=9395)
    and im trying to send stuff on the fly using the serial monitor (arduino). This lcd only has 1 connection to arduino…I tried using your library, but it’s not working for me :( help would be greatly appreciated. Thank you


  31. Mikal

    16 years ago

    Hafiz–

    I haven’t tried a serial display, but it should work fine. Don’t forget to connect the grounds of the Arduino and the display together. What exactly is “not working”?

    Mikal


  32. Keith Nasman

    16 years ago

    Mikal,

    I’ve been beating my head against the wall on this. I am trying to set up communication between two arduinos. Here are the sketches for each arduino.

    // Sending arduino

    #include
    #include
    #define rxPin 2 // d2
    #define txPin 3 // d3
    LED led = LED(13);
    NewSoftSerial mySerial(rxPin, txPin);
    void setup() {}
    void loop()
    {
    mySerial.begin(9600);
    mySerial.print(“1”);
    led.blink(1000);
    delay(5000);
    }

    // Receiving arduino

    #include
    #include
    #define rxPin 2 //d2
    #define txPin 3 //d3
    LED led = LED(13);
    NewSoftSerial mySerial(rxPin, txPin);
    void setup() {}
    void loop()
    {
    mySerial.begin(9600);
    if (mySerial.available()) {
    mySerial.read();
    led.blink(2000);
    }
    delay(5000);
    }

    What am I missing?
    Thanks, Keith


  33. Mikal

    16 years ago

    Cool, Keith.

    Just a couple of thoughts: remove the calls to begin() from loop(); these belong in setup(). Also remove the delay from loop on the receiving end. You want the receiver to act immediately whenever a character arrives.

    Make sure the Arduino grounds are connected together and that the TX pins are connected to the RX pins, and I bet it will work.

    Mikal


  34. leosys

    16 years ago

    Hi Mikal,

    Great work.

    At some point you asked about wishlist… Well, configurability, i.e. E,7, 1 style parity, data and stopbit configuration would be appreciated much. Currently I got an FT1.2 enabled KNX/EIB device (BIM113) to listen/talk to. And the FT1.2 protocol seems to require 8 data bits, EVEN parity and 1 stop bit (8E1 if I’m right :-)).

    Any visibility about that? Or could you point a where in your lib to start work on that?

    BR Joe


  35. Keith Nasman

    16 years ago

    Mikal,

    I made the changes you suggested and now the receiving arduino blinks on receive. For the next step I’d like the sending arduino to send the number of blinks to the receiver. Here is the what the receiver is doing:

    int count = mySerial.read();
    for (int blinks=0; blinks < count; blinks++) {
    led.blink(500);
    }

    No matter what number I put in on the sending side, I get one blink. I’ve tried setting the mySerial.print() to pass an integer variable with no success.

    Thanks so much!


  36. Mikal

    16 years ago

    leosys–

    The E71-style configurability is one of the top two feature requests for NewSoftSerial. (The other is support for the Mega.) Conceptually, this wouldn’t be too hard. In the code you’d simply change the loops which count to 8 and make them count to 7 or whatever and then add the parity bit check. I haven’t done this because the changed timing might be a little messy to sort out. I’m afraid I can’t give you visibility yet — too much other stuff going on — but I’d welcome other contributions, if anyone is game… :).

    Mikal


  37. leosys

    16 years ago

    Mikal,

    I made a quick&dirty hack in recv() to ignore the parity bit and write() for 8E1, just to proceed with my project. I used the stop bit timing for the parity bit, and checked it with an oscilloscope @19200. The relevant code fragments below…

    Generally I could think to improve it a bit.
    – begin(): add 2nd parameter with type of parity (Ignore, None, Odd, Even, Mark, Space)
    – recv(): _receive_parity_error flag to indicate a parity error during reception of a byte

    But you are the owner (or maintainer) of the lib. It’s up to you to decide and integrate later on. And I would go ahead only then ;-) No need to work in vain.

    Joe

    void NewSoftSerial::recv()
    {

    // Read each of the 8 bits
    for (uint8_t i=0x1; i; i <don’t care
    // skip the stop bit
    for (uint8_t i=1; i<2; i++) {
    tunedDelay(_rx_delay_stopbit);
    DebugPulse(_DEBUG_PIN2, 1);
    }

    void NewSoftSerial::write(uint8_t b)
    {

    // *JW* hack parity=EVEN
    uint8_t parity= 0;

    if (_tx_delay == 0)
    return;

    // *JW* Calculate parity = EVEN
    for (byte mask = 0x01; mask; mask <<= 1)
    if (b & mask) parity= !parity;

    activate();

    uint8_t oldSREG = SREG;
    cli(); // turn off interrupts for a clean txmit

    // Write the start bit
    tx_pin_write(_inverse_logic ? HIGH : LOW);
    tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);

    // Write each of the 8 bits
    if (_inverse_logic)
    {
    for (byte mask = 0x01; mask; mask <<= 1)
    {
    if (b & mask) // choose bit
    tx_pin_write(LOW); // send 1
    else
    tx_pin_write(HIGH); // send 0

    tunedDelay(_tx_delay);
    }

    // *JW* write parity = EVEN
    tx_pin_write(parity ? LOW : HIGH);
    tunedDelay(_tx_delay);

    tx_pin_write(LOW); // restore pin to natural state
    }
    else
    {
    for (byte mask = 0x01; mask; mask <<= 1)
    {
    if (b & mask) // choose bit
    tx_pin_write(HIGH); // send 1
    else
    tx_pin_write(LOW); // send 0

    tunedDelay(_tx_delay);
    }

    // *JW* write parity = EVEN
    tx_pin_write(parity ? HIGH : LOW);
    tunedDelay(_tx_delay);

    tx_pin_write(HIGH); // restore pin to natural state
    }

    SREG = oldSREG; // turn interrupts back on
    tunedDelay(_tx_delay);
    }


  38. Phlogi

    16 years ago

    Are there any news about supporting the Arduino Mega? Anyone tried to get it working?

    Thanks a lot.


  39. Mikal

    16 years ago

    Phlogi–

    All that’s needed (I think) to get NewSoftSerial working on Mega is for someone to calculate and define these four macros at the top of NewSoftSerial.cpp:

    #define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)NULL)) #define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1)) #define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)NULL)))) #define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14))) Are you sure you need it? The Mega has four "real" serial ports, you know. Mikal


  40. Mark

    16 years ago

    Hello Mikal,
    I have an speed issue.
    While keeping an 5khz pulse running to an stepper motor I need to send my position and other data out via serial port at the same time.
    I was hopeful the NewSoftSerial was faster.
    But NO.

    in my test both the NewSoftSerial and the old Serial use the standard 0&1 pins.
    so I can only run the test once as the old serial will not release.

    Question. Do you have any ideas how I can do my 2 things at the same time?

    here is my test code for the Atmega328

    // Speed test of new Soft Serial
    #include

    NewSoftSerial mySerial(0, 1);
    int ver;
    long val_1;
    long val_2;
    long time;

    void setup()
    {
    // set the data rate for the NewSoftSerial port
    mySerial.begin(57600);
    mySerial.println(“Hello, world?”);
    ver = NewSoftSerial::library_version();
    mySerial.print(“NewSoftSerial::library_version = “);
    mySerial.println(ver);
    mySerial.println(“Speed test for 480 chars begin.”);
    delay(1500);
    }

    void loop() // run over and over again
    {
    //NewSoftSerial mySerial(0, 1);
    mySerial.begin(57600);
    val_1 = millis();
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    mySerial.println(“The quick brown fox jumps over the lazy dog.”);
    val_2 = millis();
    time = val_2 – val_1;
    mySerial.print(“NewSoftSerial takes “);
    mySerial.print(time);
    mySerial.println(” to complete.”);
    mySerial.println(“”);
    mySerial.end();

    delay(1200);

    Serial.begin(57600);
    val_1 = millis();
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    Serial.println(“The quick brown fox jumps over the lazy dog.”);
    val_2 = millis();
    time = val_2 – val_1;
    Serial.print(“Old Serial takes “);
    Serial.print(time);
    Serial.println(” to complete!”);
    Serial.println(“”);

    delay(2000);
    }


  41. Andre Crone

    16 years ago

    I tried to compile this library with the Antipasto Arduino IDE; it’s not working. I am getting several error messages. Has anyone found out how to solve this? I would love to use one IDE for Arduino and TouchShield Slide development.


  42. Mikal

    16 years ago

    Mark, I think you may have a misconception of how serial works. If you need to 500 characters over a 57.6K/N/8/1 serial link, it’s going to take at least 86 milliseconds no matter what kind of software library you use. I don’t see why the stepper library should be incompatible with Serial, but I would always use Serial in lieu of NewSoftSerial whenever you have other stuff in your program that might be time sensitive.

    Mikal


  43. Mikal

    16 years ago

    Andre, can you share the first few error messages? That might give us some idea of what’s involved.

    Mikal


  44. Andre Crone

    16 years ago

    Mikal,

    I get the following error:
    compile(), new thread run about to sketch.handleRun()
    [echo] Building Arduino Diecimila, Duemilanove, or Nano w/ ATmega168 libraries…
    [apply] /Applications/Arduino/hardware/cores/arduino/src/components/library/NewSoftSerial/NewSoftSerial.cpp: In member function ‘void NewSoftSerial::begin(long int)’:
    [apply] /Applications/Arduino/hardware/cores/arduino/src/components/library/NewSoftSerial/NewSoftSerial.cpp:410: error: ‘NULL’ was not declared in this scope
    [apply] /Applications/Arduino/hardware/cores/arduino/src/components/library/NewSoftSerial/NewSoftSerial.cpp: In member function ‘void NewSoftSerial::end()’:
    [apply] /Applications/Arduino/hardware/cores/arduino/src/components/library/NewSoftSerial/NewSoftSerial.cpp:428: error: ‘NULL’ was not declared in this scope

    This looks a bit like the issue regarding the macro’s as mentioned a few replies before mine?


  45. JDMartin

    16 years ago

    Mikal,

    I have a project I’m working on that will have 7 or 8 Arduino AT168 clones, each receiving button and switch inputs. I am then converting the button and switch inputs to actual keystrokes, and then I am sending those to the application on the PC. What I would like to do is have all the Arduino clones communicate their respective keystroke outputs back to a single Arduino, which would do the communicating with the PC. There would only be a single button or switch activated at a time.

    Is this something that could be accomplished with this library?

    Jim


  46. Mikal

    16 years ago

    Jim,

    I’m afraid that that doesn’t sound like a very good app for NewSoftSerial. Unless you knew which of the 7 or 8 Arduinos to listen to in advance, you would lose data.

    Mikal

4 Trackbacks For This Post
  1. 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 […]

  2. side2 » Bimeji Client for Arduino

    […] このソースでは、PS2ライブラリとNewSoftSerialライブラリを利用しています。 コンパイルするには、これらのライブラリを有効にしておく必要があります。 […]

  3. Live Twitter Table using New Bluetooth Shield | Club45

    […] 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 […]

  4. tokyo->kobe->osaka << Motoi Ishibashi

    […] 急遽、Arduinoでシリアル通信をふたつやる必要が発生してホテルで開発。といっても手元にハードがないので、ほとんど勘でプログラムしているようなもの。 次の日現場で試すも、予想通り動かない。そりゃそうだ。 NewSoftwareSerialなんていう便利なものがあるのを後で知った。 […]

Leave a Reply