Timeout (Error 10060) with Arduino Server

Hello,

I'm working on a sensor system right now where I have two computers and an arduino talking to each other.

-Computer #1 sends out a 'trigger' to the arduino, asking the arduino to take a sensor measurement.
-The arduino takes the measurement, and sends a message to Computer #2
-Computer #2 takes an action (TBD) based off of the sensor reading.

However, I'm running into the problem where my server (running a C++ program) tries to send commands to my arduino, and gets a Timeout Error (10060). I'm not sure what part of my code is causing this -- does anyone have suggestions for perhaps a better server architecture that would avoid these issues?

My code:

arduino server/client:

#include <avr/wdt.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SM130.h>
#include <SoftwareSerial.h>

//localClient parameters, for sending data to the server.
byte mac[] = {0x90, 0xA2, 0xDA, 0x0F, 0x03, 0x58};
byte ip[] = {192,168,0,250};
byte server[] = {192, 168, 0, 100};
int serverPort = 8220;

//Server parameters, for acting like a server.
int pollPort = serverPort + 2000;
EthernetServer pollServer = EthernetServer(pollPort);
EthernetClient client;

//sonar stuff
String content_string;
int NUM_SONARS = 1;
int sonarPin[] = {2, 3, 4, 5};
int triggerPin = 6;
int sonarThreshold = 12.0;
int sonarState[] = {0, 0, 0, 0};
long pulse;
int numPulses = 3;
int pulseArray[] = {0,0,0,0,0};
int filteredMode = 0;
float time;

boolean debug = true;

void setup() {
  if(debug) {
  Serial.begin(9600);
  }
  Ethernet.begin(mac, ip);
  
  wdt_enable(WDTO_8S);
  while(!client.connect(server, serverPort)) {
    ;
  }
  
  pollServer.begin();
  
  for(int i = 0; i < NUM_SONARS; i++) {
    pinMode(sonarPin[i], INPUT);
  }
  pinMode(triggerPin, OUTPUT);
  digitalWrite(triggerPin, LOW);
  time = 0;
}

void loop() {
  wdt_reset();
  time = millis();
  
  EthernetClient pollClient = pollServer.available();
  if (pollClient) {
    boolean currentLineIsBlank = true;
    String receivingString = "";
    while (pollClient.connected()) {
      //while the socket is open
      if(pollClient.available()) {
        //and there is something to read on the port, then read the available characters
        char c = pollClient.read();
        receivingString += c;
        //share with the serial monitor:
        if (c == '\n' && currentLineIsBlank) {
          if(debug) {
          Serial.print("String received -- ");
          Serial.print(receivingString);
          Serial.print("at ");
          Serial.println(time);
          }
          pollClient.println("Received message.");
          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);
    
    // parse the incoming data
    String command = split(receivingString,'\n',0);
    String payload = split(receivingString,'\n',1);
    
    String key = split(payload,'=',0);
    String value = split(payload,'=',1);
    
    //PARSE THE KEY AND VALUE NOW
    if(command == "GET") {
      //if I received a GET command, send a response to the client.
      if(key == "SONAR") {
        pingSonars();
      }
    }
    else if(command == "PUT") {
      //if I received a PUT command, do something.
      if(debug) {
      Serial.println("PUT command received.");
      }
      if(key == "PING") {
        if(debug) {
        Serial.println("Received PING");
        }
      }
      else if(key == "SETIP") {
        if(debug) {
        Serial.println("Received SETIP");
        }
      }
    }
    pollClient.stop();
    if(debug) {
    Serial.println("Closing poll client connection.");
    }
  }

}

String split(String data, char delimiter, int index) {
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==delimiter || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void isort(int *a, int n) {
  for (int i = 1; i < n; ++i) {
    int j = a[i];
    int k;
    for (k = i - 1; (k >= 0) && (j < a[k]); k--) {
      a[k + 1] = a[k];
    }
    a[k + 1] = j;
  }
}

int mode(int *x,int n){

  int i = 0;
  int count = 0;
  int maxCount = 0;
  int mode = 0;
  int bimodal;
  int prevCount = 0;
  while(i<(n-1)){
    prevCount=count;
    count=0;
    while(x[i]==x[i+1]){
      count++;
      i++;
    }
    if(count>prevCount&count>maxCount){
      mode=x[i];
      maxCount=count;
      bimodal=0;
    }
    if(count==0){
      i++;
    }
    if(count==maxCount){//If the dataset has 2 or more modes.
      bimodal=1;
    }
    if(mode==0||bimodal==1){//Return the median if there is no mode.
      mode=x[(n/2)];
    }
    return mode;
  }
}

void printArray(int *a, int n) {

  for (int i = 0; i < n; i++)
  {
    Serial.print(a[i], DEC);
    Serial.print(' ');
  }
  Serial.println();
}

void pingSonars() {
  digitalWrite(6, HIGH);
    for(int i = 0; i < NUM_SONARS; i++) {
    for(int j = 0; j < numPulses; j++) {
      pulse = pulseIn(sonarPin[i], HIGH);
      pulseArray[j] = pulse/147; //convert to inches -- 147 uS per inches
      delay(5);
    }
    isort(pulseArray, numPulses);
    filteredMode = mode(pulseArray,numPulses);
    //printArray(pulseArray,numPulses);
    if(debug) {
    Serial.print("Filtered distance for Sonar ");
    Serial.print(i);
    Serial.print(": ");
    Serial.println(filteredMode);
    }
    if((filteredMode < sonarThreshold) && !sonarState[i]) {
      //if we are closer than the threshold and previously were not, this is a rising edge:
      if(debug) {
      Serial.print("Sonar ");
      Serial.print(i);
      Serial.println(" triggered!");
      }
      sonarState[i] = 1;
    }
    else if (filteredMode > sonarThreshold && sonarState[i]) {
    //if we are greater than the threshold and previously were, this is a falling edge:
    if(debug) {
      Serial.print("Sonar ");
      Serial.print(i);
      Serial.println(" falling!");
    }
      sonarState[i] = 0;
    }
      //always respond to a poll with the current state
      content_string = "PUT\nBANANASBANANASBANANAS ";
      content_string += String(i);
      content_string += "= ";
      content_string += String(sonarState[i]);
      content_string += "\n\n";
      content += "[/TCP]"; //here as an arbitrary delimiter
      client.println(content);
      if(debug) {
          Serial.println("Posted:");
    	  Serial.println(content);
      }
  }
}

a side remark to make it a bit a faster

Why not:

  • Arduino takes continuous sensor readings
    -Computer #1 sends out a 'trigger' to the arduino, asking the arduino to send latest sensor measurement.
    -The arduino sends latest reading to Computer #2
    -Computer #2 takes an action (TBD) based off of the received reading.

This way there is always a sensor reading ready to be send to Computer #2, otherwise (depending on the sensor) it can take many milliseconds before #2 is triggered!


The receiving computer does a
output = conn.recv(2048);

Does this block until it has 2048 bytes (or timeout)?
If you make a (python) loop that receives per character instead of a wait for a full buffer, would that help?

I'll look into recv; i hadn't thought of that!

The reason I don't have the sensors 'free-running' is that they're sonars, and they tend to interfere with each other unless you make sure they all take a measurement at the same time, or they make a measurement sequentially.

I'm attempting a 'polling' solution where one computer coordinates all of the arduinos to tell them when it's their 'turn' to read, and then the arduinos take a measurement and send the data along to their respective computers.

After some hacking, it looks like it's my server functionality that's causing the problem.

Computer 1 gets a 10060 error (timeout) when it tries to send data to the arduino, so it seems like the problem is actually with my server code.

Any suggestions?