Arduino w/Wiznet 5100, Connection drops out frequently

I’m working on a design in which i’m using the Atmega328 and the Wiznet 5100. They are talking to LabView on a dedicated PC, using TCP, with the PC as the Server. I’m not very familiar with this stuff so I may have some errors here.

The PC and Arduino/5100 are connected directly via a CAT5 cable, no other devices are on the network.

I am able to connect to the Arduino/5100 quite reliably. Once connected I am sending 6 bytes of data every 500-2000mS to the Arduino, and nothing back to the PC. The 6 bytes turn digital IO on and off.

Randomly, the connection to the server will drop out. I used Wireshark to sniff the connection, and TCP ZeroWindow errors occur. I believe this means that the receive buffer on the Arduino/5100 is full, but I am not sending large amounts of data, nor am I sending data at ludacris speed.

Any ideas?

Code to follow in next post

#include <SPI.h>
#include <Ethernet.h>
#include <MemoryFree.h>


//Define Unit MAC Address
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0E, 0xD1, 0x61 };
//End Unit MAC Address

//Define Unit IP Address
IPAddress ip(192,168,1,177);
//IPAddress ip(10,1,10,177);
//End Unit IP Address

//Define Server IP Address
IPAddress server(192,168,1,30); 
//IPAddress server(10,1,10,30); 

//End Server IP Address

//Define Ethernet Client
EthernetClient client;
//End Ethernet Client

//Define Port
#define Port 50000


//Define IO Pins
#define Connection 8  //Client connected LED, active LOW
#define NoConnection 9 //Client not connected LED, active LOW

int OutputPins[] = {2,3,4,5,6,7,14,15,16,17,18,19};







//End Define IO Pins

void setup(){
  
//Set Pin Modes
pinMode(Connection, OUTPUT);
pinMode(NoConnection, OUTPUT);
SetPinModeOutput(OutputPins,12);
//End Pin Modes

for(int i = 0; i<20;i++){
  
 digitalWrite(Connection, HIGH);    //Flash the LED's a bunch to determine if the board was reset.
 delay(50);
 digitalWrite(Connection, LOW);
 digitalWrite(NoConnection, HIGH);
 delay(50);
 digitalWrite(NoConnection, LOW);
 delay(50); }

Ethernet.begin(mac,ip);  //Start the Ethernet connection

//Serial.begin(9600);  //Start the serial connection at 9600 baud

delay(1000); // Wait a bit to let the ethernet enable
  
ConnectionLedState(LOW);  //Turn on disconnected LED

//Try to connect to the server
ClientConnect();
}
/******************************************************************************/
/******************************** MAIN LOOP ***********************************/
/******************************************************************************/
void loop(){
   
   // Serial.print("freeMemory()=");
   // Serial.println(freeMemory()); 
GetEthernetData();
//Serial.print("Buffer contains ");
//Serial.println(client.available());
//Serial.println(millis());

WriteEthernetData(freeMemory());

if(ClientDisconnect() == 1){
  
  ClientConnect();}
  

delay(5);
    


}

/******************************************************************************/
/****************************** END MAIN LOOP *********************************/
/******************************************************************************/

//Controls the bicolor led, red = no connection, green = connection
void ConnectionLedState(boolean State){  //HIGH = connection
  
if(State == HIGH){
  
  digitalWrite(Connection, LOW);
  digitalWrite(NoConnection, HIGH);
}

if(State == LOW){
  digitalWrite(Connection, HIGH);
  digitalWrite(NoConnection, LOW);
}
  
}

//End Connection LED

/******************************************************************************/
/**************************** Get Ethernet Data *******************************/
/******************************************************************************/

char GetEthernetData(){
  
char temp = 0;
int count = 0;


int NumOfBytes = 0;

int TimeOut = millis();

if(client.available() > 0){  //If data is available
    
    char Size[2];  //Create a char array for the size indicator
    
    for(int x=0; x<2; x++){  //Get the chars for the size of the data packet
      Size[x] = client.read();}
      
      NumOfBytes = atoi(Size);  //Change from char array to string.
      
    
   // Serial.print("This many bytes: ");
   // Serial.println(NumOfBytes);
    
    while(client.available()<NumOfBytes && (millis() - TimeOut <350)){  //Wait for the packets to arrive
    delay(25);
    //Serial.println("Waiting");
    }}
    
char Data[NumOfBytes];  //Create an array based on the size if the packet

for(int i = 0; i < NumOfBytes; i++){  //Get the packet

  Data[i] = client.read();
  
}
if(NumOfBytes > 0){  //If data was read, pass it to the function to parse the data
  
  ParseEthernet(Data, NumOfBytes);
}
}



/******************************************************************************/
/************************** End Get Ethernet Data *****************************/
/******************************************************************************/

/******************************************************************************/
/*************************** Parse Ethernet Data ******************************/
/******************************************************************************/

void ParseEthernet(char Data[], int Size){
  
char temp[2];  //Create temp char array
int CommandSize = Size/2;
int commands[CommandSize];  //Command array is half the size of char array.

for(int i = 0; i < Size; i++){
  
  temp[0] = Data[i*2];    //Get the MSB of the value
  temp[1] = Data[(i*2)+1];  //Get the LSB of the value
  commands[i] = atoi(temp);  //Convert that to an int
  
}

Control(commands, CommandSize);

}

/******************************************************************************/
/************************* End Parse Ethernet Data ****************************/
/******************************************************************************/



/******************************************************************************/
/*************************** Write Ethernet Data ******************************/
/******************************************************************************/
void WriteEthernetData(int Data){
  //while (Serial.available() > 0) {  //While serial data available print to Network
   
    char inChar = Data;
    if (client.connected()) {
      client.print("OK"); 
      client.print('r');
      client.print('\n');
     
    }
  //}
}
/******************************************************************************/
/************************* End Write Ethernet Data ****************************/
/******************************************************************************/

/******************************************************************************/
/**************************** Client Disconnect *******************************/
/******************************************************************************/

int ClientDisconnect(){
  
   if (!client.connected()) {
    client.stop();
    ConnectionLedState(LOW);
  return 1;}
    else{return 0;}
}

/******************************************************************************/
/************************** End Client Disconnect *****************************/
/******************************************************************************/

/******************************************************************************/
/****************************** Client Connect ********************************/
/******************************************************************************/

void ClientConnect(){

if(client.connect(server, Port)){  //If server connection is sucessful, turn on Green LED
  ConnectionLedState(HIGH);
  client.flush();}
else(ConnectionLedState(LOW));  //Else, turn on RED LED

}
/******************************************************************************/
/*************************** End Client Connect *******************************/
/******************************************************************************/

/******************************************************************************/
/********************************* Control ************************************/
/******************************************************************************/

void Control(int Commands[], int Size){
  
  //Serial.print("Size is:");
  //Serial.println(Size);
  
  for(int i = 0; i < Size; i+=2){
   
   ExecuteCommand(Commands[i], Commands[i+1]); 
   //Serial.println(i);
   //Serial.println(i+1);
    
  }
  //Serial.println();
  
}
/******************************************************************************/
/******************************** End Control *********************************/
/******************************************************************************/

/******************************************************************************/
/****************************** Execute Command *******************************/
/******************************************************************************/

void ExecuteCommand(int Command, int Value){
  
boolean State = LOW;

if(Value == 1){
  
  State = HIGH;}    
digitalWrite(Command, State);
 
  
}

/******************************************************************************/
/**************************** End Execute Command *****************************/
/******************************************************************************/

/******************************************************************************/
/******************************* Set Pin Mode *********************************/
/******************************************************************************/

void SetPinModeOutput(int Pins[],int Size){
  
  for(int i = 0; i < Size; i++){
    
    pinMode(Pins[i], OUTPUT);}
  
}

/******************************************************************************/
/***************************** End Set Pin Mode *******************************/
/******************************************************************************/

You may be running out of sockets. Add this to your sketch, then call it somewhere in loop(). I would call it right after the delay(5) call.

#include <utility/w5100.h>

void ShowSockStatus()
{
	for (int i = 0; i < MAX_SOCK_NUM; i++) {
		Serial.print("Socket#");
		Serial.print(i);
		uint8_t s = W5100.readSnSR(i);
		Serial.print(":0x");
		Serial.print(s,16);
		Serial.print(" ");
		Serial.print(W5100.readSnPORT(i));
		Serial.print(" D:");
		uint8_t dip[4];
		W5100.readSnDIPR(i, dip);
		for (int j=0; j<4; j++) {
			Serial.print(dip[j],10);
			if (j<3) Serial.print(".");
		}
		Serial.print("(");
		Serial.print(W5100.readSnDPORT(i));
		Serial.println(")");
	}
}

Here is the format of the serial display. (remote port) is the “client id”.
Socket#: D:(remote port)

The common status byte codes are
0x00 = available (not used)
0x14 = server waiting for client
0x17 = server with client
0x22 = udp

It is bad in your case if there are no status 0x00 sockets.

Thanks! I will hopefully try this tomorrow morning, I think i nuked the W5100, so I had to rebuild the board!

From my research, a socket is a particular connection to an IP and port. If I'm only talking to one PC with a single IP, and the W5100 is capable of multiple sockets, how could be out of sockets?

Thanks!!

I am able to connect to the Arduino/5100 quite reliably. Once connected I am sending 6 bytes of data every 500-2000mS to the Arduino, and nothing back to the PC. The 6 bytes turn digital IO on and off.

That sounds like the arduino is the server and the pc is the client, which seems to be different from

i’m using the Atmega328 and the Wiznet 5100. They are talking to LabView on a dedicated PC, using TCP, with the PC as the Server.

From my research, a socket is a particular connection to an IP and port. If I'm only talking to one PC with a single IP, and the W5100 is capable of multiple sockets, how could be out of sockets?

If the socket is not closed correctly on the Arduino end, the socket is no longer available. Leaving characters in the socket rx buffer is the best way to stop the socket from closing.

Since there are only 4 sockets, it is easy to run out of sockets. I open multiple sockets to the same ip but different ports in some of my sketches. FTP requires connections to two ports on the same ip simultaneously.

edit: The way you can tell if crash is caused by unavailable sockets is if the ShowSockStatus() call shows all 4 sockets have a status of 0x17. That is the status code for a client connected to the Arduino server, or the Arduino as a client is connected to a server. If there is not a socket with a status of 0x00, any subsequent connection attempt will fail.

zoomkat:

I am able to connect to the Arduino/5100 quite reliably. Once connected I am sending 6 bytes of data every 500-2000mS to the Arduino, and nothing back to the PC. The 6 bytes turn digital IO on and off.

That sounds like the arduino is the server and the pc is the client, which seems to be different from

i'm using the Atmega328 and the Wiznet 5100. They are talking to LabView on a dedicated PC, using TCP, with the PC as the Server.

Made a mistake in typing that out. I am trying to have the PC as the Server and the arduino as the client.

SurferTim:
If the socket is not closed correctly on the Arduino end, the socket is no longer available. Leaving characters in the socket rx buffer is the best way to stop the socket from closing.

Since there are only 4 sockets, it is easy to run out of sockets. I open multiple sockets to the same ip but different ports in some of my sketches. FTP requires connections to two ports on the same ip simultaneously.

edit: The way you can tell if crash is caused by unavailable sockets is if the ShowSockStatus() call shows all 4 sockets have a status of 0x17. That is the status code for a client connected to the Arduino server, or the Arduino as a client is connected to a server. If there is not a socket with a status of 0x00, any subsequent connection attempt will fail.

I have tested to see if available sockets was the issue. Only socket 0 showed a connection to the server, sockets 1-3 had 0x00 status.

What I did notice though, was the addition of ShowSockStatus() caused the arduino to reset itself. I monitored the Reset line and it was not pulled down externally, or noisy.

Doing some reading, it appears that other people have had the arduino reset when not enough RAM was available, specifically using Serial.print. I'm wondering if my issue is in fact RAM based, maybe i'm reaching the limits of ram on the arduino?