NewSoftSerial Library: An AFSoftSerial update

And using one of those ports looks like what I am going to have to do. Did like having the TouchSlide mount right on top of the Mega as a "shield" but I will get over it. Pin 2 & 3 on the Mega are routed to (OC3B/INT4)PE4 & (OC3C/INT5)PE5 on the ATMEGA1280-16AU.

Keshka

It doesn't compile again ;-(

OS: openSUSE 11.1

i | avr-libc | package | 1.6.6-10.7 | i586 | AVR
i | cross-avr-binutils | package | 2.19-9.1 | i586 | openSUSE-11.1-Oss
i | cross-avr-gcc44 | package | 4.4.0_20090604-15.3 | i586 | AVR

error:

NewSoftSerial.cpp:54: warning: only initialized variables can be placed into program memory area
/tmp/cc5IqSje.s: Assembler messages:
/tmp/cc5IqSje.s:229: Error: register r24, r26, r28 or r30 required
/tmp/cc5IqSje.s:282: Error: register r24, r26, r28 or r30 required
o: In function main': undefined reference to NewSoftSerial::NewSoftSerial(unsigned char, unsigned char)'

There is one option though:

You can also install gcc43, then it works again as it then uses gcc43, but you need to keep gcc44 or it will downgrade avr-libc and that gets some more dependency hell going ;-(

Simple newbie question..
Does NewSoftSerial use Timer2 at all?

Thanks,
Paul

Nope. :slight_smile:

Mikal

Hi,

I am new to Arduino and need multiple serial ports, but I have a question about NewSoftSerial: the page at Arduiniana says that you can only use one serial device at a time, and have to designate one as "active" at any given time. Does this mean the buffer cannot receive data from the inactive devices? I have a setup where it is unpredictable which serial devices will chime in next and when, so I can't declare ahead of time--I need to "listen" to all of them, all the time. Will NSS not work for me, or does the "one at a time" rule only apply to READING the buffer, not the buffer accumulation itself?

Also, is there any documentation to NSS that lists all the functions you can call, and how they work, sort of like the "Reference" section of the main Arduino page?

Sorry if these questions are dumb, I'm a newb. Thanks in advance!

Hi p53--

Your question is far from dumb.

I'm afraid the "one at a time" rules applies to the actual reception of the data and not just to when you check the buffer. The reason is this. If two devices are connected via "soft" serial ports, we have to assume that they are transmitting independently to the Arduino. As you say, it is entirely unpredictable when a byte might arrive from either one. But reliable reception on a software port requires that the whenever a byte arrives, the processor is 100% occupied in receiving it. So you see, if two bytes arrive from the ports at close to the same time, the processor can either abandon the partly-finished byte that arrived first to process the second, or ignore the second in favor of the first, but it cannot process both at once.

That's why you can't actively receive on two ports at once.

However, there are many successful designs out there where, say, you monitor the serial GPS device for a while, perhaps processing a single sentence, and then make your XBee active for another while. You might also see if one of the devices might be attached instead to a hardware port.

I hope some of this helps. I'd like to help your project succeed.

To answer your last question, no, I have long wanted to add a "reference" section to all my Arduiniana libraries, but unfortunately the project has not yet bubbled up to the top of my priority stack.

Good luck!

Mikal

Mikal,

Thanks, that makes sense. I was hoping that maybe there was some magic beyond the horizon of my understanding that would make simultaneous reception possible, but that was wishful thinking. I'll try to come up with a synchronized scheme whereby each device holds off until its "turn" to "speak"--I think this may be feasible without losing any data. The other devices are actually other Arduinos, so I can probably program them to wait, and then say everything in bursts.

Thanks for all your voluntary hard work on this! No rush on the Reference page, I think I can figure out what I need from the included code examples.

Patrick

Patrick, I happen to be working with this multi-port receive issue in some writing I'm doing. Perhaps this sample sketch might give you an idea how you might structure your code. This kind of solution isn't for everyone, but it might be enlightening.

Here I have an XBee radio that I am listening for input on. As soon as I get a 'y' from the radio, I want to note my position, as defined by the serial GPS device I also have connected. Here's a solution that will work with NewSoftSerial:

#include <NewSoftSerial.h>
const int rxpin1 = 2;
const int txpin1 = 3;
const int rxpin2 = 4;
const int txpin2 = 5;
NewSoftSerial gps(txpin1, rxpin1); // gps device connected to pins 2 and 3
NewSoftSerial xbee(txpin2, rxpin2); // gps device connected to pins 2 and 3

void setup()
{
  gps.begin(4800);
  xbee.begin(9600);
}

void loop()
{
  if (xbee.available() > 0) // xbee is active.  Any characters available?
  {
    if (xbee.read() == 'y') // if xbee received a 'y' character
    {
      unsigned long start = millis(); // begin listening to the GPS for 10 seconds
      while (start + 100000 > millis())
      {
        if (gps.available() > 0) // now gps device is active
        {
          char c = gps.read();
          // *** process gps data here
        }
      }
    }
  }
}

After 10 seconds of processing GPS, it returns to listening to the XBee. This paradigm isn't for everyone, but something similar might work for you.

Mikal

NewSoftSerial V9 doesn't compile on openSUSE 11.2

i | avr-libc | package | 1.6.7-4.2
i | cross-avr-binutils | package | 2.19.51-16.1
i | cross-avr-gcc44 | package | 4.4.1_20090817-17.1

The offending code:

inline void NewSoftSerial::tunedDelay(uint16_t delay) {
  uint8_t tmp=0;

  asm volatile("sbiw    %0, 0x01 \n\t"
    "ldi %1, 0xFF \n\t"
    "cpi %A0, 0xFF \n\t"
    "cpc %B0, %1 \n\t"
    "brne .-10 \n\t"
    : "+r" (delay), "+a" (tmp)
    : "0" (delay)
    );
}

Same error about some registers as posted before.

Thanks for making, this it's awesome!

With regards to the error above, the offending line is the "sbiw %0, 0x01 \n\t". I'm messing around with alternatives, I found some place that suggests manually moving %0 into a register before calling sbiw which I'll try soon.

edit: 64bit linux, GCC 4.4.2, avr-gcc 4.4.1. I don't know what I'm doing so I gave up on my mov r30, %0 and sbiw r30, 0x01 idea.

Hmmm... Thanks for the analysis. It may be tricky to modify it to work correctly with GCC 4.4 AND still maintain the correct timing.

-- Mikal

If only the register naming of inline assembler didn't suck that much... I swear I've read more than one manual regarding this and it still is pretty obscure stuff.

I wonder if the best solution for NewSoftSerial would be to abandon this little tunedDelay() function and migrate over to DelayMicroseconds().

Mikal

Hello,

sorry for this "necro post", but I'm running out of ideas.
I'm trying to interface an arduino with a bluetooth chip, enabling the arduino to talk to my computer (over bluetooth).
I'd like to describe the situation / problem first, I'll give a short list of technical data at the bottom. All help is appreciated.

I have an arduino that I have hooked up to a bluetooth device, I'm trying to make the arduino talk to my computer (which also has a bluetooth device, obviously). I have tried the SoftwareSerial library, which doesn't appear to ever see anything it can read, a custom method that is based on a interrupt on the rx pin, trying to read the bits as the fly past (to my understanding this is also how NewSoftSerial reads data), aswell as the SoftwareSerial library.
I can send data to my laptop without problems, it arrives just as I send it (with a quirk of inverted linebreak/newline characters, but thats a quirk of the bluetooth chip I reckon), the receiving data on the arduino side is the problem.
SoftwareSerial denies the existance of ever seeing anything arrive.
The NewSoftSerial however, shows promise.
While calls to the available() method say that it has nothing to read, pure calls to the read() method give back invalid values (-1, no byte found). But this is the part where I see promise, because it will print a number of error bytes based on the number of characters I sent to the arduino (bluetooth device).
ie: I send a message "hello" to the arduino, the arduino would print 5 times a -1 value to the computer through its hardware serial.
This tells me that it is receiving something, but I have the feeling it doesn't know what it is it is trying to read..
Any insights and help regarding the matter would be most appreciated!

The sketch(es), in case it yields any information regarding the issue:

#include <NewSoftSerial.h>

NewSoftSerial mySerial = NewSoftSerial(2, 3, false);

void setup()
{
  pinMode(2, INPUT);  //softserial rx
  pinMode(3, OUTPUT); //softserial tx
  pinMode(4, OUTPUT); //reset pin of the bluetooth module
  pinMode(5, INPUT);  //"has a connection" pin of the bluetooth module
  pinMode(8, OUTPUT); //led
  
  Serial.begin(9600);
  mySerial.begin(9600);
  delay(500);
  digitalWrite(4, LOW);
  delay(1800); //reset the bluetooth module for at least 1500ms
  digitalWrite(4, HIGH);
  mySerial.print("ats+10=1\n\rat+btmode,3\n\rat+btname=Arduino\n\rat+btscan\n\r");
  delay(500);
  Serial.println("ready");
}


void loop()
{
//most basic attempt, which prints a number of -1's equal to the number of characters sent to the arduino
  //Serial.print(mySerial.read());

//basic test attempt, doesn't print anything on Serial
  if(!digitalRead(5)) //this pin goes HIGH if the bluetooth device has a connection
  {
    digitalWrite(8, HIGH); //light up a LED
    mySerial.print("la\n\r");
    if(mySerial.available())
    {
      Serial.println(mySerial.read());
    }
    delay(100);
  }
  else
  {
    digitalWrite(8, LOW); //no connection, turn off the LED
  }
}

Technical details:

  • OS of computer: ubuntu 9.10
  • class2 transmitter
  • Arduino IDE version 16
  • NewSoftSerial version 10
  • DFRduino duemilanove with atmega328 chip
  • promi-ESD bluetooth chip
  • 9600bps baud (baud rate of 9600, I assume?)
  • 8 data bit, no parity, stop bit 1
  • H/W flow control
  • 3.3v input voltage (a custom chip drops the arduino voltages for safe interfacing)
  • pulls 73mA in its most power hungry state
  • class1 transmitter

Hi, running your example program:

#include <NewSoftSerial.h>

NewSoftSerial mySerial(2, 3);

void setup()
{
Serial.begin(57600);
Serial.println("Goodnight moon!");

// set the data rate for the NewSoftSerial port
mySerial.begin(4800);
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());
}
}

I've got two PUTTY windows open, the hardware uart is on COM3, and the SoftSerial is on COM4 on pins 2, 3. Both windows print out their greetings fine. When I type on COM3, I see the characters echoed on COM4 tty. However, when I type on COM4, I don't see anything echoed back to COM3.

COM3 is going to a tested FTDI, COM4 is a Modern Device P4, going to a Profile RS232->USB cable. Both have been tested for uploads with Arduino.

Hard to say for sure, but the appearance of that RS-232 worries me. I suspect either a voltage level problem (RS-232 is different than TTL) or perhaps the RX wire is not correctly connected to pin 2.

Mikal

I located the culprit.
It was something related to timing (as I expected), though it was of a rather unexpected cause..
Found the problem thanks to this topic: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1268626974
Turns out that the read() method of NewSoftSerial also needs a tiny delay in order to get the actual value.

Still a bit annoyed that this isn't documented, but that'll pass.
Now the whole world of the arduino will open for me =)
Thank you to anybody who spent time trying to solve my conundrum.

This is regarding the inability to get serial binary data at 4800N1 from a W800RF32 unit from an earlier post.
http://www.wgldesigns.com/w800.html
http://www.wgldesigns.com/protocols/w800rf32_protocol.txt

I'm able to see it's serial data when connected to a standard PUTTY console window. The characters are 'garbage' as expected because it's binary data.

I'm also able to demonstrate that my circuit & sketch can read data at 4800N1 from a serial console window (connected to RX=2, TX=3).

But Serial.available() never returns > 0 when I connect the W800RF32A to the serial input. If I don't use Serial.available() and just try a read, I only get 0xFF.

I'm starting to suspect that flow control is playing a role here. The makers of the W800RF32 (wgldesigns) state that only TX/RX (and GND) are used by the unit. However, is NewSoftSerial being thrown off by the binary serial data? (By the way, I've tested with SoftwareSerial - same result).

Is NSS using software flow control that is being tickled by the binary data? (XON/OFF).

Any working example for reading serial binary data?

-creatrope

Solved!

Nothing to do with flow control, it was the old serial culprit, forgetting to take into account DCE and DTE units. With a NULL modem dongle installed between the Arduino's serial adapter and the W800RF32A, I started seeing valid serial data - from there getting the W800RF32A was a snap.

-creatrope

Hi,
i'm developing a university thesis and i need RTS/CTS control flow. my device talks at 38.4K bps.
from Mikalhart's (NewSoftSerial) posts i noticed at this rate TX is OK but RX is 99.9%.
2 questions:

  • is it the ONLY library using RTS/CTS pins?
  • what is the AFSoftSerial?

thank you,
mario