Photon transmission over WiFi (no cloud)

Hello verybody,

I am working on a transmission between a mobile (robot) and a ground station (laptop) using 2 photons, 1 as ‘server’ (the laptop) and the other as ‘client’ on the mobile (the robot). My purpose is to transmit a data telemetry from the robot to the laptop at high rate in WiFi through the router connected to the Internet.

In the robot, the photon (client) is connected to the sensors via I2C communication and is polling regularly the data, then fills a telemetry buffer (currently 77 bytes long). Ideally I would like to transmit more than 10 frames per second (corresponding to a serial link of 9600 bauds).

I have tried the TCP connection through the cloud with poor performance and frequent and rapid disconnections.

Now I am trying to by-pass the cloud and to use directly the WiFi connection for a TCP transmission between both photons. For this I use the Particle.disconnect() function from the Firmware API (Cloud Functions).

1- My first question is: do I need to disconnect both the server and the client from the cloud or only the server?

Once I have applied the Particle.disconnect() function (on both devices, first instruction in setup()), the leds turn green but not cyan, which looks ok as the photons are only connected to the WiFi and not to the cloud.

After a few tries it appears that sometimes one or both photons are blinking green and sometimes one or both are breathing green. I may have one blinking (the server) and the client breathing. During that time, the transmission goes on better than with the cloud connected, but still with low performance (3-5 frames per second) and sometimes disconnection where the client hangs (not blinking/breathing anymore).

2- My second question is: what should be the normal behaviour in this situation: blinking or breathing? And what is the meaning of ‘blinking’ and ‘breathing’?

3- Finally I would like to know if this transmission is optimized, or how to optimize it, or should I use a UDP connection instead to transmit faster?

Thank you very much for your support.

Here is the central code for the client:

/******************************************/

define SERVER_IP {192,168,1,10}
define SERVER_PORT 23


// Declarations, initializations...

void setup()
{
    Particle.disconnect(); // Disconnect the cloud
    
    Wire.begin(); // I2C start
    

    /* Setup Client/Server */
    byte ip[] = SERVER_IP;
    client.connect(ip, SERVER_PORT);

    // Initialize the sensors...
  
    // Initialize the telemetry and I2C buffers
}



void loop()
{
    // Acquisition of the sensors...

    // Filling the telemetry buffer tmBuffer[]...

    // Sending the telemetry buffer over WiFi
    if (client.connected()) {
        client.write(tmBuffer, TM_LENGTH);
        client.flush();
    }
    else
    {
    }
}

Following is the central code for the server:

/************************************************/



TCPServer server = TCPServer(23);
TCPClient client;

void setup()
{
    Particle.disconnect();
    
    Serial.begin(9600); // For communication with the laptop
    Serial.println();
    Serial.print("Photon Server local IP: "); 
    Serial.println(WiFi.localIP()); // To discover the IP address of the server and type it in the client code
    
    server.begin();
}

void loop()
{
  if (client.connected()) {
      
    while (client.available()) {
        rxBuffer[rxIndex++] = client.read();
        
        if (rxIndex == RX_BUFSIZE) {
            rxIndex = 0;
            Serial.write(rxBuffer, RX_BUFSIZE);  // to be read by the laptop through USB line
        }
    }
  } else {
    client = server.available();
  }
}
1 Like

You should read up on SYSTEM_MODE(SEMI_AUTOMATIC) and are you not missing a TCPClient object in your client code?

@jmeuf, FWIW, I put some code up on github that seems to work fairly well for tcp on manual without the cloud. It probably needs more tweaking, but maybe it could be helpful to you:

Hi @bpr
I have issues eith a photon project like yours.
First of all I suggest to set serial speed to 115200 baud. This seems to work better in general with TCP…
Second about UDP. That’s definitely a good approach. To make a ‘reliable UDP’ connection send messages twice and let the server acknowledge.
Third insert pauses between steps like 100 millis. When everything works decrease them one by one untill a value that balances speed versus reliability.

@marcus, I guess your mistaking me for the OP; your suggestions sound valid in general. There may be issues with my github code but not the ones you mention :relieved:

@ScruffR: Sorry, you are right, I forgot to mention the TCPClient object that is indeed in the code! What would the SEMI_AUTOMATIC mode bring compared to the AUTOMATIC mode with Particle.disconnect() instruction?

@bpr: thanks for the code. I will have a look at it.

@marcus: thank you very much for the tips. I will implement step by step.

Thank you all for your support. I have some homework now :wink: I will post my results and findings.

JM

SEMI_AUTOMATIC is the dedicated mode for this kind of use case (temporarily disconnected).

Hello bpr,

I have flashed your code: TCPClientFast in the client and TCPserverSimple in the server. It looks to work pretty well, straight ‘out of the box’! I understand that the transmission is visualized by the led blinking blue (D7). Thank you very much for that.

Now I would like to interface the photons to the PC.

I am pretty new in java script. Could you kindly provide some useful links on that and advise on how to compile the .js applications and how to interface them with a c++ program (the telemetry app) that I compile with a gcc++ compiler such as CodeBlocks. Or should I completely develop my applications in java script?

Thank you for your help.

JM

Hi @jmeuf,

For the .js apps, just make sure you have node installed, then enter node nodetcpserver.js in your terminal.
You might change the ‘9’ in sock.write(‘9’) to the value of the photon client’s replymsg, if you want to duplicate the photon client server back and forth messaging.
Note that node.js apps aren’t compiled, just run on the command line.
I’m entirely self-(mis)taught, so I don’t have any specific links to recommend other than nodejs.org. Normally I just search around the web. There are LOTS of javascript tutorials out there! Also, there are LOTS of ready-made node modules/examples you can install/copy/extend.

Hello bpr,

thank you very much for all your advices.
I have now node installed and can run your javascripts from the console.
My configuration is as follow:

Photon1 (client) connected to the Arduino for polling sensor data, running 'TCPClientFast’
Photon2 (server) connected to the PC via USB (but I guesse the USB link is useless in this case), running ‘TCPServerSimple’

If I run ‘nodetcpserver.js’ on the PC, will it be in communication with the Photon1?

What do you mean by “You might change the ‘9’ in sock.write(‘9’) to the value of the photon client’s replymsg” knowing that replymsg on the Photon1 holds: “TheInMsg and then a whole lot more characters than before”?

Thank you

JM

Hello bpr,

I have now completely recoded the client and server photons firmwares using your github code and implementing the sensor acquisition.
I am using the message from client to server for the telemetry and the reply message for commanding the robot.
I evaluate the transmission rate to something like 4 messages per s (in sync with the blue led), and this lokks not depending on the messages length.
Is there a way to improve / accelerate the transmission rate to reach, say, 10 messages per second?

Thank you a lot for this pices of code that looks much more robust and repetitive than going through the cloud.

JM

@jmeuf, I can’t answer your question about increasing transmission rate, other than to say that eliminating waiting for reply would help.
BTW, putting the @ in front of the screen name is the way to make sure I or anyone else you want to alert gets the message.

@bpr
Thank you for the @tip!
I am not sure where is the delay in your code. For example in TCPServerSimple:

  in(inmsg,40); //40 pure trial and error and longer than in client
  myInStr =inmsg;
  if (myInStr.indexOf(clientmsg)  >= 0) {
    digitalWrite(D7, 1);          // Flashes the LED
    lastTime = millis();
    while ( millis()-lastTime < 5) { } //50
    digitalWrite(D7, 0);          // Flashes the LED
    out(replymsg);
  }//if (myInStr.indexOf(clientmsg)  >= 0)

the reply message (out) follows directly the flashing of D7 (for 5 ms) which follows the test of myInStr.
The delay() at the very beginning of the loop is 1 ms only.

The code in the client is quite similar.

Could you help me to locate such delay?

Thank you.

@jmeuf, I just meant to say that if you only want to send data from the client to the server, you could eliminate sending the reply that verifies receipt, i.e., comment out this whole code block, which would speed up things a bit.

/*:
myInStr =inmsg;
if (myInStr.indexOf(clientmsg) >= 0) {
digitalWrite(D7, 1); // Flashes the LED
lastTime = millis();
while ( millis()-lastTime < 5) { } //50
digitalWrite(D7, 0); // Flashes the LED
out(replymsg);
}//if (myInStr.indexOf(clientmsg) >= 0)
*/
Also, you would want to eliminate the corresponding receipt block in the client code

@bpr

I understand. In fact this is good to keep the reply because that will be for me the channel to remote control the robot. Nevertheless, I reduced the length of the reply message to 16 bytes instead of 50-60 as it was originally.

I will perform some transmission tests in this configuration and see how it looks like with real data.
I guess the next step to improve the data rate will be to go to UDP protocol.

Thank you again for all your advises!

JM