Go Down

Topic: YunServer + SoftwareSerial = periodic hangs (Read 7481 times) previous topic - next topic

skr1

Nov 01, 2013, 01:19 pm Last Edit: Nov 01, 2013, 01:23 pm by skr1 Reason: 1
Hi all,

I have some periodic hangs if I combine the YunServer and the SoftwareSerial in my application.
My application is using the YunServer to publish sensor data which is collected by some XBee nodes. The SoftwareSerial is used to communicate with a XBee module which is mounted on a Sparkfun XBee shield.
I have written a demo application which combines the YunServer and the SoftwareSerial in the same way like in my production application and the hangs are also reproducable in the demo application.
For debugging, my loop method writes into a log file every 10 seconds and I can see the hangs clearly.
While the loop method hangs, it is not possible to make a web request to the arduino via the Bridge. In this case I receive an http error 500.
Here is my demo code:

Code: [Select]
#include <SoftwareSerial.h>
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#include <FileIO.h>

// Software Serial
SoftwareSerial _serial(8, 9); // RX, TX

// Webserver
YunServer server;

const char* LOGDIRECTORY = "/mnt/sd/arduino/www/BridgeTest";
const char* LOGFILENAME = "/mnt/sd/arduino/www/BridgeTest/log.txt";

unsigned long _loopMillis = 0;

void setup()
{
 _serial.begin(9600);
 
 Bridge.begin();
 server.listenOnLocalhost();
 server.begin();

 FileSystem.begin();

 // Wait till the FileSystem-service is started
 while (!FileSystem.exists(LOGDIRECTORY))
   delay(1000);

 // Wait thill the clock is synchronized via NTP
 while (getDateTime().startsWith("08/08/13"))
   delay(1000);

 writeToLog("Setup");
}

void loop()
{
 if(getElapsedMillis(_loopMillis) > (unsigned long) 10000)
 {
   writeToLog("Loop");
   _loopMillis = millis();
 }
 
 String startTime = getDateTime();
 unsigned long startMillis = millis();
 
 processXBeePackets();
 
 if (getElapsedMillis(startMillis) > (unsigned long) 5000)
   writeToLog("processXBeePackets() took more than 5 seconds! Action started at " + startTime);
 
 startTime = getDateTime();
 startMillis = millis();
 
 processWebRequests();
 
 if (getElapsedMillis(startMillis) > (unsigned long) 5000)
   writeToLog("processWebRequests() took more than 5 seconds! Action started at " + startTime);
 
 delay(50);
}

void processXBeePackets()
{
 if (_serial.available())
 {
   while(_serial.available())
   {
     int inByte = _serial.read();
   }
 }
}

void processWebRequests()
{
 YunClient client = server.accept();

 if (client)
 {
   String command = client.readString();
   command.trim();
   command.toLowerCase();
   
   if(command == "clearlogfile")
   {
     clearLogFile();
   }
   
   client.print("Your command was: " + command);
 
   client.stop();    
 }
}

unsigned long getElapsedMillis(unsigned long milliseconds)
{
 unsigned long currentMillis = millis();
 unsigned long elapsedMillis;

 if (currentMillis >= milliseconds)
 {
   elapsedMillis = currentMillis - milliseconds;
 }
 // Es gab einen Überlauf des Wertebereiches!
 else
 {
   elapsedMillis = ((unsigned long) 4294967295 - milliseconds) + currentMillis;
 }

 return elapsedMillis;
}

void writeToLog(String message)
{
 String dateTime = getDateTime();
 File file = FileSystem.open(LOGFILENAME, FILE_APPEND);

 if (file)
 {
   file.println(dateTime + ": " + message);
   file.close();
 }
}

void clearLogFile()
{
 FileSystem.remove(LOGFILENAME);
}

String getDateTime()
{
 String dateTime;
 Process time;
 time.begin("date");
 time.addParameter("+%D %T");
 time.run();

 while (time.available() > 0)
 {
   char c = time.read();
   if (c != '\n')
     dateTime += c;
 }

 return dateTime;
}


Here is my log file:
11/01/13 12:46:11: Setup
11/01/13 12:46:18: Loop
11/01/13 12:46:28: Loop
11/01/13 12:46:39: Loop
11/01/13 12:46:49: Loop
11/01/13 12:47:00: Loop
11/01/13 12:47:10: Loop
11/01/13 12:49:15: Loop
11/01/13 12:50:04: Loop
11/01/13 12:50:14: Loop
11/01/13 12:50:25: Loop
11/01/13 12:50:41: Loop
11/01/13 12:50:51: Loop
11/01/13 12:51:02: Loop
11/01/13 12:51:13: Loop
11/01/13 12:51:24: Loop
11/01/13 12:52:32: Loop
11/01/13 12:52:43: Loop
11/01/13 12:52:53: Loop
11/01/13 12:53:04: Loop
11/01/13 12:53:14: Loop
11/01/13 12:53:26: Loop
11/01/13 12:53:37: Loop
11/01/13 12:53:47: Loop
11/01/13 12:53:58: Loop
11/01/13 12:57:47: Loop
11/01/13 12:57:58: Loop
11/01/13 12:58:08: Loop
11/01/13 12:59:19: Loop

Can someone explain what is wrong with my code?
Thanks in advance!

Bye,
Sebastian

federicofissore

Can you try the latest nightly build of the IDE? We included a fix in Bridge that solved a similar issue

skr1

Hi Federico,

I have tested this with the nightly build from yesterday night and the same behavior appears.
Can you explain how the Bridge internally works and what could interfere with the SoftwareSerial?

Thanks!
Sebastian

mamu

Have you tried this:
Code: [Select]
  if (client) {
    client.setTimeout(5);
   ...

This hint from Federico helped in my project.

federicofissore

Hi skr1, I've run your sketch for half an hour and it behaved as expected, without big latencies between runs (I don't have an xbee module though)
How long does it take yours to show that weird behaviour?

Rutgero

Hello,

It looks I am having quite the same problems. Mostly it happens after quite a lot of hours. Like 8-30 hours. Also with the nightly from two days ago.

The strange thing is that I am still able to connect via ssh(/http). When I do this 'route' does not show the default route anymore. So any external http call will not succeed.
(In my test environment I only use eth1. wireless is on 'master' modus)

When I do:
route add default gw 192.168.1.1 eth1
will correct the problem temporarily.

But '/sbin/reboot' does mostly NOT work anymore after this has happened. Ssh connection is closed and will not recover (no ping, no ssh, no arduino output).

I am trying to make an example with a shorter period to 'crash'.

Kind regards.

skr1

Hi Federico,

I have played again with my demo sketch and I figured out that the hangs only occur if serial data is received!
I have connected the XBee shield to the Yun via the digital pins 8 (RX) and 9 (TX) and it takes only a few minutes when the first hangs occur. Then, I have disconnected pin 8 (RX) and everything worked fine. I kept the sketch running for an hour and everything was stable.
So, it has definitely to do with the serial data. I have 5 XBee nodes which send a IO sample every minute to the XBee coordinator which is connected to the Yun.
Could you simulate this load with a Arduino UNO which generates some test data and which you connect to the pins 8 and 9 of the Yun?
Could it be that the hangs have something to do with the interrupt which is used by the SoftwareSerial?

@Fred: It seems that you have another network related problem.

Bye,
Sebastian

cmaglie


I currently have no clue on what the problem may be, but maybe its worth a to try with AltSoftSerial?

http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html

C.

skr1

Hi cmaglie,

this is a good idea! I had a look into this, but it seems that the Yun is not yet supported by this library. If I use this library, I get an error because the header file "known_boards.h" does not contain some "Yun specific" defines.
Do you know which defines I have to set for the Yun?
Thanks!

cmaglie


Try to add this snippet to the board list:

Quote

// Arduino Leonardo or Arduino Yun
//
#elif defined(ARDUINO_AVR_YUN) || defined(ARDUINO_AVR_LEONARDO)

//#define ALTSS_USE_TIMER1
//#define INPUT_CAPTURE_PIN        4  // receive
//#define OUTPUT_COMPARE_A_PIN     9 // transmit
//#define OUTPUT_COMPARE_B_PIN     10 // unusable PWM
//#define OUTPUT_COMPARE_C_PIN     11 // unusable PWM

#define ALTSS_USE_TIMER3
#define INPUT_CAPTURE_PIN      13 // receive
#define OUTPUT_COMPARE_A_PIN        5 // transmit


I derived this one from the lib specification but I've not tried on the real hardware yet.

Note that you must use pin 13 for RX and 5 for TX.

Alternatively you can disable TIMER3 and enable TIMER1  (by commenting/uncommenting the relative sections), in this case you can use pin 4 for RX and pin 9 for TX, but you lose PWM functionality on pin 10 and 11.

C.

skr1

Hi cmaglie,

thanks for the configuration! Now it is working since two days without any hangs!  :D

I am using pin 13 for RX and 5 for TX. I have attached a picture so that everyone can see how the Sparkfun XBee shield is now connected for using the AltSoftSerial library.

Although I have a working solution now, it would be great to figure out why the SoftwareSerial library is producing hangs. What is the main difference between both libraries? AFAIK, the SoftwareSerial library is using an interrupt. Is there a problem because I am using only 9600 baud for communicating with the XBee module?

Bye,
Sebastian

cmaglie

Cooool! :)

I read that SoftwareSerial disables interrupts while it's receiving characters from the emulated com port.
Running at low speeds means that it keeps interrupts disabled for long time (low speed => longer bit duration), this may be the reason why you are experiencing  the hangs, but I can't explain myself why it doesn't resume normal operation aftwards, I expect that the hang should be temporary.

For a final answer we should do a more deep debugging session but, at this point, I guess that it will hardly happen ;)
C.

skr1

I am really happy that everything is working now!  :D
Thanks again for the great support!

What you say about the interrupt sounds reasonable. Maybe I (or someone else) will test the SoftwareSerial library with a higher baud rate.  ;)

Sea2605

Same problem here.

I am/was successfully connecting to a HC-05-Bluetooth-Module over SoftSerial (Pins 9 and 10) and then wanted to use REST with Bridge+YunServer+YunClient and also got reboots... Altsoftserial didn't help ( included the standard altsoftserial sketch code and connected to Pins 5 an 13)... Could you explain what you mean with "board list"? If I paste your code into the Sketch I get an error "#elif without #if" ...

sonnyyu

#14
Mar 28, 2014, 04:05 pm Last Edit: Mar 28, 2014, 04:10 pm by sonnyyu Reason: 1
Code add into "known_boards.h". It is altsoftserial based solution.

Go Up