I have an official wifi shield, currently on an Uno R2. I have some code that receives a request, does some simple parsing, and returns a simple response. It functioned slower than I expected, so I set up some timers to see what was slow. Turns out that the arduino receives an http message in about 60ms, but sending a similarly sized message back out takes about 4 seconds!
For simplicity, I'll show the code from the WiFiWebServer example, which exhibits the same behavior (the code in my project is very similar):
void loop() {
unsigned long time = micros();
//Serial.println("In Loop");
// listen for incoming clients
WiFiClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// add a meta refresh tag, so the browser pulls again every 5 seconds:
client.println("<meta http-equiv=\"refresh\" content=\"5\">");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("
");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disonnected");
Serial.println("Time: " + String(micros() - time));
}
}
You can see my timer code added to the example, and the time to send a message over wifi is consistently on the order of 3.7-3.8 seconds.
Ideally I'd like to be able to send my data in ~100ms (remember I receive a similar size in ~60ms, and I think wifi is symmetrical?).
I read here Arduino Forum that each println command is though to create a new packet (unconfirmed, but that's how the ethernet shield works, which shares a lot of the library). I read elsewhere (sorry, didn't save the link) that each character is sent as a separate packet with print or println, and that write should be used instead. If that were the case, I'd expect to be able to drop about 16 tcp bytes for every byte I'm currently sending (minus one), which would speed me from ~4 seconds to ~250ms, much closer to the speed I'm looking for.
So with that in mind, I modified the WiFiWebServer example with the following:
void loop() {
unsigned long time = micros();
//Serial.println("In Loop");
// listen for incoming clients
WiFiClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<meta http-equiv=\"refresh\" content=\"5\"><body>Hello just
testing</body></html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disonnected");
Serial.println("Time: " + String(micros() - time));
}
}
So now there is only a single client.println statement, which should mean just one packet sent, and a lot of overhead cleared. This reduced the times down to about 1.3s. Big improvement!!
Based on this, I'm thinking that each println/print/write statement does create a new data packet, and all the overhead that goes with that. My messages will be short (~100 characters), so the more overhead I can reduce, the better.
While reducing the number of packets created is good (285% speedup!!), 1.3 seconds is still a lot more than the ~200ms I expected from reducing the number of packets. And it's much greater than the ~60ms times I get receiving data. Are there any known issues limiting the speed of the wifi shield? What else can I do to get a speedup? Most of the information I can find refers to the ethernet shield, and while that was helpful, I'm still looking for more improvement.