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.
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...
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.
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?
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.
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.
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.
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