Wifi Shield - UDP Sending Problem

Hi guys,

I've just purchased a new WiFi sheild from RS and coupled this to an R3 UNO. I have a problem when trying to transmit a simple UDP string. Basically everything works fine if the string is small but if I increase the string length to approx 90 characters it appears that nothing is sent. Any ideas why in the following code replyString is only sent if less than approx 90 characters?

I should point out of course that this code snippet is only the reply / sending code. The RX side of things appears to be fine, it's just when the Arduino tried to send the response that the problem occurs. If someone who has the WiFi shield (or even the Ethernet shield) could test this themselves that would be a big help.

String replyString = "123456789012345678901234567890123456789012345678901234567890";

char replyBuffer[replyString.length() + 1];
replyString.toCharArray(replyBuffer, sizeof(replyBuffer));

Udp.beginPacket(Udp.remoteIP(), localPort);
Udp.write(replyBuffer);
Udp.endPacket();

Thanks in advance!

I have also just tested by simply declaring the string as a char array (as below) but this shows the exact same problem.

char replyString [] = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";

The above string works (with 90 characters) but increasing the number of characters to 100 kills it. The Udp.write function returns the number of sent characters but nothing appears to actually be sent.

Could this be a bug in the WiFi shield / library?

I should point out of course that this code snippet is only the reply / sending code.

I should point out that this is only a snippet of an answer: because.

Post code.

Ok, well this isn’t my exact code but here’s the code that produces the same result…

#include <SPI.h>
#include <WiFi.h>
#include <WiFiUdp.h>

int status = WL_IDLE_STATUS;
char ssid[] = "MyNetworkID"; //  your network SSID (name)
char pass[] = "MyPass";    // your network password (use for WPA, or use as key for WEP)
int localPort = 17070;

// create UDP instance
WiFiUDP Udp;

void setup() {
// check for the presence of the WiFi shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    while(1);
  }
  
  // attempt to connect using WPA2 encryption:
  Serial.println("Attempting to connect to WPA network...");
  status = WiFi.begin(ssid, pass);

  // if you're not connected, stop here:
  if ( status != WL_CONNECTED) {
    Serial.println("Couldn't get a wifi connection");
    while(true);
  }
  // if you are connected, print out info about the connection:
  else {
    Serial.println("Connected to network ok.");
  }
 
  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (Udp.begin(localPort)) {
    Serial.println("Connected to UDP OK.");

    // UDP started ok so send a string of characters
    char testString [] = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
  
    IPAddress ip = IPAddress(192,168,1,240);
    Udp.beginPacket(ip, localPort);
    Udp.write(testString);
    Udp.endPacket();
  }else{
    Serial.println("Not connected to UDP!");
  }
}

void loop() {
   //do nothing
}

Have you looked at the source code for the WiFiUdp class? There is an internal buffer that beginPacket() initializes, write() writes to, and endPacket() sends. That buffer is not all that big, IIRC.

Well I've just taken a look at the two WifiUDP files in the lib folder and to be honest it doesn't really mean that much to me. Can''t see anything obvious that would limit the TX size. There is the "UDP_TX_PACKET_MAX_SIZE 24" but I can't see how that is affecting a string length of 90 - 100 characters.

Can someone else with a WiFi or Ethernet shield just quickly test this for me using the test code above?

onevision:
Can someone else with a WiFi or Ethernet shield just quickly test this for me using the test code above?

Does your code work if the size of your replyString is reduced?

Yes, 90 characters works fine. If I increase this to 100 it appears to not send any data at all.

I just need someone to repeat this on their setup really just to prove I'm not going mad or missing something really simple! :slight_smile:

Yes, 90 characters works fine. If I increase this to 100 it appears to not send any data at all.

I think in the recent past there has been similar discussion on an ~90 byte buffer size limit. You might look for similar previous post on the subject. Edit: the below might be of interest.

http://forum.arduino.cc/index.php?topic=166151.0

Thanks zoomkat! That certainly explains the 90 byte limit problem. A network interface that won't send data with a length greater than 90 bytes seems fundamentally flawed to me. I hope this issue is resolved in future firmware updates.

I guess for now I'll have to look at trimming down the string length, maybe sending two separate strings etc.

Just out of interest, are there any "better" alternatives to the official Arduino WiFi Shield?

Just out of interest, are there any "better" alternatives to the official Arduino WiFi Shield?

You might look at the data sheets for the wifly shield for a comparison.

onevision:
A network interface that won’t send data with a length greater than 90 bytes seems fundamentally flawed to me.

Yes and no. Packet size is always a compromise and somewhat arbitrary. The downside of large packets is having to buffer and process them (RAM and runtime). The downside of small packets is having to add another 45ish bytes of transport overhead before the packet hits the wire(less). For TCP packets, every packet sent out produces an ACKnowledgement packet sent back, further increasing the transport overheads of the original data.

90 bytes is fine for sending data from a couple sensors, every few seconds. It is fair to say, a 90 byte limit is not appropriate for working with flexible, text based protocols, such as HTTP.

I finally found some time yesterday to have a look at the WiFi shield buffer issue and it get’s worse!

Building a UDP packet data segment byte by byte, I only got 30 bytes of data before the send operation failed silently. A packet is (always) transmitted but contains only the first 30 bytes of data. The majority of the packet on the wire, is made up of transport header bytes.

// this is pseudo code which will not compile.
//  fill in the blanks yourself.

#define MIN_CHARS 16
#define MAX_CHARS 64

void sendPackets() {

  //send a series of packets with increasing data size
  
  uint8_t ch =0;

  for (uint8_t packetLength = MIN_CHARS; packetLength < MAX_CHARS; packetLength++) {
    
    Udp.beginPacket(targetIP, targetPort);
  
    //create data by writing byte by byte
    for (uint8_t i =0; i < packetLength; i++ {
      Udp.write('A' + ch++);
      if (ch > 25) ch =0; 
    }
    Udp.endPacket;
    
    delay(500);
  }
}

I hope this issue is resolved in future firmware updates.

So do I. Any network operation which fails silently is a flaw, in my oppinion.

Writing a 90 byte framer to cut up data is simple enough but it will (still) sap network resource. As it stands, I would say the WiFi shield is only really suitable for sending very small amounts of data, infrequently.

Thanks for your efforts MattS. My application is probably only going to be sending data a few times a day (if that) so hopefully this will still be suitable. I should be able to cut down the data length to less than 90 chars without too much trouble.

Let's hope the Arduino devs are listening and are planning a FW update soon! :slight_smile: