NewSoftSerial 9 is now available. This is a major new release that replaces all the performance path pin reads and writes with direct Port I/O.
What does that give you? Well, a couple of things. Most importantly, it makes NewSoftSerial more compatible with the latest Arduino release. Changes to timings of digitalRead and digitalWrite in Arduino 0015 broke NewSoftSerial at higher baud rates. All software serial libraries are timing sensitive, and even a microsecond or two change in a function’s timing can introduce enough error to fatally corrupt serial transmissions. By using direct port I/O and retuning all the timing tables, we avoid problems caused by the longer digitalReads and digitalWrites. Furthermore, the library should be more immune to future changes of this kind.
Direct port I/O is amazingly fast — about 10-25 times faster than the equivalent call to digitalRead/Write. Because of this, NewSoftSerial 9 is able to operate reliably at higher baud rates than in the past. In my test suite, I am now able to get reliable RX at speeds up to an unprecedented 57.6K baud on a 16MHz processor and 31.25K baud at 8MHz*. Because the performance paths no longer use digitalRead/Write, they are less sluggish and much easier to tune to the higher speeds.
*These figures are about 70% higher than NewSoftSerial 8 with Arduino 0014. These were measured using USB-powered Arduinos running a prerelease v. 0016 copy of the software, which optimizes the timer 0 overflow counter — an important contributor to software serial performance. I/O was tightly controlled to avoid overflow, which can easily occur at high baud rates when you have no hardware flow control.
Please let me know what you think. The new version is here.
What’s next for NewSoftSerial? Well, there are a number of things being asked for:
- Arduino Mega support
- Signal inversion option
- RTS/CTS flow control option
- Configurability, i.e. “E, 7, 1” style parity, data and stopbit configuration.
What are you most interested in? Let me know here.
Mikal
pete
15 years ago
Hi Mikal,
I’m running into an overflow issue. My scenario is, I’m sending a string of data — about 90 chars or so — every few seconds to the serial port. It accepts the data the first couple times with no problems, then the third time, overflow is true. I’m reading data everytime through the loop if it’s available so I don’t think it could be building up. Any advice on how to solve it?
Thanks.
Mikal
15 years ago
Pete,
I think it *is* building up. There are several solutions I can think of. Slow down your transmitter or speed up your loop by reducing the amount of processing you do after you check for available bytes. Or perhaps check for bytes more often within your loop. If none of these is practical, you could probably solve your problem by increasing the buffer size inside NewSoftSerial to say, 128.
Mikal
pete
15 years ago
Thanks Mikal, I did some further investigating last night. It seems one always comes up with ideas after asking for help :) My project displays data from the serial to an LCD display (using LCD4Bit library). I’m making the LCD scroll if the data is too long and when I comment out the scrolling, I don’t overflow. Again, this was late last night so I’ll verify again today. Thanks for your suggestions, I’ll definitely give them a shot and let you know.
Johan Adler
15 years ago
Maybe I will solve this on my own, maybe it would be useful for others too.
I bought a GPS receiver, a Globalsat BR-355, and I thought it would be easy to interface it with the Arduino since Globalsat clearly states that it uses TTL level serial, and they also inform about the pinout of the PS/2 connector. I have been trying for weeks to get it working, no luck. When connecting it to a computer with a PS/2 to USB cable (sold separately) it spits out NMEA or Sirf binary just as it should.
Today I made a breakout cable and connected the GPS to the computer and to my Saleae Logic analyzer. When I tell the analyzer to use “idle low” instead of “idle high” I get a more meaningful signal, though each bit is inverted (so each hex character xor 0xFF gives the proper ASCII code). I have not done any more testing yet, and I am not sure if “idle high” tells the analyzer to just consider the proper idle state to be logic high, or if it inverts the entire signal. Either way some NSS hacking (or development) or maybe a simple inverter IC might do the trick. Being a software kind of guy originally I might try the soft road first, but on the other hand, if a simple signal inverter makes it compatible with any serial connection this would of course be easier.
Johan Adler
15 years ago
(Guess my earlier comment is still awaiting approval.)
I hooked it up through the inverting buffers of a 74HC240 that I originally bought for BEAM projects. Now it works just fine, through FTDI adapter or from Arduino. :-)
Mikal
15 years ago
Johan, thanks for your contribution. Do I understand correctly that your problem would have been solved if NewSoftSerial had an inverted logic option?
Johan Adler
15 years ago
Mikal, yes it would, I think. But you would need to invert the entire signal, all signal levels. Even for me, being more at home with programming, it seems like a lot of unnecessary work to implement this in software when you can do it in hardware so very very cheap and easily.
I have used 1/4 of the 74HC240 (octal inverting buffer), and according to local prices here in Sweden I guess you can invert about two dozen signals for $1 USD. There might be even cheaper logic inverters, I chose this chip simply because I have a bunch of them around. It does not bother me to solder this chip to a dedicated BT-355 GPS adapter leaving most of the chips capacity unused. It is a cheap and very simple solution to a problem that has been bugging me for weeks now.
Right now I am drawing schematics in Eagle that I will post on my electronics blog (which is in English) later today. My honest and sincere recommendation to you is to skip the software solution to signal inversion, maybe add information about simple hardware solutions to the doc/FAQ, and spend your time and energy on other parts that are less suited for hardware hacks (maybe hardware flow control or different number of data bits, stop bits, parity etc).
I recently started using Mega1280 boards, they are getting cheap on eBay (though if I chose today I would order the new Seeeduino Mega 1280 instead). It has four hw UART:s, and personally I think it will take a long time before I feel the need for any advanced software serial solution for the Mega. My vote would be for a rather low priority for that part.
These are just my personal opinions, and I am sure that you are getting a lot of other input too, and I guess you have personal preferences too, what parts are more fun and interesting to implement.
Thank you for the good work on NSS and the other libraries! (I had a look at your tinyGPS, but think I will use Sirf Binary instead. Maybe I will even be able to produce a library of my own..)
Johan Adler
15 years ago
I just thought of one thing I have missed in NSS — I use LCD displays with serial adapters (from Modern Devices), and they use strict one way communication, one TX pin is all that is needed to talk to it. On the Mega I have digital I/O pins enough, but on the smaller Arduino it does feel a bit silly to reserve both TX and RX pins when I know that I will only be using one of them.
There are probably situations where only an RX pin is needed too, e.g. to listen on a GPS in case you do not need to change any settings.
If others are interested and if you think it could be done I know that I would appreciate having the option to use NSS with one way communication, and actually that would be one thing I would liek to be able to do on the Mega too.
Mikal
15 years ago
Johan,
It is quite common to hook up a “one way” device with NewSoftSerial. To avoid wasting the pin, simply declare a nonexistent pin number for that unused direction. My usual is 255, like this:
NewSoftSerial lcd(255, 3); // tx only
NewSoftSerial gps(2, 255); // rx only
Johan Adler
15 years ago
Thank you Mikal! I was not aware that this was possible!
Adr1an
15 years ago
Hi Mikal, just wondering how far off the version with likely Arduino Mega support? I realise I have 4 UARTs to burn, but for various reasons, I’d like to be able to use NewSoftSerial to get stuff off of the HW Uarts (and reserve them for the high-stream-rate devices….)
Thanks for your great work!
Johan Adler
15 years ago
I did not post when I thought I would, but now you can find the schematics and a lot more information on my English blog (link from my name here).
I still have not tested communication TO the GPS. I inverted that signal too, but I can not yet say if it is correct or not.
Mikal
15 years ago
Adr1an — I’m afraid that Mega support is just about at the bottom of my priority queue for NewSoftSerial. There are just too many other excellent ideas and projects to work on. Anyone want to help with this? Thanks!
Mikal
Mikal
15 years ago
Johan–
Thanks for keeping us apprised.
Mikal
Brian Kennedy
15 years ago
I’m having a problem compiling with the .flush() method in version 9:
I’m using a barebones arduino 328 with editor 0015 and I get the following compile error
“:\Temp\build11860.tmp/Temporary_6801_8399.cpp:39: undefined reference to `NewSoftSerial::flush()'”
I can see the flush method in the source code so I know it exists.
The line in my code is
mySerial.flush();
Help anyone?
Mikal
15 years ago
Brian, I bet if you delete the NewSoftSerial.o file and recompile your sketch (or re-enter Arduino IDE), you’ll resolve your problem.
Mikal
Brian Kennedy
15 years ago
Thanks, Mikal: that’s exactly what happened. I guess when I overwrite NewSoftSerial with newer versions I’ll need to delete the .o file, correct?
By the way, I’m making a communications aid/toy for my disabled son with the arduino and a Vmusic2 – so I thank you, and Patrick thanks you. I started off with a Picaxe but moved over to Arduino because of the advantages of C over BASIC. I’m a bit old (45) to be learning C but help like yours (and all the others involved with the arduino crowd) really removes the learning curve. Thanks again.
SAM
15 years ago
How can I activate and deactivate this “New Software Serial”?
I mean that I have a time sensitive task and I don’t want to stop it for 15 ms because there is an incoming string into software RX pin.
Any suggestion, please?
Pär
14 years ago
Hello Mikal,
I have not tried using NSS yet, but would greatly appreciate if you could explain what configuration possibilities there are. I’m not looking to do 8N1, but 7E1 @ 300bauds. Is that possible?
Cheers,
Pär
Mikal
14 years ago
Pär, I’ml afraid that the only configuration possible with NewSoftSerial currently is 8N1. However, adding configurability, especially for the very common E71, is something that I hope to add in the future.
Regrets,
Mikal
SAM
14 years ago
Mikal, the NSS library is running quite good in my application.
My problem is that I would like to stop for the NSS Rx channel while performing a time-critical task (just another serial transmission through hardware Serial.print()).
Really there would be no problem if this incoming frame is lost, because it will be repeated again and the time-critical task will be done again after 500 ms. The main problem would be to stop the time-critical task.
Maybe it is a bit difficult to understand it, but I want to avoid having a problem.
Thanks,
SAM
Mikal
14 years ago
SAM, another workaroud to try would be to create a second, dummy, NSS instance. When you want to turn off the “real” one, activate the second one like this:
NewSoftSerial nss(3, 2); // the "real" one
NewSoftSerial dummy(255, 255); // the "dummy" one
...
dummy.read(); // <- deactivates your "real" port ... while (nss.available() == 0) // reactivates it ;
Mikal
SAM
14 years ago
Let me understand what are you suggesting:
– I create a virtual “dummy serial port”;
– Whenever I need to perform a time-critical task without being disturbed by a nss RX interrupt, I just call this “dummy.read()”.
But what happens inside the CPU? Does it really kill any incoming SIGNAL from RX line?
Mikal
14 years ago
Hi SAM,
There can only be one “soft” serial port actively receiving at any given time. The active port is whichever one you have most recently called read(), begin(), available(), or print[ln]() on. By activating the dummy port, you deactivate the “real” one.
Your question “does it really kill any incoming SIGNAL from RX line?” is a good one. Currently the answer is, technically, no. Incoming data from the “inactive” port still fires the RX interrupt. However, what happens is that the handler detects that the interrupt was not for the active port, and so immediately returns, keeping the interrupt time to a minimum — just a couple of microseconds. This should allow the parallel processing you need to complete without apparent interruption.
Mikal
SAM
14 years ago
Thanks, Mikal!
SAM
14 years ago
Mikal,
This afternoon I’ve tested your code, so I wrote something like this:
dummySerial.read(); // to stop real nss interrupt
… // begin of my critical section
… // end of my critical section
nss.read(); // restart nss
Unfortunately nss ceases to work and seems to keep deactivated for some seconds.
Any suggestion?
Thanks!
SAM
Mikal
14 years ago
SAM, can you be a little more explicit with regards to what you are seeing? What does “ceases to work” mean exactly?
Mikal
SAM
14 years ago
Hi Mikal!
I’m sorry for my inaccurate language. I meant that wherever my code executes dummySerial.read() it stops nss working. That’s correct, but the bad thing is that nss.read() call doesn’t seem to restablish nss communication.
Let me explain my application:
– there are two serial ports on my Arduino controller: the hw serial is getting and sending data to a high-traffic RS-485 network and the sw serial (my nss channel) is linked to a “serial sensor” (which may send “event-strings”, not continuous like RS-485);
– the weak point of this application is to avoid stopping RS-485 xmit messages whenever the serial sensor receives an event;
– when dummySerial.read() is called, the nss stops as needed and an event comming from the serial sensor is lost. That’s Ok because this sensor will send another one after some milliseconds;
– after some “dummySerial.read() calls, nss.read() function doesn’t wake up again my nss channel. It may remain stopped for some seconds! Maybe it is an unfortunate function and a better option should be nss.print().
Thanks!
SAM
F. Miguel Verde
14 years ago
Thanks Mikal! I’d definitely like to see a 7e1 or variable parity, stop, data bits.
TDG
14 years ago
Hi Mikal,
I’m seeing massive corruption all over the place when trying to use NewSoftSerial with a Wifly GSX at 9600 baud… works fine for me on a Lantronix Xport direct.
Can I contact you to try and establish what is going on?
Cheers
Mikal
14 years ago
TDG- You just did. :)
So you have two devices and ONE of them doesn’t play well with NewSoftSerial? Are the two devices grounded together? What does the “massive corruption” look like?
Mikal
TDG
14 years ago
Hi Mikal – OK! :-) Just didn’t want to spam the comments too much.
I only have one device physically connected at a time, I was using a Lantronix Xport direct for about 6 months with NewSoftSerial and everything worked great..
I swapped it out for a Wifly GSX and now problems…
If I use your demo serial pass thru program, everything works perfect, like so:
> get wlan
< SSID=solar
< Chan=0
< ExtAnt=0
etc…
However, when I try something very simple:
NewSoftSerial wifly(10,11);
void setup() {
Serial.begin(9600);
wifly.begin(9600);
wifly.println(“get wlan”);
}
void loop()
{
if (wifly.available()) {
Serial.print((char)wifly.read());
}
if (Serial.available()) {
wifly.print((char)Serial.read());
}
}
I get weird corruption at the start:
get wleÖLØm¤D=solar
Chan=0
ExtAnt=0
etc…
When I do “get wlan” again in the program above once it’s up and running – no corruption. Am I missing something very obvious?!
Thanks for the great library btw :D
TDG
14 years ago
Actually I also see weird corruption sometimes (randomly) too with the default passthru program, for example:
ls
FL# SIZ FLAGS
11 18 3 WiFly_GSX-2.12
29 1 10 config
30 18 3 WiFly_GSX-2.15
48 19 3 WiFly_GSX-2.17
189 Free, Boot=48, Backup=48
ls
FL# SIZ FLAGS
11 18 3 WiFly_GSX-2.12
29 1 10 config
30 18 3 WiFly_GSX-2.15
48 19 3 WiFly_GSX-¹vÖX`Ì9 Free, Boot=48, Backup=48
Mikal
14 years ago
Hmm… What happens if you put a delay(2000) just before you do the “get wlan” in setup? Does the port need to “settle” for a second before you start sending data?
Mikal
TDG
14 years ago
Get all sorts of strange corruption still:
get wla5¦lµjÒB=solar
Chan=0
ExtAnt=0
get
S6m²iÑ=solar
Chan=0
ExtAnt=0
Strangely it seems to echo part of the ‘get wlan’ back too… not sure why it would do that?
TDG
14 years ago
Any thoughts? :-(
TDG
14 years ago
Sorry! I’ve just realised… I do actually get the corruption if I use serial_passthru and slam enough data at it… the corruption comes in… (for example if I repeatedly fire get wlan at it) – the first time on it’s own usually doesn’t give corruption.
Just to verify, I have hooked the exact same setup to the hardware UART on the arduino (i.e. just using the FTDI) and there’s no corruption no matter how much data I fire at it.
Would definitely seem like an NSS bug to me of some sort (or I’m doing something badly wrong?)
Mikal
14 years ago
I think I may understanding this, TDG. Software serial solutions are delicate beasts. You can’t transmit and receive simultaneously. If you start transmitting a byte and a byte begins to arrive at the same time, the received byte will be corrupted or lost because interrupts are disabled for the duration of the transmitted byte.
Make sure your communication is half duplex, i.e. transmit a request to the device, then wait for the entire response to arrive before attempting another one.
Mikal
Dustin Romero
14 years ago
i was wondering does anyone have some sample code using this nss as a serial multiplexer? i am trying to run 5 rs232 signals into one arduino and multiplex them down a single rs232 line to get split up again by another arduino. is this possible? or am i wasting my time?
TDG
14 years ago
Thanks Mikal but still struggling…
I found an option in the firmware to disable echoing over the UART interface but it isn’t helping…
Definitely not transmitting any data at the time of receiving so genuinely confused – I will try to utilise the CTS pin and see if I can get something with that…
Thanks for the help
TDG
14 years ago
I’ve been trying for weeks now and still the same unfortunately (tried CTS/RTS too)… looks like I may have to give up with NewSoftSerial unfortunately.
I don’t suppose there is any upcoming improvements that would help in any way?
Thanks
TDG
14 years ago
Also why is it always just the first few bytes? It’s always perfectly fine after that…
Nothing is being sent whilst data is being received
Derek S.
12 years ago
Mikal,
I know this is an old thread, but maybe you could help me. I’m using a similar setup to what Johan Alder was using (Arduino Mega 2560 and GlobalSat BR-355 GPS receiver). I’m fairly certain that the GlobalSat BR-355 is spitting out TTL and not RS-232. My voltmeter will tell me tomorrow.
I used your SoftwareSerial.h and it worked as well as my hard serial port, but the inverter changed my junk reception to different junk (junk=8 to 25 seemingly random ASCII characters or corresponding codes 0-255…the good news is that the junk was consistently random so the same random characters showed up routinely in similar positions). I saw a lot of 0’s at the end of my junk sentences, and the inverter cosistently changed them to 255’s.
Here’s my setup statement:
SoftwareSerial ss(rxPin, txPin, true);
Here are some samples of non-inverted receptions:
153
116
156
220
124
116
68
156
0
0
114
250
136
184
153
116
156
220
124
116
100
156
0
0
Now here are some examples of inverted receptions:
12
141
13
237
131
177
193
185
145
193
197
217
177
255
100
108
109
108
155
142
13
179
145
177
205
177
145
177
177
229
197
145
177
177
229
221
35
131
139
171
11
255
Sorry for the long post. Anyhow, can you offer any advice on what might be different from Johan’s hardware inverter and your software inverter (or heaven forbid, my faulty reasoning!)?
Another thought…are you watching for an inverted signal or are you inverting the data after it’s received?
Any help would be appreciated. My next step is to find an inverter IC and wire it inline like Johan did and see if that works.
Thanks so much!
Derek
Mikal
12 years ago
@Derek,
I replied by email, but I do think that GPS is an RS-232 device.
Göran Andersson
11 years ago
Hi Mikal,
Can NewSoftwareSerial be set up for 9 bit data ( no parity, 1 stopbit)? If not it would be most desirable for the near future.