1

i am having trouble getting data from two sensors using two software serial ports with an arduino board. I noticed a similar question might have been asked before but the answers suggest it can't be done and I know fully well it can based on the example here (http://arduino.cc/en/Tutorial/TwoPortReceive)!

I am using an arduino ethernet. The devices I am trying to get data from include a GPS and an IMU both from sparkfun.

I can get data from either devices using just on software serial port but as soon as I add the second software serial port, neither ports will work. I can't use the hardware serial port because that is being used byt another device.

My code is exactly similar to the example:

#include <SoftwareSerial.h>

SoftwareSerial portOne(7,8);
SoftwareSerial portTwo(5,6);

void setup()
{
  Serial.begin(9600);


  portOne.begin(9600);
  portTwo.begin(9600);
}

void loop()
{

  portOne.listen();
  while (portOne.available() > 0) {
    char inByte = portOne.read();
    Serial.write(inByte);
  }

  delay(500);

  portTwo.listen();
  while (portTwo.available() > 0) {
    char inByte = portTwo.read();
    Serial.write(inByte);
  }

  Serial.println();
}

Anyone with any ideas?

Dyps
  • 91
  • 1
  • 3
  • 10
  • Can you give us more information about how it doesn't work? – Jeff Sep 18 '12 at 15:51
  • I somehow got it working, you have to set the pin states i.e. Receiving pin as input and transmitting pin as output. – Dyps Sep 21 '12 at 15:18

3 Answers3

3

This code will not work, or will work poorly if it works at all. SoftwareSerial only has one internal buffer. Yes, you can have multiple SoftwareSerial objects in existence, but only one of them controls the internal buffer. When any RX pin gets asserted, that generates an interrupt, but only the listen()ing RX pin gets checked for a start bit.

What's really needed is the ability to check on multiple pins when an interrupt comes along from the start bit. Then you'd have to set up pointers to the appropriate data structures. It would be complicated, but possible.

Or maybe just give up on interrupt-driven reception, and spin on checking both/all of the RX pins, and start the receive based on the pin you see. Be forwarned that this code has much hair, and you WILL need an oscilloscope to make it work.

I'm having a similar problem, which is why I found your sensor. After talking it over with my co-workers, we've decided to read our sensors in rotating order. Our sensors report the current state of the sensor, and not specific events, so it's okay if we lose some reports. So we'll read from port 1, then read from port 2, then port 1, etc. Our sensors spit out lines of text, so we know when to switch to the next sensor.

  • 1
    thanks for your answer. Can you please provide some codes to demonstrate your rotating order concept? – Dyps Apr 18 '13 at 14:33
1

The referenced example only actively listens to one port at a time. The recommended solution would be to upgrade to an Arduino Mega (https://www.sparkfun.com/products/11061) which has 4 hardware serial ports.

In order to simultaneously support two software serial ports is going to require a lot of the CPU resources. It also be a difficult design and excessive programming time far outweighing the cost of $58 + shipping.

Looking at you code again it occurs to me that you are immediately checking for characters after your portOne.listen command. At 9600 baud it will take approximately 1ms for the first character to arrive, your while test will have been completed and the portTwo.listen command executed long before the first character arrives.

For testing purposes try adding a 1-2 ms delay after the portOne.listen command and see if you get a character.

As an example (untested and note, if port one is sending characters with no intercharacter gaps, the first while will never fail, preventing reading portTwo characters):

void loop()
{

    portOne.listen();
    delay(2);
    while (portOne.available() > 0) {
        char inByte = portOne.read();
        Serial.write(inByte);
        delay(1);
    }

    portTwo.listen();
    delay(2);
    while (portTwo.available() > 0) {
        char inByte = portTwo.read();
        Serial.write(inByte);
        delay(1);
    }
    Serial.println();
}
Jeff
  • 1,364
  • 1
  • 8
  • 17
  • Are you saying, the above code doesn't work? I am only listening on one port at a time. – Dyps Sep 18 '12 at 08:26
  • I should say I have not tried to do this. I would it will work as long as you open port one, receive data, close port one, open port two, receive data, close port two, then repeat. It will still use more micro resources then two hardware ports, however depending on the micro loading and the rest of your firmware that may not be a issue. – Jeff Sep 18 '12 at 15:46
0

Don't use while ......

Use:

  {     portOne.listen();

   if (PortOne.available() ) {
       ricevo = myPort1.read(); }

   // delay(2);   // ridiculos waiting time
   // delay(1);   // extra ridiculos waiting time

Than 500 ms is a too big time for switching, no time.....

david
  • 1