WiFi shield does not send out data immediately and blocks write() for 150 ms

I have issues with the orginal arduino WiFi shield. I use it as a TCP/IP server, to send data periodically over an open connection (streaming).

I experienced bursts of the send data each 2 seconds, and each write() that finally starts a burst is blocked for a really long time (I think it was around 500 ms, but not sure any more.)

I found a bug report under https://github.com/arduino/wifishield/issues/24 and applied the given workaround (sending data to the shield in between). Still the data comes in bursts, always 5 data lines in one burst, and each 5th write() blocks for 150 ms (detailed calculation below). This is still inacceptable in my opinion (and for my use case).

Here is some output of the attached sources:

1366397893,140 sek value=1023.0 1366397893,140 sek value=1023.0 1366397893,140 sek value=1023.0 1366397893,389 sek value=1023.0 1366397893,390 sek value=1023.0 1366397893,390 sek value=1023.0 1366397893,391 sek value=1023.0 1366397893,391 sek value=1023.0 1366397893,642 sek value=1023.0 1366397893,642 sek value=1023.0 1366397893,643 sek value=1023.0 1366397893,643 sek value=1023.0 1366397893,643 sek value=1023.0 1366397893,894 sek value=1023.0 1366397893,895 sek value=1023.0 1366397893,895 sek value=1023.0 1366397893,896 sek value=1023.0 1366397893,896 sek value=1023.0 1366397893,897 sek value=1023.0 1366397894,148 sek value=1023.0 1366397894,148 sek value=1023.0 1366397894,148 sek value=1023.0 1366397894,149 sek value=1023.0 1366397894,149 sek value=1023.0 1366397894,402 sek value=1023.0 1366397894,402 sek value=1023.0 1366397894,402 sek value=1023.0 1366397894,403 sek value=1023.0 1366397894,403 sek value=1023.0 1366397894,403 sek value=1023.0 1366397894,657 sek value=1023.0 1366397894,657 sek value=1023.0 1366397894,658 sek value=1023.0 1366397894,658 sek value=1023.0 1366397894,658 sek value=1023.0 1366397894,907 sek value=1023.0 1366397894,908 sek value=1023.0 1366397894,908 sek value=1023.0 1366397894,908 sek value=1023.0 1366397894,909 sek value=1023.0 1366397895,160 sek value=1023.0

Each 250 ms there are 5 values comming in in one burst. This does not change, when I accompany each data line with an extra line (see in the arduino code), so it cannot be a simple buffer-filled trigger.

Another thing we see in this data: The arduino code was supposed to send a data line each 20 ms (see "delay(20)" in the code). This would make 50 values per second. But there are only 5 values/burst * 4 bursts = 20 values per second. So, the loop passes the delay(20) only 20 times per second, that make400 ms /sec. So the missing 600 ms /sec are spended in the 4 "client.write()". This gives a blocking of 150 ms on each send() that leads to a send-burst.

This is much to much to be in any way "normal". The WiFi shield has its own processor, so the write() should take just a few microseconds.

I put the code in the next post, due to post size limits.

Here is the arduino code I am using:

#include <Servo.h> 

#include <SPI.h>
#include <WiFi.h>

boolean debug = true;

Servo myservo; 
int pos = 45; 
int servoPin = 8;

int potiPin = A5;
int value;

char outbuf[512];
int outbufLen = 512;

char ssid[] = "xxxx";      //  your network SSID (name) 
char pass[] = "xxxx";   // your network password
int status = WL_IDLE_STATUS;

WiFiServer server(80);
WiFiClient client;

void setup(void) {
  delay(1000);

  if (debug) {  
    Serial.begin(9600); 
    while (!Serial) {
      ; // wait for serial port to connect. Needed for Leonardo only
    }
  }
  
 // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    if (debug) Serial.println("WiFi shield not present"); 
    // don't continue:
    while(true);
  } 
  
  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) { 
    // Connect to WPA/WPA2 network.
    status = WiFi.begin(ssid, pass);
    // wait 6 seconds for connection:
    delay(6000);
  } 
  server.begin();
  // you're connected now, so print out the status:
  if (debug) printWifiStatus();

  pos=45;  
  myservo.attach(servoPin);
  myservo.write(pos);           

  delay(100);
}


void loop(void) {

  delay(20);

  if (debug) Serial.println("read analog in");
  
// For this test, do not anything else, that might steal any time  
//  value = analogRead(potiPin);
//  pos = value * 180 / 1024;
//  myservo.write(pos);           
    value = 345;

  float max = 0.0;
  float min = 200.0;
  int i;

  if (! client.connected()) {
     if (debug) Serial.println("not connected");
     delay(100);
     client.stop();
     delay(100);
     client = server.available();
  } 

  if (! client) {
    if (debug) Serial.println("still not connected");
    return;
  }
  

  outbuf[0] = 0;
  String x = "value=";
  x += value;
  appendToOutbuf(x);
  appendToOutbuf("\n");
  
  // another test case:
  // appendToOutbuf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");

  if (debug) Serial.println("send to wifi");

  if (client.connected()) client.write(outbuf);
  if (debug) Serial.println("send finished");

  readWiFi();
  
}


void appendToOutbuf(String in) {
  char x[200];
  in.toCharArray(x,200);
  appendToOutbuf(x);
}

// As the EthernetClient tends to send each character of e.g. an integer in an own packet, I made
// this function to collect everything to send. Not needed for WiFiClient, but still
// useful, to be on the save side, and to be consistent to EthernetClient-code.
void appendToOutbuf(char in[]) {
  int pos = 0;
  // append-position suchen
  for (pos = 0; pos < outbufLen; pos++) {
    if (outbuf[pos] == '\0') break;
  }
  int pos2 = 0;
  // kopieren
  for (pos2 = 0; pos2 < 200; pos2++) {
    outbuf[pos] = in[pos2];
    if (in[pos2] == '\0') break;
    pos++;
    if (pos == outbufLen) {
      outbuf[pos] = '\0';
      break;
    }
  }
}

void readWiFi() {
   while (client.available()) {
      char c2 = client.read();
   }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

And here the java code for the PC side:

package graph2;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;


public class TestWiFi {

	public static void main(String[] args) {
		
		EtherClientIntern client = null;
			try {
				client = new EtherClientIntern("192.168.0.102");
				client.openSocket();
				client.writeLine("XXXXXXXXXXXXXXXXXXXXXXXXXXX"); // so the arduino available() will be triggered
			} catch (Exception e) {
				e.printStackTrace();
				System.exit(1);
			}

		while (true) {
			double v = getNextValue(client);
			String millis = System.currentTimeMillis() + "";
			int kommaPos = millis.length() -3;
			System.out.println(millis.substring(0, kommaPos) +"," + millis.substring(kommaPos) + " sek    value="+v);
		}
	}

	
	public static double getNextValue(EtherClientIntern client) {
		
		try {
			while (true) {
				String s = client.readLineFromSocket();
				if (s.startsWith("value=")) {
					
					// write some data, as suggested by 
					// https://github.com/arduino/wifishield/issues/24
					// Still, an unacceptable 250 ms delay keeps being.
					client.writeLine("x");
					
					return Double.parseDouble(s.substring(6));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			client.close();
		}
		return 0.0;
	}
	
	// ============ reduced EthernetClient class included here for forum ====================
	
	public static class EtherClientIntern {

		private String ipAdress;
		int port = 80;
		int TIMEOUT = 0;

		Socket s = null;
		OutputStreamWriter sout =null;
		BufferedInputStream bin = null;
		
		public EtherClientIntern(String ipAdress) throws Exception {
			this.ipAdress = ipAdress;   // "192.168.0.111"
		}

		public void close() {
			try {
				try { Thread.sleep(20); } catch (InterruptedException e) {	}
				s.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			finally {
				s = null;
			}
		}

		
		public void openSocket() {
			try {
				s = new Socket(ipAdress,port); 
				bin = new BufferedInputStream(s.getInputStream());
				sout = new OutputStreamWriter(s.getOutputStream());
			} catch (Throwable e) {
				System.out.println("Can not open connection ("+ipAdress+" Port 80): "+e.getMessage());
				System.out.println("Exiting now.");
				System.exit(-1);
			}
		}
		
		public void writeLine(String cmdString) throws Exception {
			writeToSocket(cmdString + "\r\n");
		}

		public void writeToSocket(String sendChars) throws IOException {
			sout.write(sendChars);
			sout.flush();
		}
		
		public String readLineFromSocket() throws IOException {
			StringBuffer buf = new StringBuffer();
			int l = 0;
			do {
				l = readWithTimeout();
				if (l > -1) {
					if (((char) l != '\r') && ((char) l != '\n'))
						buf.append((char) l);
				}
				else {
					break;
				}
			} while ((char) l != '\n');

			String ret = buf.toString();
			return ret;
		}
		
		private int readWithTimeout() throws IOException {
			int waited = 0;
			while (bin.available() <1) {
				waited++;
				if ((TIMEOUT > 0) && (waited > TIMEOUT)) {
					throw new IOException("Timeout");
				}
				try { Thread.sleep(1); } catch (InterruptedException e) {	}			
			}
			return bin.read();
		}

	}

}

Hello,

it is 4 weeks ago that I have posted about a serious missbehaviour of the WiFi library, but I still got no response. Aren't there any arduino-people feeling a bit responsible for supporting the HW they sell?

I sent a detailed problem description, a reference to a similar bug report, and complete SW for both communication parties, so it should easily be reproducible. What else can I do (besides trying to fix it by myself)?

BTW: I use arduino-1.0.4 on linux, the official arduino WiFi shield and a Mega2560.

Thanks a lot, Thomas

Thomas33: Hello,

it is 4 weeks ago that I have posted about a serious missbehaviour of the WiFi library, but I still got no response. Aren't there any arduino-people feeling a bit responsible for supporting the HW they sell?

I sent a detailed problem description, a reference to a similar bug report, and complete SW for both communication parties, so it should easily be reproducible. What else can I do (besides trying to fix it by myself)?

BTW: I use arduino-1.0.4 on linux, the official arduino WiFi shield and a Mega2560.

Thanks a lot, Thomas

I have other issues with the same hardware:arduino wifi shield (mine is R3), and MEGA 2560. I'm using windows. Mine is the longest string I can client.print is 90 bytes. I wonder if you have experienced this. What is the longest string you collect and send?

Hi liudr,

sorry for answering so late.

Lets look at my code. I tried to send each 20 ms a string like this: "value=345\n". As far as I can tell, always 5 of those strings went in one packet. That are 50 characters.

In another testcase (see this statement above:)

Each 250 ms there are 5 values comming in in one burst. This does not change, when I accompany each data line with an extra line (see in the arduino code), so it cannot be a simple buffer-filled trigger.

I tried to send each 20 ms a string like this: "value=345\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n". That are 68 characters. As far as I can tell, always 5 of those strings (that are 340 characters) went in one packet again. At least, the 250 ms delay appeared at each 5th packet again.

You will probably ask next, which firmware and HW I have. How can I find out?

Another good idea would be, if you try to reproduce my results. If you need help with the java side, let me know.