WiFlyHQ: A new library for the WiFly RN-XV

After working on a few WiFly projects with the WiFly RN-XV, and not having much success using and extending the libraries that are available, I decided to write my own. I think its fairly easy to understand and extend as needed. Version 0.1 is available here: GitHub - harlequin-tech/WiFlyHQ: WiFly RN-XV Arduino Library.

I'll continue to add additional features with the goal of providing full access to all of the WiFly module's capabilities, starting with adhoc network support.

Example code to setup and use the hardware serial interface:

	Serial.begin(9600);
	wifly.begin(&Serial);

Example code to setup and use a software serial interface:

	#include <SoftwareSerial.h>
	SoftwareSerial wifiSerial(8,9);

	wifiSerial.begin(9600);
	wifly.begin(&wifiSerial);

Example code to join a WiFi network:

	wifly.setSSID("mySSID");
	wifly.setPassphrase("myWPApassword");
	wifly.enableDHCP();
	wifly.join();

Example code to send a UDP packet:

	wifly.setIpProtocol(WIFLY_PROTOCOL_UDP);
	wifly.sendto("Hello, world", "192.168.1.100", 2042);

Example code to open a TCP connection and send some data, and close the connection:

	wifly.open("192.168.1.100",8042);
	wifly.println("Hello, world!");
	wifly.close();

Exmaple code to receive UDP or TCP data (assumes software serial interface):

	if (wifly.available() > 0) {
	    Serial.write(wifly.read());
	}

Thank you! Even though I get errors trying to pull down an XML page with weather data on it (I need to debug that a little more to find out EXACTLY what's going on with the request, may require more RN-XV settings configuration), it works great for pinging servers, routers, and the like for my ping logger and will enable me to move off my Arduino Ethernet and onto one of my FIOs and shrink the hardware device footprint.

Thanks again, and once I find out what the issue is with pulling down that XML data from an RSS feed I'll let you know.

Great. If you run into any bugs, or are missing key functions, you could open an issue on the github page and I'll work on a fix.

dhunt:
Great. If you run into any bugs, or are missing key functions, you could open an issue on the github page and I'll work on a fix.

Just posted the issue I'm seeing to Github.

EDIT: And I resolved it and closed that issue-not-really-an-issue.

This library is by far the easiest to use out of all the ones I've been using so far. WiFlyHQ has allowed me to combine a ping logger and internet weather display easily and with a lower amount of flash and RAM - less than 18k to ping 3 devices every 30 seconds and pull down internet weather every 2 minutes.
It's also more stable in that it doesn't just "lock up" like WiFlySerial.h and WiFly.h would do after pulling down weather about 7 times. It just keeps going and going...

Awesome, good to hear.

I've aimed for a small RAM footprint, and once the library is feature-complete I'll look at ways to reduce the flash size.

dhunt:
Awesome, good to hear.

I've aimed for a small RAM footprint, and once the library is feature-complete I'll look at ways to reduce the flash size.

Doesn't seem to want to work on a Mega 2560. Put issue on the github with more details.

RESOLVED: Cannot use SoftwareSerial.h on Mega 2560 with this. Duh. Replacing "wiflyserial" with a Mega serial pair you've wired the Xbee RN-XV breakout to works just fine.

I look forward to using it next month! Hopefully it will be well tested by many users by then... :slight_smile:

Is it working reliably? How many testers/users so far?

Will you be adding FTP functions soon?

sbright33:
Is it working reliably? How many testers/users so far?

Seems to be quite stable, three or four people have been using it. I have no problems with stability for UDP packets.

I don't think there are any issues preventing you from trying it out. Let me know how it goes.

sbright33:
Will you be adding FTP functions soon?

That should be quite easy to add. Feel like giving it a go and contributing it to the library? I'm planning to add support for adhoc networks next.

I've release version 0.3 of the library GitHub - harlequin-tech/WiFlyHQ: WiFly RN-XV Arduino Library.

This adds support for creating Ad Hoc wifi networks:

#include <WiFlyHQ.h>
#include <SoftwareSerial.h>
SoftwareSerial wifiSerial(8,9);

WiFly wifly;

void setup()
{
    Serial.begin(115200);
    Serial.println(F("Starting"));
    wifiSerial.begin(9600);
    wifly.begin(&wifiSerial, &Serial));

    wifly.createAdhocNetwork("wifly", 10);

    Serial.println(F("Network ready"));
}

void loop()
{
    wifly.terminal();
}

Version 0.2 added a Web Server example sketch with chunked encoding support:

/*
 * WiFlyHQ Example httpserver.ino
 *
 * This sketch implements a simple Web server that waits for requests
 * and serves up a small form asking for a username, then when the
 * client posts that form the server sends a greeting page with the
 * user's name and an analog reading.
 *
 * This sketch is released to the public domain.
 *
 */

 /* Notes:
  * Uses chunked message bodies to work around a problem where
  * the WiFly will not handle the close() of a client initiated
  * TCP connection. It fails to send the FIN to the client.
  * (WiFly RN-XV Firmware version 2.32).
  */

/* Work around a bug with PROGMEM and PSTR where the compiler always
 * generates warnings.
 */
#undef PROGMEM 
#define PROGMEM __attribute__(( section(".progmem.data") )) 
#undef PSTR 
#define PSTR(s) (__extension__({static prog_char __c[] PROGMEM = (s); &__c[0];})) 

#include <WiFlyHQ.h>

#include <SoftwareSerial.h>
SoftwareSerial wifiSerial(8,9);

//#include <AltSoftSerial.h>
//AltSoftSerial wifiSerial(8,9);

WiFly wifly;

/* Change these to match your WiFi network */
const char mySSID[] = "myssid";
const char myPassword[] = "my-wpa-password";

void sendIndex();
void sendGreeting(char *name);
void send404();

char buf[80];

void setup()
{
    Serial.begin(115200);
    Serial.println(F("Starting"));
    Serial.print(F("Free memory: "));
    Serial.println(wifly.getFreeMemory(),DEC);

    wifiSerial.begin(19200);
    if (!wifly.begin(&wifiSerial, &Serial)) {
        Serial.println(F("Failed to start wifly"));
	wifly.terminal();
    }

    /* Join wifi network if not already associated */
    if (!wifly.isAssociated()) {
	/* Setup the WiFly to connect to a wifi network */
	Serial.println(F("Joining network"));
	wifly.setSSID(mySSID);
	wifly.setPassphrase(myPassword);
	wifly.enableDHCP();
	wifly.save();

	if (wifly.join()) {
	    Serial.println(F("Joined wifi network"));
	} else {
	    Serial.println(F("Failed to join wifi network"));
	    wifly.terminal();
	}
    } else {
        Serial.println(F("Already joined network"));
    }

    wifly.setBroadcastInterval(0);	// Turn off UPD broadcast

    //wifly.terminal();

    Serial.print(F("MAC: "));
    Serial.println(wifly.getMAC(buf, sizeof(buf)));
    Serial.print(F("IP: "));
    Serial.println(wifly.getIP(buf, sizeof(buf)));

    wifly.setDeviceID("Wifly-WebServer");

    if (wifly.isConnected()) {
        Serial.println(F("Old connection active. Closing"));
	wifly.close();
    }

    wifly.setProtocol(WIFLY_PROTOCOL_TCP);
    if (wifly.getPort() != 80) {
        wifly.setPort(80);
	/* local port does not take effect until the WiFly has rebooted (2.32) */
	wifly.save();
	Serial.println(F("Set port to 80, rebooting to make it work"));
	wifly.reboot();
	delay(3000);
    }
    Serial.println(F("Ready"));
}

void loop()
{
    if (wifly.available() > 0) {

        /* See if there is a request */
	if (wifly.gets(buf, sizeof(buf))) {
	    if (strncmp_P(buf, PSTR("GET / "), 6) == 0) {
		/* GET request */
		Serial.println(F("Got GET request"));
		while (wifly.gets(buf, sizeof(buf)) > 0) {
		    /* Skip rest of request */
		}
		sendIndex();
		Serial.println(F("Sent index page"));
	    } else if (strncmp_P(buf, PSTR("POST"), 4) == 0) {
	        /* Form POST */
	        char username[16];
	        Serial.println(F("Got POST"));

		/* Get posted field value */
		if (wifly.match(F("user="))) {
		    wifly.gets(username, sizeof(username));
		    wifly.flushRx();		// discard rest of input
		    sendGreeting(username);
		    Serial.println(F("Sent greeting page"));
		}
	    } else {
	        /* Unexpected request */
		Serial.print(F("Unexpected: "));
		Serial.println(buf);
		wifly.flushRx();		// discard rest of input
		Serial.println(F("Sending 404"));
		send404();
	    }
	}
    }
}

/** Send an index HTML page with an input box for a username */
void sendIndex()
{
    /* Send the header direclty with print */
    wifly.println(F("HTTP/1.1 200 OK"));
    wifly.println(F("Content-Type: text/html"));
    wifly.println(F("Transfer-Encoding: chunked"));
    wifly.println();

    /* Send the body using the chunked protocol so the client knows when
     * the message is finished.
     * Note: we're not simply doing a close() because in version 2.32
     * firmware the close() does not work for client TCP streams.
     */
    wifly.sendChunkln(F("<html>"));
    wifly.sendChunkln(F("<title>WiFly HTTP Server Example</title>"));
    wifly.sendChunkln(F("<h1>"));
    wifly.sendChunkln(F("<p>Hello</p>"));
    wifly.sendChunkln(F("</h1>"));
    wifly.sendChunkln(F("<form name=\"input\" action=\"/\" method=\"post\">"));
    wifly.sendChunkln(F("Username:"));
    wifly.sendChunkln(F("<input type=\"text\" name=\"user\" />"));
    wifly.sendChunkln(F("<input type=\"submit\" value=\"Submit\" />"));
    wifly.sendChunkln(F("</form>")); 
    wifly.sendChunkln(F("</html>"));
    wifly.sendChunkln();
}

/** Send an greeting HTML page with the user's name and an analog reading */
void sendGreeting(char *name)
{
    /* Send the header direclty with print */
    wifly.println(F("HTTP/1.1 200 OK"));
    wifly.println(F("Content-Type: text/html"));
    wifly.println(F("Transfer-Encoding: chunked"));
    wifly.println();

    /* Send the body using the chunked protocol so the client knows when
     * the message is finished.
     */
    wifly.sendChunkln(F("<html>"));
    wifly.sendChunkln(F("<title>WiFly HTTP Server Example</title>"));
    /* No newlines on the next parts */
    wifly.sendChunk(F("<h1><p>Hello "));
    wifly.sendChunk(name);
    /* Finish the paragraph and heading */
    wifly.sendChunkln(F("</p></h1>"));

    /* Include a reading from Analog pin 0 */
    snprintf_P(buf, sizeof(buf), PSTR("<p>Analog0=%d</p>"), analogRead(A0));
    wifly.sendChunkln(buf);

    wifly.sendChunkln(F("</html>"));
    wifly.sendChunkln();
}

/** Send a 404 error */
void send404()
{
    wifly.println(F("HTTP/1.1 404 Not Found"));
    wifly.println(F("Content-Type: text/html"));
    wifly.println(F("Transfer-Encoding: chunked"));
    wifly.println();
    wifly.sendChunkln(F("<html><head>"));
    wifly.sendChunkln(F("<title>404 Not Found</title>"));
    wifly.sendChunkln(F("</head><body>"));
    wifly.sendChunkln(F("<h1>Not Found</h1>"));
    wifly.sendChunkln(F("<hr>"));
    wifly.sendChunkln(F("</body></html>"));
    wifly.sendChunkln();
}

Nice! Thanks! I'm writing some brief code to execute commands and retrieve/parse their results. I've noticed it works at 460k baud using hardware UART, but only 38,400 reliably using SofwareSerial. For debugging I use SoftwareSerial to Wifly, pins 0,1 for debug messages, but when the code is reliable you can easily switch 2 wires and 1 define to make it faster with hardware UART. Do you see the same results?

hi, I have the usb weather board from sparkfun and I am trying to get this RN-XV WiFly Module - RP-SMA Connector - WRL-11047 - SparkFun Electronics to get it work but after uploading the httpserver example all I get is this:

Starting
Free memory: 1337
setPrompt failed
Failed to enter command mode
Failed to start wifly
Terminal ready

what am I doing wrong ?:frowning:

thanks

ndanl:
hi, I have the usb weather board from sparkfun and I am trying to get this RN-XV WiFly Module - RP-SMA Connector - WRL-11047 - SparkFun Electronics to get it work but after uploading the httpserver example all I get is this:

Starting

Free memory: 1337
setPrompt failed
Failed to enter command mode
Failed to start wifly
Terminal ready




what am I doing wrong ?:(

thanks

The XBee hardware interface looks ok, its directly connecting TX and RX to the WiFly at 3.3V.

Those errors indicate that the Library can't talk to the board. Why don't you post the sketch you are using. It might be a simple problem like you're still using software serial when the WiFly is actually connected to the hardware serial interface, or maybe the baud rate doesn't match the rate set in the WiFly module.

A kind off topic question.

I read some tutoriais In the net, where they don't use a wireless shield, they connect directly In the arduino using SoftwareSerial.

The question is: the UART software serial In Arduino is not a 5v communication? If yes, why don't fry the board?

i did the same thing and work fine using your library, the board still working!

Thanks for the help, and sorry my english =]

the UART software serial In Arduino is not a 5v communication?

On a 5V Arduino, it is. On a 3.3V Arduino, it's at 3.3V.

viniciustc:
i did the same thing and work fine using your library, the board still working!

If you're using a 5V Arduino, then yes you will damage the WiFly over time and it will fail. It could take hours, days, or weeks for the failure to occur.

To fix the problem, add a voltage divider (two resistors) between the pin you're using for TX on the Arduino and the DIN pin on the WiFly module. A nice write up on how to do this is available here: http://www.savagecircuits.com/forums/content.php?309-Mixed-Voltage-Systems-Interfacing-5V-and-3-3V-Devices.

sbright33:
Nice! Thanks! I'm writing some brief code to execute commands and retrieve/parse their results. I've noticed it works at 460k baud using hardware UART, but only 38,400 reliably using SofwareSerial. For debugging I use SoftwareSerial to Wifly, pins 0,1 for debug messages, but when the code is reliable you can easily switch 2 wires and 1 define to make it faster with hardware UART. Do you see the same results?

I can only use 19200 baud reliably with SoftwareSerial, but yeah the hardware UART supports much faster speeds. I think I'll start using software serial for debugging via the serial monitor (with an FTDI USB cable) and the hardware UART for the WiFly module.

dhunt:

ndanl:
hi, I have the usb weather board from sparkfun and I am trying to get this RN-XV WiFly Module - RP-SMA Connector - WRL-11047 - SparkFun Electronics to get it work but after uploading the httpserver example all I get is this:

Starting

Free memory: 1337
setPrompt failed
Failed to enter command mode
Failed to start wifly
Terminal ready




what am I doing wrong ?:(

thanks

The XBee hardware interface looks ok, its directly connecting TX and RX to the WiFly at 3.3V.

Those errors indicate that the Library can't talk to the board. Why don't you post the sketch you are using. It might be a simple problem like you're still using software serial when the WiFly is actually connected to the hardware serial interface, or maybe the baud rate doesn't match the rate set in the WiFly module.

hm, i think that my usb weather board is damaged, since yesterday I can't get anything from serial ... so maybe this is why the wifly module is not working ... I will return :slight_smile: