WiFi Shield client code test

Thanks again to PaulS for loaning me the wifi shield for the test and programming.

Here is my new WiFi shield client code. I ran it overnight and it did great. I ran as many fail tests as I could think of, and it did fine. Try it out and let me know if it works for you. I will put it in the playground if it works ok. You must change the wifi network and password. Requires the IDE v1.0.5 firmware upgrade to work correctly. The firmware version should display as v1.1.0.

/*
   Wifi client sketch for IDE v1.0.5 and WiFi shield
   Uses GET method.
   Posted 24 Nov 2013 by SurferTim
   Last modified 23 Nov 2013
*/
#include <WiFi.h>

// change to your server
IPAddress server(68,99,58,117);

//Change to your domain name for virtual servers
char serverName[] = "www.wififoryou.com";
// If no domain name, use the ip address above
// char serverName[] = "68.99.58.117";

// change to your server's port
int serverPort = 80;

WiFiClient client;
char ssid[] = "mynetwork";     // the name of your network
char pass[] = "mypassphrase";  // your network password

int status = WL_IDLE_STATUS;     // the Wifi radio's status

int totalCount = 0;
int loopCount = 0;
char pageAdd[32];

void setup() {
  Serial.begin(115200);

  // disable SD SPI
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println(F("WiFi shield not present")); 
    // don't continue:
    while(true);
  } 

  // check firmware version
  Serial.print(F("Firmware version: "));
  Serial.println(WiFi.firmwareVersion());
  
 // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) { 
    Serial.print(F("Attempting to connect to open SSID: "));
    Serial.println(ssid);
    status = WiFi.begin(ssid,pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
   
  // you're connected now, so print out the data:
  Serial.print(F("You're connected to the network"));
  printCurrentNet();
  printWifiData();
  delay(2000);
  Serial.println(F("Ready"));
}

void loop()
{
  if(loopCount < 30)
  {
    // if loopCount is less than 30, just delay a second
    delay(1000);
  }
  else
  {
    // every thirty seconds this runs
    loopCount = 0;

    // Modify next line to load different page
    // or pass values to server
    sprintf(pageAdd,"/arduino.html",totalCount);

    // sprintf(pageAdd,"/arduino.php?test=%u",totalCount);

    if(!getPage(server,serverPort,pageAdd)) {
      SetSockStatus();
      Serial.print(F("Fail "));
    }
    else Serial.print(F("Pass "));

    totalCount++;
    Serial.println(totalCount,DEC);
  }    

  loopCount++;
}

byte getPage(IPAddress ipBuf,int thisPort, char *page)
{
  int inChar;
  char outBuf[128];

  ShowSockStatus();

  Serial.print(F("connecting..."));

  if(client.connect(ipBuf,thisPort))
  {
    Serial.println(F("connected"));

    ShowSockStatus();
    
    sprintf(outBuf,"GET %s HTTP/1.1",page);
    client.println(outBuf);
    sprintf(outBuf,"Host: %s",serverName);
    client.println(outBuf);
    client.println(F("Connection: close\r\n"));
  } 
  else
  {
    Serial.println(F("failed"));
    return 0;
  }

  // connectLoop controls the hardware fail timeout
  int connectLoop = 0;

  while(client.connected())
  {
    while(client.available())
    {
      inChar = client.read();
      Serial.write(inChar);
      // set connectLoop to zero if a packet arrives
      connectLoop = 0;
    }

    connectLoop++;

    // if more than 10000 milliseconds since the last packet
    if(connectLoop > 10000)
    {
      // then close the connection from this end.
      Serial.println();
      Serial.println(F("Timeout"));
      client.stop();
    }
    // this is a delay for the connectLoop timing
    delay(1);
  }

  Serial.println();

  Serial.println(F("disconnecting."));
  // close client end
  client.stop();

  return 1;
}

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

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);    
  Serial.print(F("BSSID: "));
  Serial.print(bssid[5],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[4],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[3],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[2],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[1],HEX);
  Serial.print(F(":"));
  Serial.println(bssid[0],HEX);

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

  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print(F("Encryption Type:"));
  Serial.println(encryption,HEX);
}

void printWifiData() {
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
    Serial.print(F("IP Address: "));
  Serial.println(ip);
  Serial.println(ip);
  
  // print your MAC address:
  byte mac[6];  
  WiFi.macAddress(mac);
  Serial.print(F("MAC address: "));
  Serial.print(mac[5],HEX);
  Serial.print(F(":"));
  Serial.print(mac[4],HEX);
  Serial.print(F(":"));
  Serial.print(mac[3],HEX);
  Serial.print(F(":"));
  Serial.print(mac[2],HEX);
  Serial.print(F(":"));
  Serial.print(mac[1],HEX);
  Serial.print(F(":"));
  Serial.println(mac[0],HEX);
  
  // print your subnet mask:
  IPAddress subnet = WiFi.subnetMask();
  Serial.print(F("NetMask: "));
  Serial.println(subnet);

  // print your gateway address:
  IPAddress gateway = WiFi.gatewayIP();
  Serial.print(F("Gateway: "));
  Serial.println(gateway);
}

void ShowSockStatus() {
  for(int x = 0; x < MAX_SOCK_NUM; x++) {
    Serial.print(F("Socket #"));
    Serial.print(x,DEC);
    if(WiFi._state[x] == -1) Serial.println(F(": available"));
    else Serial.println(F(": used"));

//    Serial.println(WiFi._state[x]);    
  }
}

void SetSockStatus() {
  for(int x = 0; x < MAX_SOCK_NUM; x++) {
    WiFi._state[x] = -1;
  }
}

I left my server ip in the code so you can test it. Please change that to your server after your initial test.

edit: This example sketch requests the page every 30 seconds.

It displays the socket status before and after the connection. It should always show all 4 sockets available before the connection, and if the connection was successful, should show “Socket #0: used” and all others available. If not on your test, let me know.

There is a bug in the WiFi library. If the wifi router’s radio fails (or disabled for my test), the socket is not released after the failed connection, and if the code makes 4 requests with the radio disabled, all sockets will be used, and the connection will always fail until the Arduino is reset. To correct that bug, I installed the “SetSockStatus()” function to reset the sockets if the TCP connect fails due to the radio fail.

Tim thanks for this, much appreciated.

Am in the WiFi stragglers, trying to get this to work consistently. Tried to upgrade the WiFi firmware using the Arduino product [age info, but I find the fimrware is still showing v 1.0.0 - maybe a noob question, but where do i find the firmware upgrade for 1.0.5 Wifi. If it's not the one list on the Arduino site, am i missing something?

I'm running 1.0.5 Arduino on OS X.

Thanks, Ande

I had trouble with the Linux version of the firmware upgrade, so I resorted to Windoze. :(

Here is the guide to the upgrade. It kinda sucks due to the pitfalls of the software install. http://arduino.cc/en/Hacking/WiFiShieldFirmwareUpgrading

I downloaded the Atmel Flip installer here http://www.atmel.com/tools/FLIP.aspx

I connected my mini-usb cable to the usb port on the wifi shield (still connected to my Arduino).

Once I ran the program and it installed the software, I found it did not install the usb driver. I had to go to the device manager in the control panel and install it manually. I tried to run this from that guide, and got a something.dll error. Can't remember the dll name now.

batchisp.exe -device AT32UC3A1256 -hardware usb -operation erase f memory flash blankcheck loadbuffer /Arduino/hardware/arduino/firmware/wifishield/binary/wifi_dnld.elf program verify start reset 0

So I selected the device with the question mark and selected "reinstall driver". The driver for my computer was in c:/Program Files/Atmel/Flip 3.4.7/usb/x86 I highlighted it and selected install. That went well.

Then I tried again to run that upgrade, and it couldn't find wifi_dnld.elf, so I went to my install of IDE v1.0.5... /arduino-1.0.5/hardware/arduino/firmwares/wifishield/ ...and copied both the wifi_dnld.elf and wifiHD.elf files to my root directory (c:).

Then I ran this: batchisp.exe -device AT32UC3A1256 -hardware usb -operation erase f memory flash blankcheck loadbuffer c:/wifi_dnld.elf program verify start reset 0

...and this: batchisp.exe -device AT32UC3A1256 -hardware usb -operation erase f memory flash blankcheck loadbuffer c:/wifiHD.elf program verify start reset 0

Both warned of a bootloader overwrite but it didn't cause any problems on the upgrade. Now I am upgraded. Whew!

The wifi client library code has a bug that does not release the current socket if the connection fails. That results in the use of all the sockets after 4 failed attempts, and all subsequent connection attempts will fail until the Arduino is reset/rebooted.

I found the fix and reported it. https://github.com/arduino/Arduino/issues/1720

edit: The code above has a patch that releases the sockets until the fix is implemented.

Thanks again to PaulS for the loan of this wifi shield. Now I know when I buy one, it will work.

Hi Tim,

Managed to get the Fimrware to v1.1.0.

I've also updated the code the WiFiClient.cpp as per previous post. But not getting anywhere. I'm seeing this...

YWFirmware version: 1.1.0 Attempting to connect to open SSID: bigfatmomma You're connected to the networkSSID: bigfatmomma BSSID: C0:3F:E:F6:18:EA signal strength (RSSI):-77 Encryption Type:4 IP Address: 192.168.0.13 192.168.0.13 MAC address: 78:C4:E:1:D3:CA NetMask: 255.255.255.0 Gateway: 192.168.0.1 Ready Socket #0: used Socket #1: used Socket #2: used Socket #3: used connecting...failed Fail 1 Socket #0: available Socket #1: available Socket #2: available Socket #3: available connecting...No Socket available failed Fail 2 Socket #0: available Socket #1: available Socket #2: available Socket #3: available connecting...No Socket available failed Fail 3 Socket #0: available Socket #1: available Socket #2: available Socket #3: available connecting...No Socket available failed Fail 4 Socket #0: available Socket #1: available Socket #2: available Socket #3: available connecting...No Socket available failed Fail 5 Socket #0: available Socket #1: available Socket #2: available Socket #3: available connecting...No Socket available failed Fail 6 Socket #0: available Socket #1: available Socket #2: available Socket #3: available connecting...No Socket available failed Fail 7

But it never connects, any suggestions are very welcome :)

Cheers, Ande

You have a problem somewhere. Are you using IDE v1.0.5? What hardware are you using?

After the "ready", all your sockets are used before you even start a connection. By default in the wifi library, those array entries are set to -1 (available). My code does not modify those entries until a connection is started.

Firmware version: 1.1.0 Attempting to connect to open SSID: bigfatmomma You're connected to the networkSSID: bigfatmomma BSSID: C0:3F:E:F6:18:EA signal strength (RSSI):-77 Encryption Type:4 IP Address: 192.168.0.13 192.168.0.13 MAC address: 78:C4:E:1:D3:CA NetMask: 255.255.255.0 Gateway: 192.168.0.1 Ready Socket #0: used Socket #1: used Socket #2: used Socket #3: used connecting...failed

edit: You must use an IDE version greater than v1.04. Pre-v1.0.5 settings were backwards.

WiFi Shield where client code should be inserted? I inserted but failed. . .

Bloomgren: WiFi Shield where client code should be inserted? I inserted but failed. . .

I do not understand. You copied and pasted the code above into the IDE v1.0.5, and it did what? Failed to compile? Failed to run correctly?

Or do you mean the wifi shield upgrade?