7

My Due webserver was working perfectly fine for months when connected to Linux via the native port.

But when connected to Windows 10 via the native port, if the Arduino webserver is idle for about 5 minutes (when no client calls a webpage), then there is a strange 5-10 second delay before the webpage is able to load. This delay doesn't happen when connected to the webserver via the programming port.

It almost seems like maybe Windows is putting the port to sleep when it notices an idle delay, and then it has to wait for the port to wake up before it can call the webpage.

On the Windows "Power Settings" I set the computer to never go to sleep, and also in the Power "Advanced Settings" I disabled the USB "selective suspend".

Do you have any ideas why there would be this strange delay only on Windows and only when connected via the native port?


ADDITIONS: I made a simplified example that reproduces the problem on my machine. I wonder if anyone can see any problems with this code.

First, the python code. Note that if the python script is never run, there are no delays on the Arduino webserver, and everything works as expected.

import serial, sys

SERIALPORT = "COM5" # Change this to your serial port!

# Set up serial port
try:
  ser = serial.Serial(SERIALPORT, 115200, timeout=0)
except serial.SerialException:
  sys.exit()

ser.write("Hello World")
print("Hello World")

ser.close()

And below is the simplified Arduino code. It's just a simple webserver that serves a page that has a "reload" button that reloads the page. You can hit "reload" as many times as you want, and the program never freezes. But if you run the python code above and then try to reload the page, there is a long delay (anywhere between 10-60 seconds by my current estimate).

If you comment out all of the "SerialUSB.print" lines that are anywhere in the loop (in this simplified case, there's only 1 line at: "SerialUSB.println (data);" in the processData function), then the webpage never freezes, even if you run the python code frequently.

In my real-world example, my python code was running once a minute, causing random freezes. If I stopped the python code from running, then there were no more freezes on the webpage. I ended up commenting out all of my SerialUSB.print statements that were in the loop, and that way I could have the python code running on schedule, and my program had full functionality (except for the loss of SerialUSB.print).

#include <Ethernet.h>

byte mac[] = {
  0x04, 0xBA, 0xB0, 0xCC, 0xDF, 0x04
};
EthernetServer server(80);
EthernetClient client;

const byte MAX_INPUT = 25; //for processIncomingByte

void setup ()
{
  SerialUSB.begin (115200);
  Ethernet.begin(mac);
  SerialUSB.print("server is at ");
  SerialUSB.println(Ethernet.localIP());
}  // end of setup

bool processIncomingByte (const byte inByte)
{
  static char input_line [MAX_INPUT];
  static unsigned int input_pos = 0;
  switch (inByte)
  {
    case '\n':   // end of text
      input_line [input_pos] = 0;  // terminating null byte
      if (input_pos == 0)
        return true;   // got blank line
      // terminator reached! process input_line here ...
      processData (input_line);
      // reset buffer for next time
      input_pos = 0;
      break;
    case '\r':   // discard carriage return
      break;
    default:
      // keep adding if not full ... allow for terminating null byte
      if (input_pos < (MAX_INPUT - 1)) input_line [input_pos++] = inByte;
      break;
  }  // end of switch
  return false;    // don't have a blank line yet
} // end of processIncomingByteWeb

void processData (const char * data)
{ //Note: since there are no GET requests in this simple example, I removed the parts for processing GET.
  SerialUSB.println (data);
  if (strlen (data) < 4)
    return;
}  // end of processDataWeb

void loop ()
{
  client = server.available();
  if (client) {
    boolean done = false;
    while (client.connected() && !done)
    {
      while (client.available () > 0 && !done)
        done = processIncomingByte (client.read ());
    }  // end of while client connected

      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println();
      client.print("<html><body>");
      client.print("<a href=\"/\">Reload</a></body></html>");
      delay(10); client.stop();
  }
}  // end of loop

This is not technically a problem for me anymore, except for having had to comment out all my "SerialUSB.print" statements. But I am interested in learning what is causing this strange behavior.

Note: the "processIncomingByte" and "processData" functions are mainly from Mr. Gammon's writings and tutorials, and they are working flawlessly for me in 2 other Arduino webservers I have running. I wanted to note this because if I had written the functions myself, then obviously they would require much more scrutiny.

Jerry
  • 523
  • 1
  • 6
  • 21
  • How does the USB port relate to the Due running as a webserver?! – Majenko Dec 01 '15 at 21:14
  • Good point! I guess that adds to the mystery! I can't figure out why there would be a delay (only after being idle) with the native port, but no delay with the programming port... and only on Windows. – Jerry Dec 01 '15 at 21:23
  • 4
    But you still haven't mentioned *how* you are making the Due a webserver. It's a subtle hint to say "**We need to see and understand your setup and your code**" before we can help you out. – Majenko Dec 01 '15 at 21:24
  • I'm sorry. I'm using an ethernet shield. This setup was working flawlessly for months on Linux, and works fine on Windows only when the Due is connected via the programming port. My code is too long to post or to simplify for the forum, but basically it's nothing unique, and it's mostly just using code from Nick Gammon's tutorials. I prefer to have it connected via the native port because some of my push-buttons send keystrokes to the computer. I rarely push those buttons (only once or twice a day), so it's doubtful that the sending of the keystrokes is related to the delay. – Jerry Dec 01 '15 at 21:32
  • Re "My code is too long to post" -- arduino.stackexchange pages use scrolling windows to display code. If the problem is a code issue, show the code. People who answer questions effectively often like to determine for themselves what can be ruled out – typically they've seen hundreds of instances where someone says, "It can't be that" but it is – James Waldby - jwpat7 Dec 01 '15 at 21:59
  • Okay, thanks for the advice. I'll try to format the code for posting here later. It will take me a while though, so I don't imagine I'll get it done until tomorrow. – Jerry Dec 01 '15 at 22:16
  • I found out some new important info: There's a python script that sends data to the Due via the serial port every minute. When I stop the scheduled task from running the python script, there are no more delays for the webserver. Whenever I had attached the Due via the programming port, I didn't have the python script send the data to that port, and I'm pretty sure that's why there was never a delay with the programming port. When I edited the python script to send data to the Due's programming port number, it had the effect of resetting the Due every minute. (cont...) – Jerry Dec 02 '15 at 01:50
  • So when the Due is connected via the native port the python script ends up causing it to have long delays. When it's connected via the programming port the python script causes the Due to reset once every minute. When the python script is disabled then there are no problems. I'm pretty sure this is a problem with my python code, so I'm not sure if it belongs here. I was having other problems porting my python code to Windows, and I learned that python scripts need some modifications when moving from Linux to Windows. BTW the script basically sends weather and email data to the Due. – Jerry Dec 02 '15 at 01:53
  • 1
    If your Due program is written properly then it shouldn't cause any delays. If it's not written properly (and serial code so often is *not* written properly) then it's possible to see delays. Post your Due code - at least the portion of it that deals with the serial. – Majenko Dec 02 '15 at 11:29
  • Thanks @Majenko. I think I narrowed it down, and soon will be able to share some code that replicates the exact problem. Basically the sketch only freezes on `SerialUSB.print("whatever");`. When I comment all of those out of my code, then everything works perfectly. There seems to be no problem with `Serial.print` or `Serial2.print`. – Jerry Dec 02 '15 at 16:53
  • I made a simplified version that reproduces the problem, and added the code to the post above. Thanks everyone for reading! – Jerry Dec 09 '15 at 14:01
  • Consider an alternative approach to the problem. I lost about a weeks worth of work assuming Windows 7 networking worked. When I used wireshark (on the Windows computer and on an independent Linux computer connected using an Ethernet Hub), I found that Windows can fail a network and not really tell you about it. I was able to run ping from Windows. It will appeared to make several attempts. However, wireshark saw absolutely no attempt on Windows part to put anything on the network. So, we turned to Linux to finish up development work. My bet, Windows momentarily failed your network. – st2000 Jun 28 '16 at 00:52
  • @Jerry - Do you connect using IP addresses or names? Also IPv4 or IPv6? – Code Gorilla Jul 05 '16 at 12:22
  • @Matt - IP addresses only, and IPv4. – Jerry Jul 05 '16 at 12:35
  • @Jerry - Damn, thought it might be a WINS issue and adding your host to /etc/hosts might have fixed it. – Code Gorilla Jul 05 '16 at 16:30
  • 1
    @Matt - Thanks for sharing your ideas. I would love to eventually figure this out some day. I've been discovering from other peoples' experiences that there are some strange quirks with the Arduino Due, and now that the board is technically officially discontinued from the Arduino product line, I'm not expecting the stranger bugs to get ironed out. I'm still open to the idea that it might be a Windows networking problem, and every once in a while I do experiments with it (including those suggested here), but so far I've found nothing. – Jerry Jul 05 '16 at 17:41

1 Answers1

1

This is speculation as it may be nearly impossible for any given person to simulate your network (for example, not only the version of Windows you are running but all the drivers installed and hardware specific to your Ethernet interface ... to only mention a few variables).

Consider using a network monitor to capture all communications set out by the Windows computer. Consider the Windows computer occasionally failing your network. Consider the delay you experience may be the time it takes for Windows to recover from what it thinks is a bad network.

The observation is that Windows sends out many autonomous messages over a new network in a "discovery" mode. The suspicion is that the lack of response to some or all of these messages will result in Windows failing a network.

Windows does have ways of reporting the status of networks that vary with the version of Windows. But these methods (menus) can be frustrating to use as they don't appear to update often enough to reflect the true behavior of traffic coming out of the Windows computer.

Regardless, test if the state of the network is always good. Also, test if connecting equipment Windows might expect on a functioning network (for example, a router with a DHCP server) improves the response time. This, as an effort / test to determine if Windows is more responsive while connected to a healthy / active network.

st2000
  • 6,811
  • 2
  • 10
  • 19