Weird TCPClient behaviour - client.print needs delays of 500ms

Hey guys,

I’ve got some trouble with the TCPClient, being that I can’t use several client.print()'s without a delay of at least 500ms between each.

My code (the important bits are within VirtualShield.cpp):

vshield-2.ino

#include "application.h"
#include "VirtualShield.h"

#define SERVER "abcde.myfritz.net"
#define PORT 80

bool flashmode = false;
int loops = 0;

VShield led = VShield(SERVER, PORT, "led");    //Server, Port, and type of virtual object

void setup() {
    pinMode(D4, INPUT);

    //flash mode - it works, though there's propably a nicer way
    if(digitalRead(D4) == LOW){
        flashmode = true;
        pinMode(D7, OUTPUT);
        digitalWrite(D7, HIGH);
    }

    else{
        led.begin("red", 3);  //color and quantity
    }
}

void loop() {
    if(!flashmode){
        led.flick(1);  //on -> off, off -> on
        led.on(2);
        led.off(3);

        loops++;
        led.looped(loops);  //debugging, how many loops so far?

        delay(1000);
    }
}

VirtualShield.cpp

#include "VirtualShield.h"
    
VShield::VShield(const char* _host, int _port, String _type){
  host = _host;
  port = _port;
  type = _type;
}

bool VShield::begin(int arg1, int arg2){      //connect to server and send information about the virtual object
    if(type = "lcd"){
        arg_type1 = ",cols:";
        arg_type2 = ",rows:";
    }
    else return false;
    
    bool res = client.connect(host, port);
    if(res){
        client.println();
        client.println();
        client.println("Connected.");
        delay(delayT);
        client.print("type:");
        delay(delayT);
        client.print(type);
        delay(delayT);
        client.print(",cmd:begin");
        delay(delayT);
        client.print(arg_type1);
        delay(delayT);
        client.print(arg1);
        delay(delayT);
        client.print(arg_type2);
        delay(delayT);
        client.print(arg2);
        delay(delayT);
        client.println("$"); // = end of command
        delay(delayT);
    }
    return res;
}

bool VShield::begin(String arg1, int arg2){
    if (type = "led"){
        arg_type1 = ",color:";
        arg_type2 = ",quantity:";
    }
    else return false;
    
    bool res = client.connect(host, port);
    if(res){
        client.println();
        client.println();
        client.println("Connected.");
        delay(delayT);
        client.print("type:");
        delay(delayT);
        client.print(type);
        delay(delayT);
        client.print(",cmd:begin");
        delay(delayT);
        client.print(arg_type1);
        delay(delayT);
        client.print(arg1);
        delay(delayT);
        client.print(arg_type2);
        delay(delayT);
        client.print(arg2);
        delay(delayT);
        client.println("$"); // = end of command
        delay(delayT);
    }
    return res;
}

void VShield::print(String msg){
    if(type = "lcd"){
        client.print("type:");
        delay(delayT);
        client.print(type);
        delay(delayT);
        client.print(",cmd:print,msg:");
        delay(delayT);
        client.print(msg);
        delay(delayT);
        client.print("$"); // = end of command
        delay(delayT);
    }
}

void VShield::flick(int led){
    if(type = "led"){
        client.print("type:");
        delay(delayT);
        client.print(type);
        delay(delayT);
        client.print(",cmd:flick");
        delay(delayT);
        client.print(",led:");
        delay(delayT);
        client.print(led);
        delay(delayT);
        client.print("$"); // = end of command
        delay(delayT);
    }
}

void VShield::on(int led){
    if(type = "led"){
        client.print("type:");
        delay(delayT);
        client.print(type);
        delay(delayT);
        client.print(",cmd:on");
        delay(delayT);
        client.print(",led:");
        delay(delayT);
        client.print(led);
        delay(delayT);
        client.print("$"); // = end of command
        delay(delayT);
    }
}

void VShield::off(int led){
    if(type = "led"){
        client.print("type:");
        delay(delayT);
        client.print(type);
        delay(delayT);
        client.print(",cmd:off");
        delay(delayT);
        client.print(",led:");
        delay(delayT);
        client.print(led);
        delay(delayT);
        client.print("$"); // = end of command
        delay(delayT);
    }
}

void VShield::looped(int loops){
    client.print("  -- looped -- loops: ");
    client.println(loops);
}

VirtualShield.h

#include "application.h"

class VShield {
public:
    //Server name + port, specifying type of object
    VShield(const char* _host, int _port, String type);
    
    //'begin' for different objects + client.connect
    bool begin(int arg1, int arg2);     //lcd (for now)
    bool begin(String arg1, int arg2);  //led (for now)
    
    //for lcd only
    void print(String msg);
    
    //for led only
    void flick(int led);
    void on(int led);
    void off(int led);
    
    //meant for debugging
    void looped(int loops);

private:
    TCPClient client;
    const char* host;
    int port;
    String type;
    int delayT = 500;
    
    String arg_type1;
    String arg_type2;
};

Output:

Connected.
type:led,cmd:begin,color:red,quantity:3$

type:led,cmd:flick,led:1$
type:led,cmd:on,led:2$
type:led,cmd:off,led:3$
  -- looped -- loops: 1
type:led,cmd:flick,led:1$
type:led,cmd:on,led:2$
type:led,cmd:off,led:3$
  -- looped -- loops: 2
type:led,cmd:flick,led:1$
type:led,cmd:on,led:2$
type:led,cmd:off,led:3$
  -- looped -- loops: 3
type:led,cmd:flick,led:1$
type:led,cmd:on,led:2$
type:led,cmd:off,led:3$
  -- looped -- loops: 4
[...]

My first try was to have only one string containing all the information and send it with one single client.print(cmd). However, the core would send only part of the string (something around 10 chars), then hang and eventually blink red, SOS 1 (hard fault). I then saw someone use delays of 10ms between each client.print, so I went and printed every part of the command separately with said delay. But it wasn’t until I increased the delay to 500ms until the Core behaved as expected. Funny enough it is precisely 500ms. If I go beneath that (even 499ms), the Core will hang again.

The idea is to have a virtual shield (as you might have already guessed from the library name :smiley: credits for the idea to http://www.1sheeld.com/). So I would much like it to be as ‘realtime’ as possible.

What am I doing wrong?