Helpful ReplyUDP over WiFi questions (PIC32 with MRF24WB0MA or WG)

Post
davidhaile
Starting Member
2013/09/24 08:05:27
I'm a 28 year veteran embedded software engineer. The embedded web page demo works well and I'm able to customize it with live data off a CAN bus, but getting UDP to work on a PIC32 with an MRF24WB0MA is about to knock me down. I'd like to have one PIC32 module be an UDP server and another be the UDP client. All I'm after is a simple AdHoc connection between them. If someone has done this, PM me and I'll pay you for a working example if it includes both client and server.
 
A few assumptions/questions that I'd appreciate comments on:
  • Is there any reason why a particular node can't be a UDP Server or a Client? The way I read it, the only difference is the Server is waiting for someone to speak before responding. The client sets up the link before sending a command. Are there any other protocol setup differences?
  • Going through the steps of setting up a link (please comment on whether I understand this correctly): The server broadcasts an SSID on an IP address (169.254.1.1). The client opens a socket on that IP address then sends a command. The server responds to the command. The client closes the socket. Is it any more complicated than that?
  • On the client side, why does UDPOpenEx() always return a valid socket even if I intentionally mess up the IP address? The code that I copied from a Microchip Demo checks for MySocket == INVALID_UDP_SOCKET before failing. MySocket is always valid. I'll admit that I'm probably missing something. I use the PC and WireShark to verify that the server's SSID is up and available.
  • The final goal is a WiFi Direct implementation. I have an MRF24G demo board arriving tomorrow and will order another one so I have a pair. I'm a little worried that the WiFi Direct portion of the demo is not fully implemented. The demo sourcecode makes it look very simple.
The Demo projects are based on version 5.36.4. There were many MRF24 changes made with the 5.42 release, and now 6.00 is a Beta release. I'll stick with 5.36 unless there's a good argument to move to one of the others.
 
David Haile
Sheridan, WY
Chris A
Super Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/25 02:56:45
A few comments about UDP (having just used it for something):
A server would need to keep the socket open all the time.
The client can chose to open and close it or keep it open.
The same socket can be used to receive from mulitple clients "remoteNode" tells you what.
The same socket can also send to multiple clients by adjusting UDPSocketInfo[socket].
 
When you open the socket you are allocating it.  The IP does not matter at that point as its not doing anything.
 
Get the UDP working before playing with WiFI Direct!
davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/25 09:58:01
I agree with the UDP vs. WiFi Direct comment.
 
Two updates:
 1 - The MRF24G Demo stick arrived a few minutes ago. The demo is incomplete! Darn Microchip. If I go to the Configure page with the browser and try to configure it as WiFi Direct, a dialog box pops up that says "Feature Not Implemented". It does the same thing with SoftAP, though on the home page it says it is already using SoftAP. Not too worried about it at this point, but it is not an impressive demonstration when it has not been implemented. I bought it to see if I could watch a WiFi Direct negotiation using WireShark. I have serious doubts about Microchip's support of WiFi Direct.
 
2 - I'm presently having trouble with the linker hanging up on UDPOpenEX(). If I dummy the function, it links. That is not a long function. I was using TCPIP Stack v5.36 and am moving to 5.42 to see if the problem still exists.
MrE
Super Member
☄ Helpful
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/25 11:15:05
David,
 
You have two separate issues going on here:
1) You want a UDP link.  Fairly easy, see code below.
2) You want an Ad-Hoc or WiFi Direct Connection.  Microchip's "EasyConfig" demo [C:\microchip_solutions_v2013-06-15\TCPIP\WiFi EZConfig] supports Ad-Hoc, and from what I've read in various libraries, they are adding WiFi Direct support.  Since I don't have a WG module, I have not been able to test this.  It does seem to me that they take a long time to add support for new features.
 
Microchip has a good example of a UDP server (listener) implemented in Announce.c [C:\microchip_solutions_v2013-06-15\Microchip\TCPIP_Stack].  This library works with their discovery tool to find Microchip devices on a network.  Here is the UDP listener from this library:
/*********************************************************************
 * Function:        void DiscoveryTask(void)
 *
 * Summary:         Announce callback task.
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Recurring task used to listen for Discovery
 *                  messages on the specified ANNOUNCE_PORT.  These
 *                  messages can be sent using the Microchip Device
 *                  Discoverer tool. If one is received, this
 *                  function will transmit a reply.
 *
 * Note:            A UDP socket must be available before this
 *                    function is called.  It is freed at the end of
 *                    the function.  MAX_UDP_SOCKETS may need to be
 *                    increased if other modules use UDP sockets.
 ********************************************************************/
void DiscoveryTask(void)
{
    static enum {
        DISCOVERY_HOME = 0,
        DISCOVERY_LISTEN,
        DISCOVERY_REQUEST_RECEIVED,
        DISCOVERY_DISABLED
    } DiscoverySM = DISCOVERY_HOME;

    static UDP_SOCKET    MySocket;
    BYTE                 i;
   
    switch(DiscoverySM)
    {
        case DISCOVERY_HOME:
            // Open a UDP socket for inbound and outbound transmission
            // Since we expect to only receive broadcast packets and
            // only send unicast packets directly to the node we last
            // received from, the remote NodeInfo parameter can be anything
            //MySocket = UDPOpen(ANNOUNCE_PORT, NULL, ANNOUNCE_PORT);
            MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,ANNOUNCE_PORT, ANNOUNCE_PORT);

            if(MySocket == INVALID_UDP_SOCKET)
                return;
            else
                DiscoverySM++;
            break;

        case DISCOVERY_LISTEN:
            // Do nothing if no data is waiting
            if(!UDPIsGetReady(MySocket))
                return;
           
            // See if this is a discovery query or reply
            UDPGet(&i);
            UDPDiscard();
            if(i != 'D')
                return;

            // We received a discovery request, reply when we can
            DiscoverySM++;

            // Change the destination to the unicast address of the last received packet
            memcpy((void*)&UDPSocketInfo[MySocket].remote.remoteNode, (const void*)&remoteNode, sizeof(remoteNode));
           
            // No break needed.  If we get down here, we are now ready for the DISCOVERY_REQUEST_RECEIVED state

        case DISCOVERY_REQUEST_RECEIVED:
            if(!UDPIsPutReady(MySocket))
                return;

            // Begin sending our MAC address in human readable form.
            // The MAC address theoretically could be obtained from the
            // packet header when the computer receives our UDP packet,
            // however, in practice, the OS will abstract away the useful
            // information and it would be difficult to obtain.  It also
            // would be lost if this broadcast packet were forwarded by a
            // router to a different portion of the network (note that
            // broadcasts are normally not forwarded by routers).
            UDPPutArray((BYTE*)AppConfig.NetBIOSName, sizeof(AppConfig.NetBIOSName)-1);
            UDPPut('\r');
            UDPPut('\n');
       
            // Convert the MAC address bytes to hex (text) and then send it
            i = 0;
            while(1)
            {
                UDPPut(btohexa_high(AppConfig.MyMACAddr.v[i]));
                UDPPut(btohexa_low(AppConfig.MyMACAddr.v[i]));
                if(++i == 6u)
                    break;
                UDPPut('-');
            }
            UDPPut('\r');
            UDPPut('\n');

            // Send the packet
            UDPFlush();

            // Listen for other discovery requests
            DiscoverySM = DISCOVERY_LISTEN;
            break;

        case DISCOVERY_DISABLED:
            break;
    }   

}

davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/25 14:59:52
OK - I'm starting to get somewhere, maybe. It was more difficult than it should have been, but I found and rebuilt the MRF24WG demo application and am able to see some of what it is doing. STACK_USE_ANNOUNCE is defined which means DiscoveryTask() is called which is what you've copied here. DiscoveryTask() implies that it is a UDP server because it is waiting for incoming data and will respond with NetBIOSName and the MAC address when a 'D' is received from port 30303. That is easy enough to understand.
 
I'm confused about why AnnounceIP() is called from main() when the IP address changes. It just blasts out the NetBIOName and MAC Address over UDP. I should be able to catch the UDP blast with WireShark on power up. My next post will be after I've analyzed what it is doing. I can see that this shouldn't be as difficult as I've been making it.
MrE
Super Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/25 15:19:37
You have made excellent progress.  It took me a week to find a demo project and get it working on the Exp16 hardware, ha!  Of course, I was also learning a new compiler (X) and dealing with new hardware.
 
You are correct.  AnnounceIP() does broadcast the hostname, and MAC address of the device.  This, BTW, is an example of client side UDP.  It is actually unrelated to DiscoveryTask.  AnnounceIP() allows the discovery tool to automatically update the IP address (extracted from the received packet) that it shows without sending out another discovery packet.  The tool is found here: [C:\microchip_solutions_v2013-06-15\Microchip\TCPIP_Stack\Utilities\TCPIP Discoverer.jar]
 
Note: I may have renamed the folder "TCPIP Stack" to "TCPIP_Stack" to make the compiler quit warning me about spaces in pathnames.
 
P.S. Thanks for marking my last post as helpful.  It is nice to see that someone appreciates my hard work.
davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/26 10:27:09
More troubles. I'm attempting to change the IP address of the MRF24WB demo project! Can't do it! I've changed the MY_DEFAULT_IP_ADDRxxx values in TCPIPConfig.h, searched through the code and found a couple of hard-coded values, still no change in the IP address. I've figured it is part of the EasyConfig setup. Is that an app that I run? I've also used TCPIP Config tool which changes the same TCPIPConfig.h and WF_Config.h files that I change. I've also verified that my project is using the correct and changed *.h files.
 
Where is the IP address stored?
 
While waiting for responses, I'm going to switch to the MRF24WG project and see if I can successfully change its IP address. I need to get them both on the same subnet.
MrE
Super Member
☄ Helpful
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/26 11:42:24
The WiFi Connection state has been a real bear, and I'm still not sure I understand it 100%.  Basically, the MRF24Wb has 2 "profiles" that can be set, with only one active at any given time.  Given that they are stored in the module's RAM, there's not much point in setting the second one.  Anyways, if the WiFi is connected, then you must disconnect, then delete the profile, and set up a new one.  Here's a piece of my code:
 
                    AppConfig.dataValid = 0;                //Invalidate WiFi until we connect
                    ClrWiFiLinked;

                    //Start connection
                    //Delete old connection
                    WF_CMCheckConnectionState(&ConnectionState, &ConnectionProfileID);
                    if( (ConnectionState==WF_CSTATE_CONNECTION_IN_PROGRESS) ||
                        (ConnectionState==WF_CSTATE_RECONNECTION_IN_PROGRESS) )
                    {//Cannot disconnect while connection in process or it can hose the WiFi Module
                        UCWriteChr('2');                    //Connection in progress
                        break;
                    }
                    else
                    {
                        UCWriteChr('1');                    //Connecting
                    }
                    WF_CMDisconnect();                        //Disconnect
                    WF_CPDelete(ConnectionProfileID);        //Delete Profile

                    ClrSFWiFiConn;                            //Clear flag so we know when connection attempt finishes
                    //Start new connection
                    WF_Connect();
                    AppConfig.dataValid = 1;                //Validate wifi configuration since we connected

WF_Connect() is where the magic happens.  ClrSFWiFiConn is a flag specific to my project.  UCWriteChr() writes a byte to the comm port and is specific to my project.

Other modules where you may look frequently:
WFDebugStrings.c
WFEventHandler.c

Another gotcha: if the WiFi Driver library decides you've done anything wrong, or it thinks it can no longer communicate with the MRF24W, it will throw something called WF_ASSERT().  This macro calls a function that will print an error message to the UART (if enabled) and then lock up in a while loop.  This will cause your product to crash, or reboot if you have a WDT enabled.  Guess how I know???

If this post helps, please rate!
davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/26 12:40:23
I'm trying it right now. Having trouble figuring out a couple of Macros -
ClrSFWiFiConn, ClrWiFiLinked. I'll comment them out and see what happens.
davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/26 12:54:47
I keep having to bite a lot of bullets with this project and here's another one. I've been modifying the as-delivered Demo apps for both the MRF24WG and MRG24WB modules. Of course the G uses v5.42 stack and the B uses v5.36. You example is based on 5.42 so it is time to upgrade the B environment to use the more recent TCPIP code.
davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/26 16:16:32
<Incorrect assumptions deleted>
post edited by davidhaile - 2013/09/26 21:30:31
davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/26 17:01:04
The problem is related to SOFT_AP mode which is apparently fixed at 192.168.1.3. Now to get things running in AD_HOC mode. I'll stay offline for a bit.
davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/26 21:29:17
I got it! It seems so obvious once I found it and I did numerous "all files" searches so don't know how I missed it. MainDemo.c does not use the IP configuration in the header file. I fixed it. All is well. Will transition to UDP client and server tomorrow.
davidhaile
Starting Member
Re:UDP over WiFi questions (PIC32 with MRF24WB0MA or WG) 2013/09/27 10:33:05
It looks like restarting the link after power-up is a critical step.