Saturday, April 2, 2016

YellowJacket Arduino with WiShield Wifi (Part 16)

TCP vs UDP — 
Previous examples in this series have used TCP to transmit data between YellowJacket Arduino’s and Macs over wifi using the WiShield software. In this post, UDP will be examined and a simple example will be developed using the WiShield software to determine how the software library works using UDP.
Ref:http://electronics.stackexchange.com/questions/30474/udp-vs-tcp-protocols
Quoting Ref: “TCP and UDP are protocols on top of the IP layer. TCP and UDP differ in the strategies they use to get data to the application.
TCP is a connection-oriented protocol. When the two sides connect, they exchange a sequence number and start counting bytes sent back and forth. All bytes sent back and forth are counted within the sequence number. So one side can say “I believe I sent you bytes 20-40 in that last packet, can you confirm that you received those bytes in that packet?” This allows each side to know if data wasn’t received or was received out of order, and parts of the protocol specify how each side rectifies the situation (ie, with re-requests for certain packets). There are timeouts as well that determine whether the connection has become interrupted. If a connection is lost like this, a new session has to be re-negotiated and the sequential count starts over (but not necessarily from byte 0 – a certain amount of randomness is required to prevent some attacks). Practically this means that a connection like this can’t just be picked up again once it becomes interrupted – you have to re-establish the connection. There are also flow-control features that ensure data isn’t sent too fast for one side to process. TCP is very useful where the data absolutely must get through despite delays.
UDP is different. There is no connection, no sequential numbers, no timeouts. Packets are sent between the two sides with no other necessary information. Since there is no connection the packets can be sent at any time. There’s also no guarantee that data gets through. If you send a packet, it may not get there and you’d never know. Typically, the data is sent with checksums, sequence numbers and such into the data you send if it’s necessary for a more secure link. Because of the lack of timeouts and retries it’s much faster than TCP. Typically UDP is used for situations where speed is more important that getting all of the data.
When data is sent via UDP, one of two things will happen: either a packet will reach its destination within a moderately-short time, or it won’t. The sender will be notified that the packet was started on its journey, whether or not it actually reached its destination. If the packet is not delivered successfully, the receiver will never know of its existence. It’s important to note that while UDP will generally deliver packets in reasonably-timely fashion, there is no guarantee that packets will reach their destination in the order they were sent. Most of the time they will, but some networking equipment may arbitrarily divide up the packets going through them among several different links, some of which might be slightly faster than others.
TCP, unlike UDP, establishes a connection between two parties and attempts to ensure that all information supplied by each side is received by the other, in the order that it was transmitted; it guarantees that either every byte will be delivered in sequence, or the connection will be declared invalid. The simplest way to think of TCP is as having nodes send messages of the following format:
I have received information up to but not including your byte #1253, …
… and my data, starting at byte #4381, is “QUACK”.
Each node sends a message of the above format when either it has data that the other node has not acknowledged, or when it has received data that it has not yet acknowledged. One very nice thing about TCP is that it doesn’t matter too much if an acknowledgment gets lost. If data is received successfully but the transmitter doesn’t know about it, the transmitter will include redundant data the next time it decides to transmit, but the receiver will simply ignore that redundant data and acknowledge all the useful data it received.
A few things to note about TCP:
  1. A device which transmits information will expect an acknowledge, and will attempt retransmission if it doesn’t get one. If it persistently fails to get an acknowledge, it will decide the connection is dead, but the other party to the connection may never know about it.
  2. TCP generally only sends packets when at least one party to the communication has “something to say”. If neither node has anything to say, a TCP connection could sit idle for hours or days without any data flowing through.
  3. Some TCP implementations will, if no data flows for an extended period of type (often somewhere between a minute and an hour), resend their last byte of data in what’s called a “keepalive” packet, “pretending” that they didn’t receive an acknowledgement for it. In the normal chain of events, the receiver will know that it already received that byte, and thus discard it, but they will also know that the transmitter is probably expecting an acknowledgment for it. If the transmitter that sent the “keepalive” doesn’t get a response, it will know the other party to the connection has gone missing.
  4. A device which transmits via TCP will know that all of its data has been successfully delivered. A device which is receiving TCP will not know when it has received all data that has been sent to date, unless it receives a packet with a “FIN” flag, indicating that there will be no further data.”
Ref: http://stackoverflow.com/questions/12251551/send-arduino-data-via-a-wi-fi-shield-to-a-specific-ip-address-on-the-lan — This Ref responds to a user wanting to create a UDP app for the Copperhead WiShield Wi-Fi Server.
Ref: https://www.arduino.cc/en/Tutorial/UDPSendReceiveString, and http://duino4projects.com/sending-and-receiving-string-via-udp-using-arduino/ — These Refs by Michael Margolis use the Arduino and Ethernet boards to communicate with a Processing sketch running on a PC/Mac.
Getting UDP Working in WiShield
The following code has been adapted to use the YellowJacket Wifi to communicate with the UDPSendReceiveString Processing sketch (above Ref) running on a Mac. This example uses UDP to send text strings back and forth between the two processors, but was most useful for determining how to get UDP working with the WiShield software. The first step taken was to get a UDP signal sent from the Processing app on the Mac, through wifi, to the YellowJacket Arduino running the WiShield software. The use of the Wireshark app running on the Mac and finding the UDP messages that were being sent to the YJ Arduino at ip 10.0.1.57 was critical to getting things working. The vanilla WiShield software does not have any Serial Monitor debugging to allow tracking of UDP signals. After a lot of tracing and debugging, the proper port assignments turned out to be essential (as would be expected) but there was no obvious documentation of where those port assignments should be made. It turns out to be fairly straight forward once you know where to look and make changes.
In the Processing sketch, the WiShield client ip address is set to 10.0.1.57 with the client UDP port 1026. The Mac server wifi ip address assigned by the local network was 10.0.1.11, and the sketch assigned server UDP port 6000.
When the Processing app runs, a small Java terminal window opens, which will send out “Hello” to ip 10.0.1.57, port 1026, each time there is a keystroke in the terminal window. With the YJ57 not on, Wireshark sensed a signal to “Broadcast” and info = “Who has 10.0.1.57? Tell 10.0.1.11″, so the Processing signal was trying to be sent.
The next task was to get UDP working in a sketch on the YellowJacket. The vanilla UDPApp example code was edited to use the local network wifi settings as in previous examples, and setup() included ” WiFi.init();” and loop() contained ” WiFi.run();”. In apps.conf.h, “#define APP_UDPAPP” must be uncommented, and in uip-conf.h, “#define UIP_CONF_UDP 1” must be 1 rather than 0 (TCP) to allow UDP to run in WiShield. Running that sketch on the YellowJacket, and the Processing app on the Mac, showed “Source: 10.0.1.11; Destination: 10.0.1.57; Protocol: UDP; Info: 6000 –> 1026 Len=5” in Wireshark, which indicated that UDP was communicating over wifi since 10.0.1.57 was connected to the local network through wifi, and the Processing app was sending out the “Hello” packets to 10.0.1.57. However, 10.0.1.57 was not responding back to the Processing app, since the YJ57 ports had not been assigned.
The UDPApp.ino sketch has the udpapp.c in a separate tab. The udpapp_init module in udpapp.c must be modified to assign the correct ip and ports:
        // originalcode:
 uip_ipaddr(&addr, 192,168,1,100);
 c = uip_udp_new(&addr, HTONS(0));
 if(c != NULL) {
  uip_udp_bind(c, HTONS(12344));

        // modified code:
 uip_ipaddr(&addr, 10,0,1,11); // (server ip)
 c = uip_udp_new(&addr, HTONS(6000)); // (server port)
 if(c != NULL) {
  uip_udp_bind(c, HTONS(1026)); // (YJ57 client port)
With the modified UDPApp.ino running, Wireshark displayed the data flowing back and forth between the two devices using wifi. The Arduino Serial Monitor window showed no indication of UDP communication. Fixing that became the next task.
No. Time        Source      Destination  Protocol Length Info                 Data
15  7.912052    10.0.1.11   10.0.1.57    UDP      47     6000 → 1026  Len=5   Hello
16  7.918114    10.0.1.57   10.0.1.11    UDP      68     1026 → 6000  Len=26  Hello. What is your name?
17  7.919292    10.0.1.11   10.0.1.57    UDP      45     6000 → 1026  Len=3   Mac
18  7.925933    10.0.1.57   10.0.1.11    UDP      58     1026 → 6000  Len=16  Hello Mac
19  7.926600    10.0.1.11   10.0.1.57    UDP      45     6000 → 1026  Len=3   Mac
32  19.069058   10.0.1.11   10.0.1.57    UDP      47     6000 → 1026  Len=5   Hello

Processing Sketch on Mac
The processing sketch can be loaded and compiled in the Processing app (Ref: https://processing.org/tutorials/). The UDPSendReceive_P3.pde code is below. The “import hypermedia.net.*;” is required and was found for download at Ref: https://forum.processing.org/two/discussion/9802/looking-for-udp-library-hypermedia-library-dead, and http://ubaa.net/shared/processing/udp/udp.zip.
/*
 * UDPSendReceive_P3
 * Processing sketch to run with this example
 * =====================================================
 * 
 * // Processing UDP example to send and receive string data from Arduino
 * // press any key to send the "Hello Arduino" message
 * 
 * Processing sketch output:
 * send=> Hello
 * Hello. What is your name?
 * send=> Mac
 * Hello, Mac
 * 
 * 
 * Arduino sketch output:
 * === Initializing WiShield as UDP Client on Serial Monitor ===
 * 
 * Server port:6000; Server ip:10,0,1,11
 * Client port:1026; Client ip:10,0,1,57
 * 
 * WiFi Init OK; Start UDP Listening...
 * 
 * Server port:6000; Server ip:10,0,1,11
 * Client port:1026; Client ip:10,0,1,57
 * 
 * Incoming Message Length: 5; Message: Hello (from Processing app)
 * Outgoing Request Message Length: 26; Message: Hello. What is your name?
 * Incoming Message Length: 3; Message: Mac (from Processing app not displayed)
 * Outgoing Response Message Length: 12; Message: Hello, Mac
 * 
 */

import hypermedia.net.*;

UDP udp;  // define the UDP object
  String ip       = "10.0.1.57"; // the remote IP address
  int port        = 1026;    // the destination port


void setup() {
  udp = new UDP( this, 6000 );  // create a new datagram connection on port 6000
  // udp.log( true );           // <-- printout the connection activity
  udp.listen( true );           // and wait for incoming message
}

void draw()
{
}

void keyPressed() {
  
  //String ip       = "10.0.1.57"; // the WiShield remote IP address
  //int port        = 1026;    // the WiShield destination port
  //Wireshark Mac port 6000 to port 1026 on YJ57 10.0.1.57
  //6613  3.784864  10.0.1.11  10.0.1.57  UDP  47  6000 → 1026  Len=5

  udp.send("Hello", ip, port );   // the message to send
  //for (int i=0; i<5; i++) {
  //    udp.send("Hello", ip, port );   // the message to send
  //   for (int j=0; j<10; j++) print (".");
  //}
}

void receive( byte[] data ) {      // <-- default handler
  //void receive( byte[] data, String ip, int port ) { // <-- extended handler

  for (int i=0; i < data.length; i++)
    print(char(data[i]));
  println();
  
  // reply with name
  // send here sends the name but that kills the communication
    udp.send("Mac", ip, port );   // the message to send

}

/* ============================= */

Wireshark showed that the sketches could communicate using wifi, so that part worked as desired. The YellowJacket Wifi sketch and WiShield Library required fairly extensive modifications to display the data being transferred back and forth on the Arduino Serial Monitor. Edits were required in config.h (renamed config_udp.h to indicate that edits had been made in that file), and udpapp.c.
After a click and <cr> on the Processing app window, the Serial Monitor displayed:
=== Initializing WiShield as UDP Client on Serial Monitor ===

Server port:6000; Server ip:10,0,1,11
Client port:1026; Client ip:10,0,1,57

WiFi Init OK; Start UDP Listening...

Server port:6000; Server ip:10,0,1,11
Client port:1026; Client ip:10,0,1,57
Incoming Message Length: 5; Message: Hello (from Processing app)
Outgoing Request Message Length: 26; Message: Hello. What is your name?
    [ not displayed Incoming Message Length: 3; Message: Mac (from Processing app) ]
Outgoing Response Message Length: 10; Message: Hello, Mac

Quite a bit of time was invested in getting UDP working, primarily due to the lack of documentation for implementing UDP on WiShield. UDP will be revisited at a later date, to make it more useful for sending and receiving data.

(Apr 2, 2016)

No comments:

Post a Comment