Main Site Documentation

Wfly breakout board using SPI and FEZ Panda


#1

Hi, the Wifly driver code and the sample code on fezzer.com seem to use a UART->SPI bridge. I assume it’s on the shield. The shield was out of stock, so I purchased the breakout board from sparkfun.com.

http://www.sparkfun.com/products/10050

Anyone know where I can find sample code to talk SPI from FEZ Panda directly to the breakout board?

Thanks,
Greg


#2

Actually, you have done this the right way, so good job!

The shield has SPI<->UART bridge which makes everything overly complicated! On your board, it is just a UART interface.

Sparkfun did the SPI<->UART because Arduino only has 1 UART and it is used for deploying programs. FEZ has 3 or 4 UARTs :slight_smile:


#3

That’s great to hear! Is it easier to use the SPI or UART interface on the Wifly module? The current data sheet says to use the UART, and to contact Roving Networks if you want to use SPI, leaving me to wonder if it’s implemented.

At any rate, if someone has experience with this setup and can provide me a little sample code to get going that would be great! Since I don’t have the bridge, I can’t get any of the posted sample code to work.

TIA,
Greg


#4

There was a discussion in this forum re:WiFly.
Take a look to see if this help.

http://www.tinyclr.com/forum/2/1238/


#5

You are not using SPI…all will be just direct COM port, easy and efficient.


#6

Ok, I have wired the FEZ Panda UART, COM1, up to the Wifly Tx and Rx pins. I am successfully talking to the Wifly using the SerialPort class.

I can’t seem to get the Wifly into command mode. The manual at: http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um2.pdf says the if you send a “$$$” command, you will get a “CMD” back. That is not working. Almost all the time I get the same thing ("$$$") back, but sometimes it’s just random garbage.

Here is the code I wrote:


using System;
using Microsoft.SPOT;
using System.IO.Ports;
using System.Text;

namespace WiflyTest
{
    /// <summary>
    /// Class used to drive Wifly RN-131C Wifi module via the COM1 serial port on FEZ 
    /// Connect the FEZ "COM1 OUT" to Wifly "Rx" and Fez "COM1 IN" to Wifly "Tx".
    /// Notes (verbatim from manual at: http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um2.pdf:
    /// Connect a common ground when using the external TX, RX inputs.
    /// Factory default is hardware flow control disabled; CTS and RTS are not required
    /// </summary>
    public class Wifly
    {
        /// <summary>
        /// used to communicate over the serial port to Wifly
        /// </summary>
        private static SerialPort uart;

        /// <summary>
        /// Constructor
        /// </summary>
        public Wifly()
        {
            // Use our COM1 as the serial port at 9600 baud (factory default on Wifly)
            uart = new SerialPort("COM1", 9600);
            // Open a connection to the COM port
            uart.Open();
        }
        
        /// <summary>
        /// Try talking to the Wifly and ses what state it is in
        /// </summary>
        public void CheckStatus()
        {
            // From the manual at: http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um2.pdf
            // Upon power up, the device will be in data mode. To enter command mode, exactly the three characters $$$
            // must be sent. The device will respond with CMD.
            WriteCommand("$$$");
            string response = ReadResponse();
            Debug.Print(response);
            if (response != "CMD")
                throw new Exception("Accoring to the manual, CMD should be returned for a $$$, but it is not.");
        }

        /// <summary>
        /// Writes a command to the Wifly module
        /// </summary>
        /// <param name="data"></param>
        private void WriteCommand(string data)
        {
            byte[] tx_data = Encoding.UTF8.GetBytes(data);
            int bytesSent = uart.Write(tx_data, 0, tx_data.Length);
            if (bytesSent != tx_data.Length)
                throw new Exception("Problems transferring data to Wifly. Wifly didn't report same number of bytes sent.");
        }

        /// <summary>
        /// Reads data from the Wifly module
        /// </summary>
        /// <returns></returns>
        private string ReadResponse()
        {
            string response = string.Empty;
            int numBytesToRead = uart.BytesToRead;
            if (numBytesToRead > 0)
            {
                byte[] rx_data = new byte[numBytesToRead];
                uart.Read(rx_data, 0, rx_data.Length);
                char[] rawResponse = Encoding.UTF8.GetChars(rx_data);
                response = new string(rawResponse);
            }
            return response;
        }
    }
}



I create a new Wifly object and then call CheckStatus().

If anyone has experience with this, please let me know. Thanks!


#7

Would this help http://www.sparkfun.com/tutorials/158


#8

IMO SPI is way easier than UART…


#9

Both are easy but when you have a SPI<->UART bridge then things can be very confusing! You are writing SPI code but then you want to access the WiFly module in UART! I have worked on it and quickly realized how much waste of time and speed it would be so do all that, especially that you are doing this on NETMF, which supports UART natively.

The WiFly module is basically a serial-WiFi bridge so it makes complete sense to have it used on UART. Once you have configured the module, it is just a serial stream you have over wifi, not so much configurable but very easy to use.


#10

got it.


#11

It looks like you’re on the right track Greg. An echo back of the command sent seems likely, so you should try adding some polling to receive the echo and a delayed command response.


#12

From the factory, my board was auto joining, and THAT was the problem.

This is from the manual at: http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um2.pdf

Disabled the auto-join feature when in command mode. Auto-join causes WiFly to become
unresponsive to $$$ or commands during The period when auto-joining, when auto-joining is failing
do to non-existent AP, making it hard to process or interpret commands. Once command mode is
exited, auto join will re-enable.

I am getting commands to work now, and can even find my home network. I am not quite at the point of completing the configuration, but my goal is simply to be able to access the network and send HTTP. I will update as I get further.

Here is where I’m at with the Wifly class:


using System;
using Microsoft.SPOT;
using System.IO.Ports;
using System.Text;
using System.Threading;

namespace WiflyTest
{
    /// <summary>
    /// Class used to drive Wifly RN-131C Wifi module via the COM1 serial port on FEZ 
    /// Connect the FEZ "COM1 OUT" to Wifly "Rx" and Fez "COM1 IN" to Wifly "Tx".
    /// Notes (verbatim from manual at: http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um2.pdf:
    /// Connect a common ground when using the external TX, RX inputs.
    /// Factory default is hardware flow control disabled; CTS and RTS are not required
    /// </summary>
    public class Wifly
    {
        /// <summary>
        /// used to communicate over the serial port to Wifly
        /// </summary>
        private static SerialPort uart;

        /// <summary>
        /// Constructor
        /// </summary>
        public Wifly()
        {
            // Use our COM1 as the serial port at 9600 baud (factory default on Wifly)
            uart = new SerialPort("COM1", 9600);
            // Open a connection to the COM port
            uart.Open();
            uart.ErrorReceived += ErrorReceived;
            uart.DataReceived += DataReceived;
        }

        private void ListenToWifly()
        {
            while (true)
            {
                // As long as there is data to read, print it to the debug port
                if (uart.BytesToRead > 0)
                {
                    Debug.Print("\n" + DateTime.Now.ToString() + ": Response from Wifly: " + ReadResponse());
                }
                Thread.Sleep(100);
            }
        }

        private bool WaitForResponse(string expected)
        {
            string expectedWithCRLF = expected;
            expectedWithCRLF += "\r\n";
            int retry = 0;
            const int RETRY_COUNT = 10;
            while (retry < RETRY_COUNT)
            {
                // As long as there is data to read, print it to the debug port
                if (uart.BytesToRead > 0)
                {
                    string response = ReadResponse();
                    Debug.Print("\n" + DateTime.Now.ToString() + ": Response from Wifly: " + response);
                    // If we found the expected string somewhere in the response...
                    // Is this the right thing to do?
                    if ((response.IndexOf(expected) >= 0) || (response.IndexOf(expectedWithCRLF) >= 0))
                        break;
                }
                Thread.Sleep(100);
                retry++;
            }
            if (retry >= RETRY_COUNT)
            {
                return false;
                //throw new Exception("Did not get the expected response from Wifly...");
            }
            else
            {
                return true;
            }
        }

        private void ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {

        }

        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
        }
        
        /// <summary>
        /// Instructs Wifly to enter the command mode
        /// </summary>
        public void EnterCommandMode()
        {
            // From the manual at: http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um2.pdf
            // Upon power up, the device will be in data mode. To enter command mode, exactly the three characters $$$
            // must be sent. The device will respond with CMD.
            SendCommand("");            
            SendCommand("exit");
            Thread.Sleep(150);

            RepeatCommandAwaitResponse("$$$", "CMD");
        }

        public void ResetToManualJoin()
        {
            // Turn off WiFi auto-joining   
            RepeatCommandAwaitResponse("set wlan join 0", "AOK");
            RepeatCommandAwaitResponse("save", "Storing in config");
            // "reboot" to a known state

            RepeatCommandAwaitResponse("reboot", "*Reboot*");
            Thread.Sleep(2000);
            WaitForResponse("*READY*");
        }

        private void RepeatCommandAwaitResponse(string command, string expectedResponse)
        {
            // All commands except the $$$ need a carriage return
            if (command != "$$$")
                command += "\r";
            do
            {
                SendCommand(command);
                Thread.Sleep(100);
            }
            while (!WaitForResponse(expectedResponse));
        }

        /// <summary>
        /// Writes a command to the Wifly module
        /// </summary>
        /// <param name="data"></param>
        private void SendCommand(string data)
        {
            byte[] tx_data = Encoding.UTF8.GetBytes(data);

            int len = tx_data.Length;
            int offset = 0;
            int ret = 0;
            while (len > 0)
            {
                ret = uart.Write(tx_data, offset, len);
                len -= ret;
                offset += ret;
            }
        }

        private void SendCharacter(char c)
        {
            char[] c1 = new char[1];
            c1[0] = c;
            string s = new string(c1);
            byte[] tx_data = Encoding.UTF8.GetBytes(s);

            int bytesSent = uart.Write(tx_data, 0, tx_data.Length);
            Thread.Sleep(100);
            if (bytesSent != tx_data.Length)
                throw new Exception("Problems transferring data to Wifly. Wifly didn't report same number of bytes sent.");
        }

        /// <summary>
        /// Reads data from the Wifly module
        /// </summary>
        /// <returns></returns>
        private string ReadResponse()
        {
            string response = string.Empty;
            int numBytesToRead = uart.BytesToRead;
            if (numBytesToRead > 0)
            {
                byte[] rx_data = new byte[numBytesToRead];
                int offset = 0;
                int ret = 0;
                int len = rx_data.Length;
                while (len > 0)
                {
                    ret = uart.Read(rx_data, 0, rx_data.Length);
                    len -= ret;
                    offset += ret;
                }
                char[] rawResponse = Encoding.UTF8.GetChars(rx_data);
                response = new string(rawResponse);
            }
            return response;
        }

        public string[] GetEverything()
        {
            // We are expecting to be in command mode here
            SendCommand("get everything\r\n");
            Thread.Sleep(1200);

            string s = ReadResponse();

            return null;
        }

        public string[] DiscoverNetworks()
        {
            // We are expecting to be in command mode here
            SendCommand("scan\r");
            Thread.Sleep(3500);

            string s = ReadResponse();
            // Parse the response into networks
            string[] rawNetworks = s.Split('\r');
            string[] networks = new string[rawNetworks.Length - 6];
            for (int i = 0; i < networks.Length; i++)
            {
                networks[i] = rawNetworks[i + 5];
            }

            Debug.Print(s);
            

            return networks;
        }

        public bool JoinNetwork(string ssid)
        {
            SendCommand("join " + ssid + "\r");
            Thread.Sleep(100);
            string s = ReadResponse();
            if (s.IndexOf("Associated!") >= 0)
                return true;
            else
                return false;

        }
    }
}



#13

Nice! :clap:

Fezzer?


#14

Which firmware are you running on the GSX? I seem to recall that they may have fixed that auto-join issue.


#15

2.21


#16

BTW, I will update fezzer.com with a code sample when I get this class completed.


#17

I did not know too much about embedded solutions for Wifi when I started this a couple of weeks ago, but I’ve learned alot since then and want to share. I’m not sure I want to pursue using this module because it is not everything I thought it would be. Basically there are Wifi modules that have a serial to Wifi interface or are a native network interface. Near as I can tell, this has no native network interface and only supports one socket at a time.

Here is a link to a great article on factors you need to consider when putting Wifi into your embedded solution:

http://www.eetimes.com/design/embedded/4026972/Sorting-through-the-embedded-WiFi-confusion-item-1?pageNumber=0

I am now looking at the Microchip SPI based complete Wifi embedded solution, and the price is less than $30.

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2884

High res photos and block diagrams:

http://www.flickr.com/photos/microchiptechnology/sets/72157619304830592/

The only problem is that I can’t find the command set yet. They make programming easy from the PIC platform, but I want to use NETMF!!! ;D I guess I’m going to write my own.

Here is where I left off with the code for those interested (I don’t think I will pursue this any further):


using System;
using Microsoft.SPOT;
using System.IO.Ports;
using System.Text;
using System.Threading;

namespace WiflyTest
{
    /// <summary>
    /// Class used to drive Wifly RN-131C Wifi module via the COM1 serial port on FEZ 
    /// Connect the FEZ "COM1 OUT" to Wifly "Rx" and Fez "COM1 IN" to Wifly "Tx".
    /// Notes (verbatim from manual at: http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um2.pdf:
    /// Connect a common ground when using the external TX, RX inputs.
    /// Factory default is hardware flow control disabled; CTS and RTS are not required
    /// </summary>
    public class Wifly
    {
        /// <summary>
        /// used to communicate over the serial port to Wifly
        /// </summary>
        private static SerialPort uart;

        /// <summary>
        /// Constructor
        /// </summary>
        public Wifly()
        {
            // Use our COM1 as the serial port at 9600 baud (factory default on Wifly)
            uart = new SerialPort("COM1", 9600);
            // Open a connection to the COM port
            uart.Open();
            uart.ErrorReceived += ErrorReceived;
            uart.DataReceived += DataReceived;
        }

        private void ListenToWifly()
        {
            while (true)
            {
                // As long as there is data to read, print it to the debug port
                if (uart.BytesToRead > 0)
                {
                    Debug.Print("\n" + DateTime.Now.ToString() + ": Response from Wifly: " + ReadResponse());
                }
                Thread.Sleep(100);
            }
        }

        private bool WaitForResponse(string expected)
        {
            string expectedWithCRLF = expected;
            expectedWithCRLF += "\r\n";
            int retry = 0;
            const int RETRY_COUNT = 10;
            while (retry < RETRY_COUNT)
            {
                // As long as there is data to read, print it to the debug port
                if (uart.BytesToRead > 0)
                {
                    string response = ReadResponse();
                    Debug.Print("\n" + DateTime.Now.ToString() + ": Response from Wifly: " + response);
                    // If we found the expected string somewhere in the response...
                    // Is this the right thing to do?
                    if ((response.IndexOf(expected) >= 0) || (response.IndexOf(expectedWithCRLF) >= 0))
                        break;
                }
                Thread.Sleep(100);
                retry++;
            }
            if (retry >= RETRY_COUNT)
            {
                return false;
                //throw new Exception("Did not get the expected response from Wifly...");
            }
            else
            {
                return true;
            }
        }

        private void ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {

        }

        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
        }
        
        /// <summary>
        /// Instructs Wifly to enter the command mode
        /// </summary>
        public void EnterCommandMode()
        {
            // From the manual at: http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um2.pdf
            // Upon power up, the device will be in data mode. To enter command mode, exactly the three characters $$$
            // must be sent. The device will respond with CMD.
            SendCommand("");            
            SendCommand("exit");
            Thread.Sleep(150);

            RepeatCommandAwaitResponse("$$$", "CMD");
        }

        public void ResetToManualJoin()
        {
            // Turn off WiFi auto-joining   
            RepeatCommandAwaitResponse("set wlan join 0", "AOK");
            RepeatCommandAwaitResponse("save", "Storing in config");
            // "reboot" to a known state

            RepeatCommandAwaitResponse("reboot", "*Reboot*");
            Thread.Sleep(2000);
            WaitForResponse("*READY*");
        }

        private void RepeatCommandAwaitResponse(string command, string expectedResponse)
        {
            do
            {
                SendCommand(command);
                Thread.Sleep(100);
            }
            while (!WaitForResponse(expectedResponse));
        }

        /// <summary>
        /// Writes a command to the Wifly module
        /// </summary>
        /// <param name="data"></param>
        private void SendCommand(string data)
        {
            // All commands except the $$$ need a carriage return
            if (data != "$$$")
                data += "\r";
            byte[] tx_data = Encoding.UTF8.GetBytes(data);

            int len = tx_data.Length;
            int offset = 0;
            int ret = 0;
            while (len > 0)
            {
                ret = uart.Write(tx_data, offset, len);
                len -= ret;
                offset += ret;
            }
        }

        private void SendCharacter(char c)
        {
            char[] c1 = new char[1];
            c1[0] = c;
            string s = new string(c1);
            byte[] tx_data = Encoding.UTF8.GetBytes(s);

            int bytesSent = uart.Write(tx_data, 0, tx_data.Length);
            Thread.Sleep(100);
            if (bytesSent != tx_data.Length)
                throw new Exception("Problems transferring data to Wifly. Wifly didn't report same number of bytes sent.");
        }

        /// <summary>
        /// Reads data from the Wifly module
        /// </summary>
        /// <returns></returns>
        private string ReadResponse()
        {
            string response = string.Empty;
            int numBytesToRead = uart.BytesToRead;
            if (numBytesToRead > 0)
            {
                byte[] rx_data = new byte[numBytesToRead];
                int offset = 0;
                int ret = 0;
                int len = rx_data.Length;
                while (len > 0)
                {
                    ret = uart.Read(rx_data, 0, rx_data.Length);
                    len -= ret;
                    offset += ret;
                }
                char[] rawResponse = Encoding.UTF8.GetChars(rx_data);
                response = new string(rawResponse);
            }
            return response;
        }

        public string[] GetEverything()
        {
            // We are expecting to be in command mode here
            SendCommand("get everything\r\n");
            Thread.Sleep(1200);

            string s = ReadResponse();

            return null;
        }

        public string[] DiscoverNetworks()
        {
            // We are expecting to be in command mode here
            SendCommand("scan\r");
            Thread.Sleep(3500);

            string s = ReadResponse();
            // Parse the response into networks
            string[] rawNetworks = s.Split('\r');
            string[] networks = new string[rawNetworks.Length - 6];
            for (int i = 0; i < networks.Length; i++)
            {
                networks[i] = rawNetworks[i + 5];
            }

            Debug.Print(s);
            

            return networks;
        }

        public bool JoinNetwork(string ssid)
        {
            SendCommand("join " + ssid + "\r");
            Thread.Sleep(100);
            string s = ReadResponse();
            if (s.IndexOf("Associated!") >= 0)
                return true;
            else
                return false;

        }

        public string WebRequest(string url)
        {
            SendCommand("open " + url + " 80");
            Thread.Sleep(100);
            Debug.Print(ReadResponse());
            return null;
        }

    }
}



#18

try using


#19

For complete and native networking support, see GHI’s support on FEZ Cobra (EMX)

WiFly, like you found out, is a simple serial bridge over wifi. It is very limited but it is good enough for small applications.