Go Down

Topic: Arduino TCP socket client (Read 13732 times) previous topic - next topic

Life_Learner

Jul 26, 2015, 06:17 pm Last Edit: Jul 26, 2015, 06:23 pm by Life_Learner
Hi, I'm desperately in need of guidance here. Below is the code to program Arduino Yun to act as a client. In my PC, I have set up a LabVIEW Server and successfully connected to the Arduino Yun. However, it seems that the client.read() in the code isn't reading any string 'H' or 'L' that was sent over to the Arduino Yun.

Please help me. I really appreciate it. Thank You Kindly.

Code: [Select]

#include <Bridge.h>
#include <YunClient.h>

YunClient client;      //Initialize YunClient client
int ledPin = 13;
char incomingByte;
byte ip[] = {192, 168, 240, 152 };
int port = 255;

static boolean clientActive = false; //Initialize boolean clientActive to store the value false


Code: [Select]


// The setup function runs once when the reset button is pressed or the board is powered up
void setup() {         
pinMode(13,OUTPUT);    // Initialize digital pin 13 as an output
digitalWrite(13,HIGH); // Turn the LED on
Bridge.begin();        // Bridge startup
digitalWrite(13,LOW);  // Turn the LED off
Serial.begin(9600);
}

Code: [Select]

void loop() {
client.connect(ip,port);  // Connects to a specified IP address and port
if (client.connected()) { // Returns true if the client is connected, false if not
if (!clientActive)
Serial.println("New Client connection.");

clientActive = true;

if (client.available()) { // Returns the number of bytes available for reading
incomingByte == client.read(); // Read the next byte recieved from the server the client is connected to
Serial.print("From client: \"");
while(client.available())
Serial.print((char)client.read());
Serial.println("\"");
}
if (client.read() == 'H') {
  digitalWrite(13,HIGH);
}
if (client.read() == 'L') {
  digitalWrite(13,LOW);
}
}
else {
if (clientActive) {
client.stop();       // Disconnected from the server
Serial.println("Client disconnected.");
}
clientActive=false;
client.connect(ip,port);
}
}

Life_Learner

This attachment is the LabVIEW Server which I'm using. The connection is able to pass through.
Please help. Thank You

ShapeShifter

Your data reading logic is highly suspect. My first comment is that I suggest you adopt and follow a code indentation style. The compiler is perfectly happy to have everything lined up in the first column, but it will make your life much easier to use a structured style, and make the organization of the code much easier to follow.

I've taken the liberty of indenting your code in a manner that makes the structure stand out, even if it does take up a few extra lines. I've also added line numbers for the discussion that follows.

Code: [Select]

 1   void loop()
 2   {
 3      client.connect(ip,port);  // Connects to a specified IP address and port
 4      if (client.connected())   // Returns true if the client is connected, false if not
 5      {
 6         if (!clientActive)
 7         Serial.println("New Client connection.");
 8
 9         clientActive = true;
10
11         if (client.available())  // Returns the number of bytes available for reading
12         {
13            incomingByte == client.read(); // Read the next byte recieved from the server the client is connected to
14            Serial.print("From client: \"");
15            while(client.available())
16               Serial.print((char)client.read());
17            Serial.println("\"");
18         }
19         if (client.read() == 'H')
20         {
21            digitalWrite(13,HIGH);
22         }
23         if (client.read() == 'L')
24         {
25            digitalWrite(13,LOW);
26         }
27      }
28      else
29      {
30         if (clientActive)
31         {
32            client.stop();       // Disconnected from the server
33            Serial.println("Client disconnected.");
34         }
35         clientActive=false;
36         client.connect(ip,port);
37      }
38   }


At line 11, you are connected, and you check if any characters are available. That's reasonable, but the logic quickly falls apart.

Line 12: you read an incoming character from the connection, and store it in the variable incomingByte. But you never do anything else with that variable, you have in effect thrown the first received character away.

Line 14 prints out the beginning of a message, then lines 15 and 16 loop through all of the available characters and echo them to the serial port.  Line 17 finishes the message and prints a closing quote.

At Line 19, you are in one of two states: either there was no incoming data available (line 11 returned zero) or you have used up all available characters because of the loop on lines 15 and 16. So, at this point, it's a pretty safe bet that there are no characters waiting to be read. But the code in line 19 tries to read a character anyway, and the odds are virtually certain that there will be nothing, so read() will return -1. That is not the same as 'H' so the statement on line 21 will not be called.

At line 23, we are in the same situation: it's very unlikely a character is available in unless it has come in during the few microseconds since completing the previous logic that read and printed all of the waiting data. So read() will likely return -1. Again, this is not the same as 'L' so the statement on line 25 will never get called.
_________________

At line 13, you are reading a character, and putting it in a variable. You probably want to be using that value rather than keep on reading more characters.

Lines 14 to 17 print all data that is available from the client. You probably don't want to do this. I would think it should be a simpler version that does not have a while loop, and simply prints the value from incomingByte, with appropriate text decorating the output.

Then, I would think that lines 19 through 26 should be inside of the line 11 client.available() if statement's compound statement. lines 19 and 23 should be checking the value of incomingByte, not trying to read a new character.

Basically, if connected: check if characters are available, and if so: read one in, print it out, and test for the control values.

Life_Learner

Hi ShapeShifter, your expertise has really aid me a lot on my project.
I've done as you have told, but it isn't working. Can I have a sample code to verify with my code :( ?

ShapeShifter

Is this a school project? It seems like it might be. If so, I don't want to do it for you.  ;)

Why not post what you have after your changes?

Life_Learner

Hi, here is changed code. Yes, it's a school project and it's about to be due soon.
 :smiley-confuse: I'm stuck and anxious. Thanks for helping.


Code: [Select]

void loop()
{
  client.connect(ip,port);  // Connects to a specified IP address and port
  if (client.connected())   // Returns true if the client is connected, false if not
  {
    if (!clientActive)
    Serial.println("New Client connection.");

    clientActive = true;

    if (client.available())
    { // Returns the number of bytes available for reading
     incomingByte == client.read(); // Read the next byte recieved from the server the client is connected to
     Serial.print("From client: \"");
     Serial.print((char)incomingByte);
     Serial.println("\"");
    if (incomingByte == 'H')
    {
      digitalWrite(13,HIGH);
    }
    if (incomingByte == 'L')
    {
    digitalWrite(13,LOW);
    }
    }
  }
  else
  {
    if (clientActive)
    {
      client.stop();       // Disconnected from the server
      Serial.println("Client disconnected.");
    }
    clientActive=false;
    client.connect(ip,port);
  }
}

jessemonroy650

@Life_Learner,
We been through this before with others. It seems you instructor has a fetish with this "Labview" program.

If you might suggest ***gently*** that one of the Arduino Yun Forum member finds this silly. And we request to knowing the goal of this project, so we may better assist all students.

I don't suggest you say this, but print this and get the response.

We DO want to help, but using a complex tool like "Labview" seems silly.

If you don't feel comfortable with this, just drop the this message. Do not respond. Best of Luck with your project.

TIA
Jesse

ShapeShifter

Hi, here is changed code.
The changes you made to the incoming data handling look correct, it's very much like I would've handled it.

But the first time around, I didn't notice the client.connect() call at the top of loop(). I don't think that should be there, as it would cause it to keep trying to open a new connection every time. I think that call should be moved from the beginning of loop() and be placed at the end of setup().

The idea is that when the sketch starts up, it tries to connect to the server using that call in setup(). Then, it enters the loop: on each pass it looks to see if the client is already connected, and if so, it looks for and processes data from it. However, if the client is not connected at that point (the connection couldn't be established or had been closed by the server) then the else clause at the bottom of loop() will try to establish the connection again. At the top of the next call to loop() it will once again be processed.

It should be that the client.connect() call is only made when there isn't an active connection. That will be when the application first starts up, and later when it is detected to be inactive. Otherwise, use the currently established connection.

What might be happening is that at the top of loop(), you are currently starting a new connection. The server may not have a chance to reply with an 'H' or 'L' by the time you get to the client.available() call, so there will be no data on that pass. On the next pass through loop(), there might be data waiting, but you are abandoning the active connection and trying to start a new one. Once that connection is established, there once again might not be data ready by the time you check for data. The cycle repeats forever.

Go Up