Arduino EthernetShield - UDP - Strange behaviour/problem

Hi

I'm using Arduino to measure temperatures in two kettles and control heating in those two kettles through heating elements connected to SSRs, just so you get the brackground of my question.
I'm using the EthernetShield of Arduino to send status messages about measured temperatures and SSR status to the global broadcast address on UDP port 8000:

//Broadcast status message
void bcStatus()
{
  char statusmsg[UDP_TX_PACKET_MAX_SIZE];
  memset(statusmsg, 0, UDP_TX_PACKET_MAX_SIZE);
  
  //If the temperatures show silly values, set them to 0
  //That could be because something is wrong, or usually
  //when the temperature sensor was not connected!
  if(temp1 > 102 || temp1 < 0)
    temp1 = 0.0;
    
  if(temp2 > 102 || temp2 < 0)
    temp2 = 0.0;
  
  //Arduino platform does not allow "%f" in sprintf function
  //so we need to get the values after comma in a different way :-)
  int ctemp1 = (temp1 - (int)temp1) * 100;
  int ctemp2 = (temp2 - (int)temp2) * 100;
  
  sprintf(statusmsg, "%d,%d,%d,%d,%d,%d,%d.%d,%d.%d,%d.%d", statBrew, (digitalRead(P1) == HIGH) ? 1 : 0,
                                                                      (digitalRead(P2) == HIGH) ? 1 : 0, (digitalRead(H1) == HIGH) ? 1 : 0,
                                                                      (digitalRead(H2) == HIGH) ? 1 : 0, (digitalRead(H3) == HIGH) ? 1 : 0,
                                                                      (int)temp1, ctemp1, (int)temp2, ctemp2, 1, 2);
  //If there are any rests configured, attach information about them to the status message
  //Information will be: <TotalRestTime>,<RestTemperature>,<TimeAlreadySpentOnRest>
  for(int i = 0; i < numRests; i++)
  {
    sprintf(statusmsg+strlen(statusmsg), ",%d,%d,%d", restTimes[i], restTemps[i], currentRestTime[i]);
  }

  sprintf(statusmsg+strlen(statusmsg), "\n");
  
  Udp.beginPacket(bcast, bcPort);
  Udp.write(statusmsg);
  Udp.endPacket();
}

Where bcast and bcPort are defined like:

//Broadcast address and port for status messages
IPAddress bcast(255,255,255,255);
unsigned int bcPort = 8000;

I used Wireshark to capture the behaviour of EthernetShield. I get normal messages for about 20 minutes, sometimes even longer, they look like this:
Summary in Wireshark:

2712	505.318299000	10.0.1.2	255.255.255.255	UDP	84	Source port: vcom-tunnel  Destination port: irdmi

As you can see there are 84 bytes in the packet.
Printable bytes in the packet (the actual string I send from Arduino is 1,1,1,1,1,0,27.16,24.12,1.2,5,30,0,5,40,0):

EF@A@2Q1,1,1,1,1,0,27.16,24.12,1.2,5,30,0,5,40,0

At some point however, Arduino begins to "merge" several packets into 1 packet,...! After sending about 40 of these merged packets, Arduino crashes and doesn't answer no more over the Ethernet module, nor over serial port.

Summary in Wireshark:

2736	507.621248000	10.0.1.2	255.255.255.255	UDP	1514	Source port: vcom-tunnel  Destination port: irdmi

As you can see there are 1514 bytes in the damn packet!
Printable bytes in the packet look now:

E@a
A@c,0,26.82,23.93,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.13,23.70,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.99,23.95,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.65,23.60,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.99,23.79,1.2,5,30,0,5,40,0
1,1,1,1,1,0,27.16,23.96,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.65,23.76,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.82,23.93,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.82,23.62,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.99,24.10,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.99,23.95,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.99,23.95,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.47,23.74,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.82,24.8,1.2,5,30,0,5,40,0
1,1,1,1,1,0,27.16,24.12,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.82,23.93,1.2,5,30,0,5,40,0
1,1,1,1,1,0,27.16,24.12,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.99,23.79,1.2,5,30,0,5,40,0
,1,0,25.96,23.38,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.47,23.89,1.2,5,30,0,5,40,0
1,1,1,1,1,0,25.96,23.22,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.30,23.72,1.2,5,30,0,5,40,0
1,1,1,1,1,0,25.61,23.19,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.30,23.72,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.13,23.55,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.99,23.95,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.30,23.41,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.13,23.86,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.13,24.2,1.2,5,30,0,5,40,0
1,1,1,1,1,0,25.78,23.51,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.13,23.55,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.30,23.57,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.13,23.70,1.2,5,30,0,5,40,0
1,1,1,1,1,0,27.16,23.65,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.30,23.57,1.2,5,30,0,5,40,0
1,1,1,1,1,0,26.65,23

As you can see,...several messages in one packet, but not even correct sometimes. I don't really get the problem here, but I somehow suspect that something with the EthernetShield is very wrong, or with the UDP implementation of it.

Anybody got an idea? I really would appreciate help :-/

Are you putting more than 24 bytes into that statusmsg array?

#define UDP_TX_PACKET_MAX_SIZE 24

You might want to use your own packet size. I use 48 instead of UDP_TX_PACKET_MAX_SIZE.

Hey there

I'm sorry I did not mention this, but I already defined the value to 256 :slight_smile: Which should still be safe regarding memory etc.
But still, that value does not explain the behavior mentioned, does it? :frowning:

By the way: When I defined the max packet value to 256,...how comes that Arduino starts sending packets of 1514 bytes? That's way too large,...:slight_smile:

If that is an Uno, are you certain you are not running out of SRAM?

Hi Tim

yes, it's an UNO...
How could I check if I run out of SRAM?

Here is what I use:

int freeRam() {
  extern int __heap_start,*__brkval;
  int v;
  return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);  
}

// call like this where you want to check available memory remaining.
  Serial.print(F("SRAM left: "));
  Serial.println(freeRam());

I would call this just before calling bcStatus(), and again just after the declaration of that array in bcStatus() function.

freeRAM will not show zero if you are out of memory. It will show either a negative number, or an unrealistic positive number.

BTW, I would change the value from 256 to 48. You don't need an array that large.

Hi Tim

Just implemented the code you sent me, will start testing soon. But for this test I will leave the value at 256.
One question thow:

  • Is this UDP_TX_PACKET_MAX_SIZE the maximum packet size I can receive,...or does it also affect the size of packets that can be sent?

Rafael

I'm not sure why they picked 24 bytes for that. I use 48 all the time, as does the UdpNtpClient example sketch.

I think the max size is a little more than 1400 bytes for any packet due to the socket buffer size in the w5100, but have not tested that.

Ok,...
I got 959 before bcStatus, 673 after allocating memory, 959 after bcStatus again.
So until now it looks really stable regarding memory. Been watching for ~10 minutes now.

Regarding UDP_TX_PACKET_MAX_SIZE:
Assuming I set it to 48:

  • Will I be able to receive packets that are 96 bytes in size?
  • Will I be able to send packets that are 96 bytes in size?

As I understood, that would not work anymore. But maybe that was wrong thinking? :slight_smile:

If you need 96 bytes, use 96 bytes. But 96 bytes is a long way from 256. Bear in mind the sprintf call will use as much sram as it needs also. That could deplete a bunch of sram.

Ok. Just to let you know: It crashed again,...with 256bytes for the buffer. I will reduce it for a next test.
But: I never got strange values regarding free memory:
Always got 959 before bcStatus, 673 after allocating memory, 959 after bcStatus.

Will let you know what happens next,...and maybe I will change sprintf call to memcpy,...works too but uses less ram as it seems,...:slight_smile:

I had to re-write some of the low level access routines to the Wiznet 5100 chip.

the maker of the chip has some errata datasheets and has suggested work arounds for timeouts, which the hardware of the 5100 series chip can get stuck on.

since I've implimented them, i've had network uptime of months. I send & receive data on UDP, and packets being sent vary from small ~20 odd byte talk home every few minutes, to large 800+ byte info packets.

I can however crash the chip ( well lose info, as the buffer ( 8k ram on receive side is normally split as 2k * 4 sockets ), if you don't take data from that buffer quick enough the packet header info can get overwritten ( in the cicular buffer it uses, and that means you start reading wrong lengths of the next packet being buffered. ie a complete mess up !!

I have with my changes, altered the 4 sockets to 4k, 2k and 2 * 1k. which is fine for how my program uses the sockets ( i use 3 sockets active at times )

Darryl

Mine does fine with the IDE v1.0.5 and v1.5.5 ethernet libraries. I've gone over a week at over 180,000 packets without a failure. I've sent packets at 10 per second without fail.

If it still crashes and...

  1. the allocated memory is showing you have enough SRAM,
  2. you do not use the String object data type (not character arrays, those are fine),
    then it may be possible you are overflowing an array somewhere. That would not show on the freeRAM report. Insure your sprintf() calls are not overflowing the statusmsg array.

Hi

just wanted to give some feedback as I finally worked out what the problem was:
Hardware I was using was defective!!!!!! -.-

I optimized the software so it was using 50% of memory at maximum! And still the damn thing kept crashing randomly. So I used my spare hardware (other Arduino UNO & EthernetShield) and ... no crashes no more!!

Well, nevertheless, I learned a lot regarding SRAM, so thanks for your comments anyway.
I will enjoy destroying the defective hardware in the meantime...:slight_smile: