Speed up wifi server response time?

Hi all,

Have the below script, which allows the user to change LED Strip colours from any browser by setting the Uno and wifi shield up as a server and works well, however there's quite a degree of latency between entering these values into a URL and the lights changing.

URL format will be something like:
http://192.168.0.125/?setLed=010,010,010

Anyone got any tips on how I can speed up the response times here?

/*
 
 */

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


char ssid[] = "xxx";      // your network SSID (name) 
char pass[] = "xxx";   // your network password
int keyIndex = 0;                 // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;

String HTTP_req;


/// LED PIN - START

//pin definitions.  must be PWM-capable pins!
const int redPin = 5;
const int greenPin = 6;
const int bluePin = 3;

//maximum duty cycle to be used on each led for color balancing.  
//if "white" (R=255, G=255, B=255) doesn't look white, reduce the red, green, or blue max value.
const int max_red = 255;
const int max_green = 255;
const int max_blue = 255;

 int red = 0;
 int blue = 0;
 int green = 0;

// LED PIN - END


WiFiServer server(80);

void setup() {
  
  
  //Initialize serial and wait for port to open:
  Serial.begin(9600); 
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  
  // LED PIN SETUP - START
   //set all three of our led pins to output
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
 
  // LED PIN SETUP - END
  
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present"); 
    // don't continue:
    while(true);
  } 
  
  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) { 
    Serial.print("Attempting to connect to Network: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:    
    status = WiFi.begin(ssid, pass);

    // wait 3 seconds for connection:
    delay(10000);
  } 
  server.begin();
  // you're connected now, so print out the status:
  printWifiStatus();
}


void 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();
        HTTP_req += c;   
        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");  // the connection will be closed after completion of the response
          client.println("Refresh: 3");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
                    client.println("<html>");
                    // output the value of each analog input pin
                   client.println("<body>");
                    client.println("<h1>Odious LED Light Server</h1>");
                    client.println("<p>I'm connected and awaiting your command, master...</p>");
                    client.println("</body>");
                    client.println("</html>");
          
               // LED SET - START     
           
        // read HTTP Request for LED colour settings

    if (HTTP_req.indexOf("setLed=") > -1) {  // see if checkbox was clicked
          Serial.print("LED Command Detected: ");
        // work out first index position
        String tempRed = HTTP_req.substring(HTTP_req.indexOf("setLed=")+10,13);
        String tempGreen = HTTP_req.substring(HTTP_req.indexOf("setLed=")+14,17); 
        String tempBlue = HTTP_req.substring(HTTP_req.indexOf("setLed=")+18,21);
        //convert the value for RED to an Integer
        int redLEDValue;
        char carray[6];
        tempRed.toCharArray(carray, sizeof(carray));
        redLEDValue = atoi(carray);
        //convert the value for GREEN to an Integer
        int greenLEDValue;
        tempGreen.toCharArray(carray, sizeof(carray));
        greenLEDValue = atoi(carray);
        //convert the value for BLUE to an Integer
        int blueLEDValue;
        tempBlue.toCharArray(carray, sizeof(carray));
        blueLEDValue = atoi(carray); 
        
         Serial.println(redLEDValue);
         Serial.println(greenLEDValue);
         Serial.println(blueLEDValue);
         red= redLEDValue;
         green= greenLEDValue;
         blue= blueLEDValue;
        }
        else{
         Serial.print("No LED Values"); 
        }
  
  //map Colour values
  red = map(red, 0, 255, 0, max_red);
  blue = map(blue, 0, 255, 0, max_blue);
  green = map(green, 0, 255, 0, max_green);
  
  //set the three PWM pins according to the data read from the Serial port
  //we also scale the values with map() so that the R, G, and B brightnesses are balanced.
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
             // LED SET - END
           
           HTTP_req = "";
           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 disconnected");


  }
}


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");
}

I don't know how much latency you are talking about, but there are two ways to speed up your code a bit. Increase the serial speed to 115200, and use client.write instead of client.println. Here is an example from your code. Note the use of "\r\n" in each client.write() string.

          client.write("HTTP/1.1 200 OK\r\n");
          client.write("Content-Type: text/html\r\n");
          client.write("Connection: close\r\n");  // the connection will be closed after completion of the response
          client.write("Refresh: 3\r\n\r\n");  // refresh the page automatically every 5 sec

The client.println() function sends one byte per packet. The client.write() function sends the whole string in one packet.

edit: Just a warning. The wifi shield firmware uses only one socket for the server, and will accept a new connection before it is finished with a previous connection. This causes corruption and wrong files to be transmitted to the client if there are two or more clients accessing the server at the same time. And if it gets several requests at the same time (like it will if exposed to the internet), it will crash the firmware and needs to be reset. :frowning:

Excellent - cheers Tim - that's got things running nippety quick

As this is for controlling my house lighting, should be something I can work around.

Is there any way to limit this (ie code it to block connections until previous request complete) or is this just a limitation?

I guess the other way I could do this is use a NAS server to be the target for commands and it can parse and issue one by one (ie so the wifi shield only ever has one client and that's the server)

I have filed a bug report on the server part of the wifi shield firmware.

I use my wifi server on a localnet only. That way I can control the number of clients.

The bad part is there is sometimes a nasty delay (1000-2000ms) in the server response if the page/file it sends is large.