[Problem] WiFi shield stops working out of nowhere

Hello everybody! I just registered here and hope to find some help. I have the Arduino Uno R3 from SainSmart and the WiFi shield. What I want to accomplish is the option to control a RC tank over the internet and in my own network. I use LEDs to show me how the motors would work, and they work very nice. But a problem is that I need to communicate with the Arduino at least all 200ms or so to create a stable movement that's not too laggy.
I used the SimpleWebServerWiFi I found in the examples folder and modified it according to my needs. My Arduino receives commands relatively fast, but only sometimes. Sometimes it takes 100ms, then 1000ms or 2000ms. What also happened is that it switched between being fast and slow every second command. When I send the command with my AutoIT code all 200ms, the Arduino freezes. But if I wait one or two seconds between each command it works.

Here some informations about everything:

  • Arduino IDE 1.0.3 (Because 1.0.5 screw up my code while compiling, a known problem with 1.0.5)
  • AutoIT code to send the commands in this form: http:\[IP of Arduino]:[port][SPEED LEFT]x[SPEED RIGHT]

The code:

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


char ssid[] = "My network at home";     //  your network SSID (name)
char pass[] = "And the password";    // your network password

char ssid2[]="Arduino Tank"; // My hotspot on my laptop to be able to control the tank everywhere
char pass2[]="wowmuchawesome"; // The password for that

WiFiServer server(3178);

int pin1=3; //LED for the transistor that controls the forward speed of the left motor
int pin2=5; //LED for the transistor that controls the backward speed of the left motor
int pin3=6; //Same like pin1 but for right
int pin4=9; //Same like pin2 but for right

int netz=0; // which network, 0-none, 1-homenetwork, 2-Arduino Tank (hotspot)
boolean go=false; // So it only starts to add chars when I already got a "G" because of "GET"
int time=0; // for timeout
int run=0; // I don't want to check the connection all the time

String relativex=""; //Left speed
String relativey=""; //Right speed (variable names stayed although I changed the way I control it, ignore)
String currentLine=""; //The current received line

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

char floatbuf[64]; //For converting chars in flaot
float speedlinks=0.0; //speed left
float speedrechts=0.0; //speed right



void setup() {
  Serial.begin(9600);
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT); // I just see that I forgot to add the other two pins, how the hell could the work?!
  tryconnect(); // first connection
}

void loop() {
  if (run>60000) { // only test all 60 seconds
    run=0; //sets the countdown back to 0
    Serial.println("Run");
  if (WiFi.status()!=WL_CONNECTED) { // and only if it's not connected
  tryconnect(); //tries to connect
  }
  }
  run+=1; //countup
  delay(1);
  webserver();  //checks for connection and tries to receive data
  


    
}






void tryconnect() {  // works like a charm
  Serial.println("Trying to connect.");
  if (int num=WiFi.scanNetworks()>(-1)) {
    for (int thisNet = 0; thisNet<num; thisNet++) {
    
    if (WiFi.SSID(thisNet)=="NerdtechCorporation") {
      netz=1;
    } else if (WiFi.SSID(thisNet)=="Arduino Tank") {
      netz=2;
    } else {
      netz=0;
    }
    
  }
  
  
  
  
  if (WiFi.status()!=WL_CONNECTED) {
      Serial.println("Attempting to connect to Arduino Tank...");
      if (netz==2) {
      status = WiFi.begin(ssid2, pass2);
      }

      if ( status != WL_CONNECTED) {
         Serial.println("Couldn't connect to Arduino Tank.");
         Serial.println("Attempting to connect to NerdtechCorporation...");
         
         if (netz=1) {
         status = WiFi.begin(ssid, pass);
         }
         
         if ( status != WL_CONNECTED) {
             Serial.println("Couldn't connect to NerdtechCorporation.");
          } else {

            Serial.println("Connected to NerdtechCorporation.");
            server.begin();
            printWifiStatus();
          }
         
      } else {

        Serial.println("Connected to Arduino Tank.");
        server.begin();
        printWifiStatus();
      }
  } else {
    Serial.println("Already connected");
  }
}
}



void webserver() {

  WiFiClient client = server.available();

  if (client) {
    time=millis();  //stores the beginning time
    Serial.println("new client");
    currentLine = "";
    while (client.connected()) {
      if (millis()-time>5000) {  // if it took 5 seconds timeout so stop everything and go back to loop()
        Serial.println("Timeout.");
        client.flush();
        client.stop();
        return;
      }
      if (client.available()) {
        char c = client.read();  // reads incoming stuff
        if (c == '\n') {

          if (currentLine.length() == 0) {
            client.println();
            client.println();
            break;
          }
          else {
            currentLine = "";
            Serial.println("Blanked current line");
          }
        }     
        else if (c != '\r') {
          currentLine += c;
        }

            if (currentLine.substring(0,5)=="GET /"&&currentLine.indexOf("HTTP")!=-1) {  // if the beginning is "GET /" and it contains "HTTP", it also contains the speed of the motors
            currentLine=currentLine.substring(5,currentLine.length()-1);
            Serial.println(currentLine);
            currentLine=currentLine.substring(0,currentLine.indexOf(" "));
            Serial.println(currentLine);
            relativex=(currentLine.substring(0,currentLine.indexOf("x")));
            relativey=(currentLine.substring(currentLine.indexOf("x")+1,currentLine.length()));
            Serial.println(relativex);
            Serial.println(relativey);
            
            relativex.toCharArray(floatbuf,sizeof(floatbuf));
            speedlinks=atof(floatbuf)*255;
            relativey.toCharArray(floatbuf,sizeof(floatbuf));
            speedrechts=atof(floatbuf)*255;
            
            Serial.println(speedlinks);
            Serial.println(speedrechts);
            
            if (speedrechts<0) {  // if it's backwards, stop the forward transistor (or so) and start the backwards one
              analogWrite(pin3,0);
              analogWrite(pin4,speedrechts*(-1));
            } else {  //else stop the backwards one and start the forwards one
              analogWrite(pin4,0);
              analogWrite(pin3,speedrechts);
            }
            
            if (speedlinks<0) {  //same for left
              analogWrite(pin1,0);
              analogWrite(pin2,speedlinks*(-1));
            } else {
              analogWrite(pin2,0);
              analogWrite(pin1,speedlinks);
            }
            Serial.println("Finished speed thing");
            client.println();
            client.println();
            Serial.println("Sent response");
            client.flush();
            Serial.println(millis());
            client.stop();
            Serial.println(millis());
            delay(10);
            Serial.println("Delay over");
            return;
            
            
            }
      }
    }
    Serial.println("Going to stop client manually");
    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");
  // print where to go in a browser:
  Serial.print("To see this page in action, open a browser to http://");
  Serial.println(ip);
}

I know my code is damn ugly, but I would love to know why it doesn't work like it should or how I can make a better connection. I'm a not that good with Arduinos so I decided to learn by doing, but this is something I'm stuck for a long time now.

Thanks in advance, Lutan

What works in 1.0.5 that doesn't work in 1.0.3 ?

What happens if client.available( ) is false in the third function ?

Even the examples didn't work.

http://arduino.cc/en/Reference/ClientAvailable:
"Returns the number of bytes available for reading (that is, the amount of data that has been written to the client by the server it is connected to). "
I guess it simply skips the receiving of data in case there is none to receive. It was a part of the example.

The wifi shield has problems with the server (listener) part of the wifi library. I avoided the delays and freezing by using a udp client sketch in the Arduino with a Linux C program on the computer. It easily updates at 200 ms, and I have tested it at 100ms updates with no problems. Would that be an alternative you could use?

That means instead of making the Arduino the server, you made him the client? How did you fill him with informations? I have no clue on how to do that.

lutan:
That means instead of making the Arduino the server, you made him the client? How did you fill him with informations? I have no clue on how to do that.

That is correct. It works like NTP and DNS. The Arduino "client" sends a packet to the Linux "server" with the Arduino data, and the Linux "server" responds with a packet containing the new control data for the Arduino.

I can post the basic code for both the Arduino and the Linux computer if you are interested. You can modify it to meet your requirements. Let me know and I will boot my Linux box with the code and post it here.

I see others are watching this post, so I will post the code.

Here is the Arduino code. I have the update set to 1 second so you can see it work. Change the msPerSecond variable to speed it up.

#include <SPI.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <utility/server_drv.h>

WiFiUDP Udp;

unsigned int UDPport = 5005;      // local port to listen for UDP packets

IPAddress UDPServer(192,168,2,250); // the ip of your Linux "server"

const int UDP_PACKET_SIZE= 48;

byte packetBuffer[ UDP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 

unsigned int noChange = 0;


unsigned long currentTime;
unsigned long secondTime;

// unsigned long msPerSecond = 200UL;
unsigned long msPerSecond = 1000UL;

int UDPCount = 0;

char ssid[] = "OhSh";     // the name of your network
char pass[] = "surfertim";

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

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(115200); 
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  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();
  Udp.begin(UDPport);
  currentTime = millis();
  secondTime = currentTime;
}

void loop() {
  // check the network connection once every 10 seconds:
//  printCurrentNet();

  currentTime = millis();

  getUDPpacket();


  if(currentTime - secondTime > msPerSecond) {
//      ShowSockStatus();
      
      Serial.println(F("\r\nUDP send"));
      sendUDPpacket(UDPServer); // send an NTP packet to a time server
      secondTime += msPerSecond;
  }


}

unsigned int udpCount = 0;

// send an NTP request to the time server at the given address 
unsigned long sendUDPpacket(IPAddress& address)
{
  udpCount++;
  
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, UDP_PACKET_SIZE); 


  sprintf((char*)packetBuffer,"Arduino count %u",udpCount);

  Udp.beginPacket(address, UDPport); //NTP requests are to port 123
  Udp.write(packetBuffer,UDP_PACKET_SIZE);
  if(Udp.endPacket() == 0) Serial.println("send failed"); 
}


void getUDPpacket() {
  if ( Udp.parsePacket() ) {  
    // We've received a packet, read the data from it

    if(Udp.remoteIP() == UDPServer) {
      Serial.print(F("UDP IP OK  "));
    }
    else {
      Serial.println(F("UDP IP Bad"));
      return;
    }
    if(Udp.remotePort() == UDPport) {
      Serial.println(F("Port OK"));
    }
    else {
      Serial.println(F("Port Bad"));
      return;
    }

    
    Udp.read(packetBuffer,UDP_PACKET_SIZE);  // read the packet into the buffer

    Serial.print(F("Received: "));
    Serial.println((char*)packetBuffer);
  }
}

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 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 ShowSockStatus() {
  for(int x = 0; x < MAX_SOCK_NUM; x++) {
    Serial.print(WiFi._state[x]);    
    Serial.print("  ");
    Serial.print(WiFi._server_port[x]);    
    Serial.print("  s=");
    Serial.print(serverDrv.getServerState(x));    
    Serial.print("  c=");
    Serial.print(serverDrv.getClientState(x));    
    Serial.print("  d=");
    Serial.println(serverDrv.availData(x));    

  }
}

Here is the Linux code.

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int sock, n, nr;
    socklen_t fromlen;
    struct sockaddr_in server;
    struct sockaddr_in from;
    
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
     printf("Can not create socket in server\n");
 
    memset(&server, 0, sizeof(struct sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_port = htons(5005);
    server.sin_addr.s_addr = INADDR_ANY;
 
    if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
      printf("Can not bind in server!\n");
    memset(&from, 0, sizeof(struct sockaddr_in));
    fromlen = sizeof(struct sockaddr_in);
    
    
    while(1) {
        int n, l1;
	unsigned char tBuf[48];
	unsigned char outBuf[48];
	
	
	fflush(stdout);

	n = recvfrom(sock, tBuf, sizeof(tBuf), 0, (struct sockaddr*) &from, &fromlen);
        if (n < 0) {
            printf("Can not receive in server!\n");
        }
        if (n == sizeof(nr)) printf("\n\nSuccess\n\n");
//        l1 = ntohl(l1);

	printf("%s from IP:%s, Port:%hu\r\n",&tBuf[0],inet_ntoa(from.sin_addr), ntohs(from.sin_port));

	sprintf(outBuf,"Server: %s\0",tBuf);
	socklen_t length = sizeof(struct sockaddr_in);	

	n = sendto(sock, outBuf, 48, 0, (const struct sockaddr *)&from, fromlen);
	if(n < 0) {
	  printf("Can not send from client");
	}
    }
}

I saved it in my Linux computer as udpserverbasic.c, then compile it with this

cc ./udpserverbasic.c -o udpserverbasic.exe

And run it with this

./udpserverbasic.exe

Insure to open udp port 5005 on your Linux server firewall or it won't work.

Thanks for the detailed answer, I'll look through everything. But I don't use linux, so I'll have to make it working with AutoIT.

In case I'm successful, I'll post the code here.

There is also an ethenet shield version of this code for those interested.
http://forum.arduino.cc/index.php?topic=198259.0

@alevinemanfail1 : I am not "advertising" my post here either. Just saving myself some typing.