Arduino Forum

Using Arduino => Interfacing w/ Software on the Computer => Topic started by: mjnewsum on Jun 08, 2017, 11:28 pm

Title: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 08, 2017, 11:28 pm
Hello All,

I just started playing around with the Ethernet Shield W5100 for Arduino.
I found an example for receiving TCP IP information. I am using VVVV TCP Client for sending data.

Question 1:
I am not sure why or if this is needed, but it seems the example is setting a client = server.available().

Does this do anything or could server be used in the place of client everywhere in the example?
I'm just not sure if changing to an EthernetClient variable from an EthernetServer type has some benefit.


Question 2:
When I try to send data to the Arduino, it seems to take a long time to connect, and I am never sure when the connection has been made until the Serial.print starts showing.

Is there a way to know how long the connection should take or to verify that there is a connection before sending data that will be lost?


Question 3:
When I send a message ( example <255,000,100> ) I have the char array set to size 11 so it can get the RGB information. When this information prints, I randomly receive an extra character at the end of the message. I don't think this is coming from VVVV and I am not sure how the message can have 12 characters when the array is set to only hold 11.



Code: [Select]


#include <Ethernet.h>

byte mac[] = {0x54, 0x52, 0x49, 0x41, 0x44, 0x00};
byte ip[] = {192, 168, 2, 99};
byte gateway[] = {192, 168, 0, 1};
byte subnet[] = {255, 255, 0, 0};
EthernetServer server(4444);
EthernetClient client;

int sizeMessage = 11;

void setup() {
  Serial.begin(9600);
 
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  client = server.available();
}

void loop() {
  char inByte;
  char message[sizeMessage];
  int bytes;
 
  while(!client){
    client = server.available();
  }
 
  if(client.available()){
      inByte = client.read();
      if(inByte == '<'){
        bytes = client.readBytesUntil('>', message, sizeMessage);
        Serial.println(message);
        //Serial.print("Number of Bytes = ");
        //Serial.println(bytes);
      }
    }
   
  }




Thank you all in advance for the help!
Let me know if you need anymore information.

Kind regards,
Jake
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: ieee488 on Jun 08, 2017, 11:36 pm
You may want to read https://forum.arduino.cc/index.php?topic=351477.15 (https://forum.arduino.cc/index.php?topic=351477.15)

Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 12:21 am
@ieee488 I am reading through the forum link you sent, but it seems this is all about an issue with poorly made boards. Mine is able to connect, send and receive data.

I think I just need help understanding how to properly use the Stream class.

Do you think my issues may be caused by the physical condition of my shield?
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 12:28 am
My board does have the 511 resistor that was mentioned in the linked thread. I can add the 2x 100ohm resistors as suggested by k1ggis.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 01:01 am
@ieee488 - I added the 2 resistors as described, but I am still receiving an extra character at the end of my message when printing from my code in the original post.

I send the message <255,255,255> and it prints 255,255,255ΓΏ

I have it set to start recording the message when '<' is received and to stop when '>' is received.
The printed message is 12 characters long, so I am not sure how this is working.

TIA for all the help!
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 01:19 am
I re-uploaded the code and ran again.

This time when I send <255,255,255>, it prints 255,255,2555. It is an extra '5' at the end and I still can't figure out why.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 01:39 am
Seems the only way I can get the message to print correctly is by adding in a delay(); after printing. I don't understand how or why this would work... but it does. I hate these kinds of solutions, so I welcome any other suggestions. Although, it seems like I am just posting to myself here.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: ieee488 on Jun 09, 2017, 01:54 am
I haven't used my Ethernet shield in a while.
I was going to try it again, but I had no problems a few months ago.
I mostly tried the WebServer example.
And I did not make the modifications described in the link.
I was told I was just lucky. LOL.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: PaulS on Jun 09, 2017, 02:09 am
Code: [Select]
        bytes = client.readBytesUntil('>', message, sizeMessage);
        Serial.println(message);

message is NOT a string. Do not pass char arrays that are NOT strings to functions that expect strings.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 02:10 am
@ieee488 - Thank you for pointing me to the other forum link. It didn't change my problem, but it may have helped with other functionality I am not using.

I am not very familiar with how to use the Streaming Class properly.
It is working, but I just don't understand why flush() doesn't actually flush and data seems to be carried over from previous messages.

If I sent a message like ABCXYZ, then sent a message 1234, it would print 1234YZ...
I can even reset the arduino and send 1234 and it will still print the remaining characters from previous messages.

Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 02:26 am
message is NOT a string. Do not pass char arrays that are NOT strings to functions that expect strings.
Are you saying that my Serial.println() is the problem because message is not a string, or that I should be using a string variable in the readBytesUntil()?

TIA I am just beginning with bytes and char types.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: ieee488 on Jun 09, 2017, 02:40 am
Are you saying that my Serial.println() is the problem because message is not a string, or that I should be using a string variable in the readBytesUntil()?

TIA I am just beginning with bytes and char types.
You could try replacing that bit of code with
Code: [Select]

if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

That is used in the example sketch included in the IDE.

See what you get.

Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 02:44 am
@ieee48 - that would get the Serialprint to be correct, but I am trying to collect the whole message so I can use it for controlling some other functions in the arduino.

This example is basically to set and RGB LED from the ethernet TCP IP message. That's why I was trying to use the readByteUntil() so it would collect the message.

I was trying to set a loop to add each character to a message, but it seemed that was what readByteUntil() was made for.

Thank you for the suggestion.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: ieee488 on Jun 09, 2017, 03:51 am
@ieee48 - that would get the Serialprint to be correct, but I am trying to collect the whole message so I can use it for controlling some other functions in the arduino.

This example is basically to set and RGB LED from the ethernet TCP IP message. That's why I was trying to use the readByteUntil() so it would collect the message.

I was trying to set a loop to add each character to a message, but it seemed that was what readByteUntil() was made for.

Thank you for the suggestion.
Baby steps.

We're trying to figure out if you receiving correctly by printing to the Serial Monitor.

Your reading is not quite working, so this is to help you troubleshoot and see what you are receiving.

Title: Re: Arduino Ethernet - TCP IP Questions
Post by: PaulS on Jun 09, 2017, 05:56 am
If I hand you a stick, when you expect a stick, you can handle that, right?

If I hand you a rattlesnake when you expect a stick, that's a bit harder to handle, right?

If you NULL-terminate your array, making it a string, you can then hand it to functions that expect a string, and get the expected behavior. You are handing a rattlesnake to a function that expects a stick, and acting surprised when the function does something unexpected.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 07:43 pm
@PaulS & @ieee488 That makes a lot of sense.
I just wanted to make sure you knew that I am not just trying to print the characters.

I made the modification suggested.
This is how I started out initially.
It prints the correct message.

Code: [Select]



void setup() {
  Serial.begin(9600);
 
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  client = server.available();
}

void loop() {
  char inByte;
  char message[sizeMessage];
  int bytes;
 
  while(!client){
    client = server.available();
  }
 
  if(client.available()){
    char c = client.read();
    Serial.print(c);
    }
  }



The code that I posted previously was my attempt to collect the characters into a message that could be used later for things like analog output.

Thank you for the help.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 09, 2017, 09:38 pm
I am still trying to figure out how to make these incoming message into an int, but I can't find anything on the forum.

It seems like it is in here somewhere, but I only find reference to how this is done with Serial.read whereas I am using Ethernet Stream class.

Here is a post that seemed to relate in some ways:
https://forum.arduino.cc/index.php?topic=126138.0

And this tutorial makes sense (for Serial.read()):
https://www.gammon.com.au/serial

I just don't see any example using the Ethernet Shield.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: ieee488 on Jun 09, 2017, 09:46 pm
It would help if you post your entire sketch.
I have no idea what you have at this moment.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: PaulS on Jun 12, 2017, 10:53 am
You need to show us what is in "these incoming message". For all we know, the incoming message looks like:

"It is going to rain on Tuesday".

Now, what should the integer value of that message be?

That last bit of code is NOT collecting the data in an array. It is NOT NULL-terminating the array.

Until you do BOTH of those steps, AND the array actually contains a representation of an int, then passing anything to atoi() is a waste of effort.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 12, 2017, 07:19 pm
Here is the code as is when printing the received message one character at a time.
The message prints correctly.
Message sent is in this format:

<###,###,###>

example message:

<255,255,255>

I am adding the '<' and '>' to identify the start and end of messages.
This is not required and can be modified if needed.

Code: [Select]


#include <Ethernet.h>

byte mac[] = {0x54, 0x52, 0x49, 0x41, 0x44, 0x00};
byte ip[] = {192, 168, 2, 99};
byte gateway[] = {192, 168, 0, 1};
byte subnet[] = {255, 255, 0, 0};
EthernetServer server(4444);
EthernetClient client;

int sizeMessage = 11;


void setup() {
  Serial.begin(9600);
 
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  client = server.available();
}

void loop() {
  char inByte;
  char message[sizeMessage];
  int bytes;
 
  while(!client){
    client = server.available();
  }
 
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }
}





Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 12, 2017, 07:25 pm
@PaulS I am reading one of you other responses in this forum post:
http://forum.arduino.cc/index.php?topic=45629.0

I will try to apply these ideas and see if I can get it to work.

Title: Re: Arduino Ethernet - TCP IP Questions
Post by: PaulS on Jun 13, 2017, 03:14 pm
"255,255,255" is 11 characters. With a terminating NULL, you need space in the array for TWELVE characters, not 11.

Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 13, 2017, 09:50 pm
@PaulS the code below is from this link (http://forum.arduino.cc/index.php?topic=45629.0).

Code: [Select]

char inData[20]; // Allocate some space for the string
char inChar; // Where to store the character read
byte index = 0; // Index into array; where to store the character

void loop()
{
  while(Serial.available() > 0) // Don't read unless
                                                 // there you know there is data
  {
      if(index < 19) // One less than the size of the array
      {
          inChar = Serial.read(); // Read a character
          inData[index] = inChar; // Store it
          index++; // Increment where to write next
          inData[index] = '\0'; // Null terminate the string
      }
  }
  // Now do something with the string (but not using ==)
}


Would this produce the array size + 1 for the NULL terminating character?
It seems that you are NULL terminating the string for each character in the message.

I made the following modifications to work with Ethernet. I am getting the correct message printing.
Now, I just need to turn each comma separated value into an int.

Code: [Select]

#include <Ethernet.h>

byte mac[] = {0x54, 0x52, 0x49, 0x41, 0x44, 0x00};
byte ip[] = {192, 168, 2, 99};
byte gateway[] = {192, 168, 0, 1};
byte subnet[] = {255, 255, 0, 0};
EthernetServer server(4444);
EthernetClient client;

const int sizeMessage = 12;
char inData[sizeMessage];
char inChar;
byte index = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("Serial Started");
 
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  Serial.println("Server Started");
  client = server.available();
}

void loop() {
  char inByte;
  char message[sizeMessage];
  int bytes;

  while(!client){
    client = server.available();
    Serial.println("No connection");
  }
 
  while(client.available() > 0){
    if (index < sizeMessage -1){
      inChar = client.read();
      inData[index] = inChar;
      index++;
      inData[index] = '\0'; //Null terminate the string
    }else{
      Serial.println(inData);
      index = 0;
    }
  }
  Serial.println("no data");
}



Thanks again for the help!


Title: Re: Arduino Ethernet - TCP IP Questions
Post by: PaulS on Jun 13, 2017, 11:08 pm
Quote
It seems that you are NULL terminating the string for each character in the message.
The string is being kept NULL-terminated. In my mind, that is a far better practice than NULL terminating it after all the data is written to the array. This way, you never end up with a situation where there is NOT a NULL in the array.

Quote
I am getting the correct message printing.
Great.

Quote
Now, I just need to turn each comma separated value into an int.
strtok() and atoi(). I think I've mentioned them before. Maybe it wasn't to you, though.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 14, 2017, 03:09 am
@PaulS - thank you for the details. I am still getting used to the idea of Null Terminating the string.

In this post  (http://forum.arduino.cc/index.php?topic=288234.0) , the string was only Null Terminated after the collection of all chars. I wasn't sure if Null terminating each char would add to the string each time.

I think I will change my messages format so I don't collect information with comma space variables so I can convert the string to int without splitting the sting at each comma.

I still am a bit unsure why it takes so long to connect sometimes (original question 1). I am going to try to have the arduino send out a signal to let VVVV know when the connection has been made so I don't start sending before the arduino is ready.

I figured out that I do need the client = serial.available() for some functionality (original question 2) but I am not entirely sure what it is doing.

Thank you for all the help. I should be able to get things working from here.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: PaulS on Jun 14, 2017, 11:11 am
Quote
I wasn't sure if Null terminating each char would add to the string each time.
I'm not sure what you mean by "add to the string each time".

Suppose you have a bookshelf that can hold 100 books. But, the books fall over if you don't use a book end, when the shelf isn't full.

Now, you need to unwrap and put 10 books on the shelf. You can unwrap a book, and put it on the shelf, and let if fall over while you get the next book ready. When it is ready, you pick up the books that have fallen over, and put the new book at the end, and let it fall over...

Or, you can unwrap the first book, put it on the shelf, and put the book end in place. Then, you unwrap the next book, put it in place of the book end, and put the book end back at the end.

THAT is what is happening when you put a character in place of the NULL and put another NULL at the end.

Quote
I figured out that I do need the client = serial.available() for some functionality (original question 2) but I am not entirely sure what it is doing.
That line of code is not what you actually have. You have either
Code: [Select]
   byte numBytes = Serial.available();
or
Code: [Select]
   client = server.available();

In the first case, you are asking the Serial instance how much unread data there is. In the second case, you are asking the server if there are any clients that need attention.
Title: Re: Arduino Ethernet - TCP IP Questions
Post by: mjnewsum on Jun 14, 2017, 07:29 pm
@PaulS - Thank you for clarifying.

Quote
I'm not sure what you mean by "add to the string each time".
Earlier when you stated that the char array would need to be 12 (my message size +1) I thought the Null Termination added the +1 each time it was called. I see in the book end description that I am simply moving the null terminator to the end of the char array each time it is called.