Go Down

Topic: UDP Multicast Sending from Arduino via Ethernet Shield (Read 3027 times) previous topic - next topic

shm267

Has anyone made any progress in enabling the Ethernet UDP libaray to send Multicast UDP packets?

There is an App Note on the Wiznet site on how to do this, and I tried to get it to work, but no luck.

Is there a guru of the Arduino Ethernet Stack out there that could help?

http://www.wiznet.co.kr/Sub_Modules/en/product/product_detail.asp?Refid=93&page=1&cate1=5&cate2=7&cate3=26&pid=1011&cType=2

See number 11.

pylon

Quote
There is an App Note on the Wiznet site on how to do this, and I tried to get it to work, but no luck.


Show us the code of that try and we may help you with that. The only tricky thing is the registration with the multicast group using an ICMP packet, the rest seems to be quite straightforward.

shm267

Huh, I see mention of the IGMP socket initialization, but not sure that is required for sending. It is odd, I can get Multicast receive to work fine, even though normally a device should have to subscribe to the multicast stream. This does not appear to be the case with the default ethernet library.

Here is the code section

Per the document, you need to init the DIPR, DHAR and DPORT prior to do the open, which is done in the call to socket. I also change the flag being passed on to the socket command to include the MULTI flag. Currently the result is no data transmitted and a hand on the endpacket call to actually transmit the packets.

Code: [Select]
/* Start EthernetUDP socket, listening at local port PORT */
uint8_t EthernetUDP::beginMulti(IPAddress ip, uint16_t port) {
  if (_sock != MAX_SOCK_NUM)
    return 0;

  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    uint8_t s = W5100.readSnSR(i);
    if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
      _sock = i;
      break;
    }
  }

  if (_sock == MAX_SOCK_NUM)
    return 0;
 
  byte mac[] = {  0x01, 0x00, 0x5E, 0x7F, 0x00, 0x01 };

  W5100.writeSnDIPR(_sock, rawIPAddress(ip));   //239.255.0.1
  W5100.writeSnDPORT(_sock, port);
  W5100.writeSnDHAR(_sock,mac);
 
  _destPort = port;
  _destIP   = ip;
  _remaining = 0;

  socket(_sock, SnMR::UDP|SnMR::MULTI, _destPort, 0);

  return 1;
}

pylon

Your call to socket() won't be successful because the initial "if" statement does not allow the MULTI option:

Code: [Select]
  if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE))


I guess you have the stuff of the socket call yourself.

shm267

#4
Feb 20, 2013, 09:09 pm Last Edit: Feb 20, 2013, 09:14 pm by shm267 Reason: 1
I was trying to avoid having to modify too much to get this going and as I am not that familiar with the Ethernet library, I was hoping for some guidance. The goal here is to enable E1.31 transmission from the Arduino Ethernet Shield. Also, there are 4 sockets, do I only set 1 socket for output, or how does that work with the existing library, since it looks like it always initializes all 4 sockets.

Should I try changing the socket call to:
socket(_sock, SnMR::UDP, _destPort, SnMR::MULTI);

So the MULTI flag is passed in the flag field, and not the protocol field?

shm267

Just did a quick test and it seems to be generating UDP Multicast Packets now!!!!! Would love to see you guys add this to the stock Ethernet Library!!!

pylon

You might be successful but for that you have to change your code to accept not only your IP but any multicast IP. This means you have to calculate the MAC address from the IP. Apart from this I think your code is a candidate for inclusion.

shm267

Ok,

Here is the code with the calculation of the MAC address based on the Multicast IP address.

Let me know if you see any issues. My only concern is that the original code cycled through all 4 sockets. I am only setting up socket 4. For my particular needs, I only need to send Multicast Packets, others might need to be able to do more with the remaining sockets. Just a thought.

Added to the End of the EthernetUdp.cpp file:

Code: [Select]
/* Start EthernetUDP socket, listening at local port PORT */
uint8_t EthernetUDP::beginMulti(IPAddress ip, uint16_t port) {
  if (_sock != MAX_SOCK_NUM)
    return 0;

  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    uint8_t s = W5100.readSnSR(i);
    if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
      _sock = i;
      break;
    }
  }

  if (_sock == MAX_SOCK_NUM)
    return 0;
 
 
  // Calculate MAC address from Multicast IP Address
  byte mac[] = {  0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 };
 
  mac[3] = ip[1] & 0x7F;
  mac[4] = ip[2];
  mac[5] = ip[3];

  W5100.writeSnDIPR(_sock, rawIPAddress(ip));   //239.255.0.1
  W5100.writeSnDPORT(_sock, port);
  W5100.writeSnDHAR(_sock,mac);
 
  _remaining = 0;

  socket(_sock, SnMR::UDP, port, SnMR::MULTI);

  return 1;
}


Line added to the EthernetUdp.h: After line 55.
Code: [Select]
 
virtual uint8_t beginMulti(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use


I will upload the Arduino Code once I get the E1.31 Packet stuff done.

Go Up