TCP Server drops while loop and strange character output to client

2 problems here:

I have a MCP9700A temp sensor connected to my spark.
I have my spark setup as a tcp server which will report the temperature to the clients every 10s.

Hardware is simple. temp sensor connected to 3V3*, A0 and gnd. Powered using USB wallwart.

Problem 1:

When a client is connected that client should get the message “Hello”. On Connection only. i have run this several times and at some point it starts to send a stream of “Hello”’ 's. why?

Problem 2:
I guessing that my temp sensor is sensing correctly but i can’t seem to output the correct value constantly.
as you can see on the screen capture i get a weird character sometimes.
is this to do with my analogRead or my server.print?

i do get from time to time a fast flashing cyan. or a red (hard fault).
i have also from time to time lost connection to my spark aswell.

Ok, the documentation shows this example

// telnet defaults to port 23
TCPServer server = TCPServer(23);
TCPClient client;

void setup()
{
  // start listening for clients
  server.begin();

  // Make sure your Serial Terminal app is closed before powering your Core
  Serial.begin(9600);
  // Now open your Serial Terminal, and hit any key to continue!
  while(!Serial.available()) SPARK_WLAN_Loop();

  Serial.println(Network.localIP());
  Serial.println(Network.subnetMask());
  Serial.println(Network.gatewayIP());
  Serial.println(Network.SSID());
}

void loop()
{
  if (client.connected()) {
    // echo all available bytes back to the client
    while (client.available()) {
      server.write(client.read());
    }
  } else {
    // if no client is yet connected, check for a new connection
    client = server.available();
  }
}

Ok, lets get this thing apart.

client.connected() means another computer has connect to the core
client.available() means data has been send from the client

Using the sample above shows the right behaviour. If client is connected and client data is received the code send them back. If no data is received but the client is still connected, do nothing. If the client has disconnected, check for new connection.

Now your code

Line 28-31: If a client has connected you set a LED and wait 1 second => why?
Line 33: You send to the client "Hello!"
Line 35-47: If the client has send some data, you send for every single byte to the client the temp.
Line 49: And you wait for every single byte 9.5sec.
Then start all over at Line 26 (client still connected, sending some data)

What you should do

  • Do NOT use delay()
  • use millis() to detect interval times. If millies()>millisbefore+9500 => send temp data => then save current millis() in millisbefore

Imagine your code runs as fast as hell, and no delays are allowed. How would you write it then?
Please do not send Code as graphic, it is very hard do read and to show you how to correct it.

1 Like

Here’s my code to make it more clear.

Line 28-31 set LED to indicate to me that it has connected and the second is to allow time for it to establish a stable connection. I have read some postings indicating that repeated postings or requests in quick succession can cause the red led sos. i don’t see the red anymore but i do see a blue breathing led from time to time.

Line 35-47 if the client has sent some data. while the client is sending data send the temp over and over every 9.5 secs. if the client stops sending data then start over at line 26.

Thanks for the tips i will make the changes to millis(). i hope this helps with the crashing but i don’t think this will help the odd Character that i get on the print of temp.
Should i be putting a “millis wait” before manipulating the temp value after the reading of A0 to allow the AtoD time to process?

Also in the Example you posted there is a “while(!Serial.available()) SPARK_WLAN_Loop();” what is this?

// telnet defaults to port 23
TCPServer server = TCPServer(23);
TCPClient client;

float temp;
int led = D7;
int Sensor = A0;

void setup()
{
//PIN Inputs
pinMode(Sensor, INPUT);
pinMode(led, OUTPUT);

// start listening for clients
server.begin();

Serial.begin(9600);

Serial.println(WiFi.localIP());
Serial.println(WiFi.subnetMask());
Serial.println(WiFi.gatewayIP());
Serial.println(WiFi.SSID());

}

void loop()
{
if (client.connected())
{
digitalWrite(led, HIGH);
delay(1000);

server.write("Hello!");

while (client.available()) 
{
// echo all available bytes back to the clients
  server.write(client.read());
  
// Read Sensor value
  temp = analogRead(Sensor)*3.3/4095.0;
  delay(500);
  
  temp = temp - 0.5;
  temp = temp * 100;
// Send Temperature to Clients  
  server.println(temp);

  delay(9500);
}

}
else
{
digitalWrite(led, LOW);
// if no client is yet connected, check for a new connection
client = server.available();
}
}

so i did a little more troubleshooting.
i stripped out a lot and what I’m running into is the communication fails after 2 writes.
i have tried the same code on 2 different spark cores and they both fail at the same place.
the response i get when it connects is “Hello1Hello2” and that’s it. the core then displays a red led (sos) hard fault error.
here’s the code i’m running for this test.
// telnet defaults to port 23
TCPServer server = TCPServer(23);
TCPClient client;

float temp;
int led = D7;
int Sensor = A0;
unsigned long millisBefore = millis();

void setup()
{
//PIN Inputs
pinMode(Sensor, INPUT);
pinMode(led, OUTPUT);

// start listening for clients
server.begin();

}

void loop()
{
if (client.connected())
{
digitalWrite(led, HIGH);
server.write(“Hello1”);
server.write(“Hello2”);
server.write(“Hello3”);
server.write(“Hello4”);
server.write(“Hello5”);
server.write(“Hello6”);
server.write(“Hello7”);
server.write(“Hello8”);
server.write(“Hello9”);
}
else
{
digitalWrite(led, LOW);
// if no client is yet connected, check for a new connection
client = server.available();
}
}

thanks Digixx. i think it’s a little deeper than my code now.

I will check that out

Hi Bootes,

This is my testing code, modified from your code

// telnet defaults to port 23
TCPServer server = TCPServer(23);
TCPClient client;

int led = D7;

void setup() {
    //PIN Inputs
    pinMode(Sensor, INPUT);
    pinMode(led, OUTPUT);

    // start listening for clients
    server.begin();
    Serial1.begin(115200);
    Serial1.println(WiFi.localIP());
    Serial1.println(WiFi.subnetMask());
    Serial1.println(WiFi.gatewayIP());
    Serial1.println(WiFi.SSID());
}

void loop() {
    SPARK_WLAN_Loop(); // keep connection with the cloud
    if (client.connected()) {
        Serial1.print("c"); // the beacon that we have a valid connection here
        digitalWrite(led, HIGH);
        server.write("Hello"); // say Hello to the client
        delay(50); // wait some short time to help debugging
        server.write(13);
        server.write(10); // new line please
        while (client.available()) {
            Serial1.print("a"); // ooh, the client has send some data
            server.write(client.read()); // just send back whats received
            delay(50); // debugging helper again
        }
    } else {
        digitalWrite(led, LOW);
        // if no client is yet connected, check for a new connection
        client = server.available();
    } 
}  

It sends endless Hello and write back received data too.

Case 1: If I start the telnet session it will send Hello forever. As a reference, the code also sends beacon data to Serial1, my debug connection.

Case 2: typing some characters to the core is handled right, the debugger shows the character ‘a’.

Case 3: If I keep the finger on the keyboard sending many character in series, after some seconds, the debugger does not send any beacons and after a fiew seconds the pulsing red led shows a mature failure. The core seems to recover from that state, but ends in blinking cyon after some 2 minutes (no new telnet session to the core since then). It recovers again and connection is possible.

You are right, there must be something deeper then our code can handle. There is no buffer handling. I do not know if there is any overflow handling on TCP side at all.

It can be informative to include sending some millis() as debugging info. In my project I noticed that many hickups have similar duration (most frequent: 60 seconds, runner-up: 20 seconds), indicating some low level time-out.
Additionally you could add pinging your router (gateway). In my case the user code often regains control after a time-out, but pinging the gateway (once or multiple times) fails, whereas before the disturbance it succeeded…

I removed the delay here

while (client.available()) {
            Serial1.print("a"); // ooh, the client has send some data
            server.write(client.read()); // just send back whats received
        }

And I can still kill the core sending keyboard data. This usage is not reliable and is therefore useless?

I think you might have built a packet amplifier since for every character you get from the client, you are sending a one character packet back. I know that the example code does this, but it is just an example not built for a particular purpose.

Have you tried gathering the client.read() bytes into an array and then writing the whole array back via the server?

You could also try looking at the return values from server.write() which should be positive on success.

1 Like

bko, you are right.
I forgot that data is send over TCP where one character only has to be transfered within a IP packet.

I am somekind old fashioned still thinking in RS232 terms. :wink:

1 Like