Serial not declared in this scope. Now: WiFly Shield not connecting to network.

New Problem! Please see multi-part post on July 8.

I'm trying to build this project.

I'm using the Uno Arduino board with the latest Mac software. I have the latest Wifly Shield.

I'm getting this error when I try to compile:

WorldMood.cpp: In function 'void setup()':
WorldMood:109: error: 'Serial' was not declared in this scope
WorldMood.cpp: In function 'void loop()':
WorldMood:116: error: 'Serial' was not declared in this scope

I've done some looking and nothing seems to make it work, even including some extra libraries. I'm a fairly competent programmer but this is my first Arduino project and I'm stumped. Even stranger, I decided to the SerialCallResponse example project. It has almost the exact same code around the Serial bit that's causing me problems, but strangely enough, it just works. I really don't get it. Here's the actual code I am working with. The extra libraries are available here.

/* 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Title : WorldMood.pde
Author : http://www.instructables.com/member/RandomMatrix/

Description : 
Arduino program to compute the current world mood.
An Arduino connects to any wireless network via the WiFly module, repeatedly searches Twitter for tweets with emotional content, 
collates the tweets for each emotion, analyzes the data, and fades or flashes the color of an LED to reflect the current World Mood: 
Red for Anger, Yellow for Happy, Pink for Love, White for Fear, Green for Envy, Orange for Surprise, and Blue for Sadness.

Created : April 22 2010
Modified : 

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
*/
#include <HtmlParser.h>
#include <TwitterParser.h>
#include <string.h>
#include <WiFly.h>
#include <WorldMood.h>
#include <LED.h>
#include <avr/pgmspace.h>


// LED setup - only some pins provide 8-bit PWM (Pulse-width modulation)
// output with the analogWrite() function. 
// http://www.arduino.cc/en/Main/ArduinoBoardDuemilanove
// PWM: 3,5,6,9,10,11
#define redPin    (3)
#define greenPin  (5)
#define bluePin   (6)

// delay in ms between fade updates
// max fade time = 255 * 15 = 3.825s
#define fadeDelay (15)

// Wifi setup
#define network ("chezsondra")
#define password ("flannigan")
#define remoteServer ("twitter.com")

const char* moodNames[NUM_MOOD_TYPES] = {
  "love",
  "joy",
  "surprise",
  "anger",
  "envy",
  "sadness",
  "fear",
};

const char* moodIntensityNames[NUM_MOOD_INTENSITY] = {
  "mild",
  "considerable",
  "extreme",
};

// the long term ratios between tweets with emotional content
// as discovered by using the below search terms over a period of time.
float tempramentRatios[NUM_MOOD_TYPES] = {
  0.13f,
  0.15f,
  0.20f,
  0.14f,
  0.16f,
  0.12f,
  0.10f,
};

// these numbers can be tweaked to get the system to be more or less reactive
// to be more or less susceptible to noise or short term emotional blips, like sport results 
// or bigger events, like world disasters 
#define  emotionSmoothingFactor (0.1f)
#define  moodSmoothingFactor (0.05f)
#define  moderateMoodThreshold (2.0f)
#define  extremeMoodThreshold (4.0f)

// save battery, put the wifly to sleep for this long between searches (in ms)
#define SLEEP_TIME_BETWEEN_SEARCHES (1000 * 5) 

// Store search strings in flash (program) memory instead of SRAM.
// http://www.arduino.cc/en/Reference/PROGMEM
// edit TWEETS_PER_PAGE if changing the rpp value
prog_char string_0[] PROGMEM = "GET /search.json?q=\"i+love+you\"+OR+\"i+love+her\"+OR+\"i+love+him\"+OR+\"all+my+love\"+OR+\"i'm+in+love\"+OR+\"i+really+love\"&rpp=30&result_type=recent";
prog_char string_1[] PROGMEM = "GET /search.json?q=\"happiest\"+OR+\"so+happy\"+OR+\"so+excited\"+OR+\"i'm+happy\"+OR+\"woot\"+OR+\"w00t\"&rpp=30&result_type=recent";
prog_char string_2[] PROGMEM = "GET /search.json?q=\"wow\"+OR+\"O_o\"+OR+\"can't+believe\"+OR+\"wtf\"+OR+\"unbelievable\"&rpp=30&result_type=recent";
prog_char string_3[] PROGMEM = "GET /search.json?q=\"i+hate\"+OR+\"really+angry\"+OR+\"i+am+mad\"+OR+\"really+hate\"+OR+\"so+angry\"&rpp=30&result_type=recent";
prog_char string_4[] PROGMEM = "GET /search.json?q=\"i+wish+i\"+OR+\"i'm+envious\"+OR+ \"i'm+jealous\"+OR+\"i+want+to+be\"+OR+\"why+can't+i\"+&rpp=30&result_type=recent";
prog_char string_5[] PROGMEM = "GET /search.json?q=\"i'm+so+sad\"+OR+\"i'm+heartbroken\"+OR+\"i'm+so+upset\"+OR+\"i'm+depressed\"+OR+\"i+can't+stop+crying\"&rpp=30&result_type=recent";
prog_char string_6[] PROGMEM = "GET /search.json?q=\"i'm+so+scared\"+OR+\"i'm+really+scared\"+OR+\"i'm+terrified\"+OR+\"i'm+really+afraid\"+OR+\"so+scared+i\"&rpp=30&result_type=recent";

// be sure to change this if you edit the rpp value above
#define TWEETS_PER_PAGE (30)

PROGMEM const char *searchStrings[] = 	   
{   
  string_0,
  string_1,
  string_2,
  string_3,
  string_4,
  string_5,
  string_6,
};

void setup()
{
  Serial.begin(9600);
  delay(100); 
}

void loop()
{
  // create and initialise the subsystems  
  WiFly wifly(network, password, SLEEP_TIME_BETWEEN_SEARCHES, Serial);
  WorldMood worldMood(Serial, emotionSmoothingFactor, moodSmoothingFactor, moderateMoodThreshold, extremeMoodThreshold, tempramentRatios);
  LED led(Serial, redPin, greenPin, bluePin, fadeDelay);
  TwitterParser twitterSearchParser(Serial, TWEETS_PER_PAGE);

  wifly.Reset();
  
  char searchString[160]; 

  while (true)
  {
    for (int i = 0; i < NUM_MOOD_TYPES; i++)
    {
      twitterSearchParser.Reset();

      // read in new search string to SRAM from flash memory 
      strcpy_P(searchString, (char*)pgm_read_word(&(searchStrings[i]))); 

      bool ok = false;
      int retries = 0;

      // some recovery code if the web request fails
      while (!ok)
      {
        ok = wifly.HttpWebRequest(remoteServer, searchString, &twitterSearchParser);

        if (!ok)
        {
          Serial.println("HttpWebRequest failed");

          retries++;
          if (retries > 3)
          {
            wifly.Reset();
            retries = 0;
          }
        }
      }

      float tweetsPerMinute = twitterSearchParser.GetTweetsPerMinute();

      // debug code
      Serial.println("");
      Serial.print(moodNames[i]);
      Serial.print(": tweets per min = ");
      Serial.println(tweetsPerMinute);

      worldMood.RegisterTweets(i, tweetsPerMinute);
    }

    MOOD_TYPE newMood = worldMood.ComputeCurrentMood();
    MOOD_INTENSITY newMoodIntensity = worldMood.ComputeCurrentMoodIntensity();

    Serial.print("The Mood of the World is ... ");
    Serial.print(moodIntensityNames[(int)newMoodIntensity]);
    Serial.print(" ");
    Serial.println(moodNames[(int)newMood]);

    led.SetColor((int)newMood, (int)newMoodIntensity);

    // save the battery
    wifly.Sleep();

    // wait until it is time for the next update
    delay(SLEEP_TIME_BETWEEN_SEARCHES);

    Serial.println("");
  }
}

Could it be that you accidentally named your sketch WorldMood.c or WorldMood.cpp instead of WorkdMood.pde? I think the Arduino magic only works right if the file extension is .pde.

Nope. It's got the .pde extension.

Have you selected the correct board?

For recent versions of Arduino, the Arduino-type include file you need outside the main sketch is "WProgram.h" and this goes before any Arduino-stuff.

So...

Edit the following library files:

TwitterParser.h

#ifndef _TwitterParser_h
#define _TwitterParser_h

#include "WProgram.h"          // <--- Put this here
#include "HtmlParser.h"
//#include "HardwareSerial.h"  // <--- Don't need this
.
.
.

WiFly.h:

#ifndef _WiFly_h
#define _WiFly_h

#include "WProgram.h"          // <--- Put this here
//#include "HardwareSerial.h"  // <--- Don't need this
.
.
.

WorldMood.h:

#ifndef _WorldMood_h
#define _WorldMood_h

#include "WProgram.h"         // <--- Put this here
//#include "HardwareSerial.h" // <--- Don't need this
.
.
.

LED.h:

#ifndef _LED_h
#define _LED_h

#included "WProgram.h"        // <--- Put this here
//#include "HardwareSerial.h" // <--- Don't need this
.
.
.

Regards,

Dave

Footnote:
If you look in the Arduino core header file WProgram.h you can see that it includes the standard C library headers <stdlib.h>, <string.h>, <math.h> and some other stuff. It is redundant to include <string.h> in the main program sketch (or anywhere else where WProgram.h has been included). It's not "wrong" to include <string.h> (or <stdlib.h> or <math.h>), but I don't like a bunch of superfluous program statements cluttering up the landscape. (But maybe that's just me: I'm funny that way.)

A final note: The Arduino IDE takes care of including "WProgram.h" before the code in your main sketch, so you don't need it there, but you need it in any library files (or "tab" files in your project) that use Arduino-specific types or functions or classes or objects or whatever...

davekw7x:
Footnote:
If you look in the Arduino core header file WProgram.h you can see that it includes the standard C (C++) library headers <stdlib.h>, <string.h>, <math.h> and some other stuff. It is redundant to include <string.h> in the main program sketch (or anywhere else where WProgram.h has been included). It's not "wrong" to include <string.h> (or <stdlib.h> or <math.h>), but I don't like a bunch of superfluous program statements cluttering up the landscape. (But maybe that's just me: I'm funny that way.)

This is why I don't like monolithic headers. Who wants to sift through .h files to see which other headers they include? I don't agree with including header files in other header files, unless that file actually needs the definitions... you don't put superfluous includes in .cpp files, so why would .h files be any different?

If you look at the posted example, there is no "WProgram.h" included, and without peeking through each of the included headers, there is no way of knowing that it is included. And without further looking at WProgram.h, you won't know which std headers are included. You save much time and effort by just including the std header straight away.

Or you could just delete all the includes and wait for the compiler to tell you which ones you need grin

WProgram.h is an exception because the name suggests it is a shortcut header. I would prefer an "Arduino.h" header that only includes arduino specific statements and definitions, though.

similar but unrelated:
If you include a file outside the scope of your program, you should use < > instead of " " to enclose the file name. This lets the programmer and the compiler know it is for an outside library.

mowcius:
Have you selected the correct board?

Yes, other programs compile fine to it.

davekw7x:
For recent versions of Arduino, the Arduino-type include file you need outside the main sketch is "WProgram.h" and this goes before any Arduino-stuff.

So...

Edit the following library files:

After pulling the code apart and copy and pasting in a new file until it wouldn't compile, I had figured out that whatever was in WorldMood.h was causing my issue. Commenting it out moved errors to other parts of the program, commenting it back in caused the error. Then I saw you'd isolated the errors I was having.

Giving this a try now. Thank you.

And yes, I agree with the other posters about monolithic includes, though I've been guilty of it before. I've had programs that would only compile when I threw the proverbial kitchen sink at them, concise code be damned.

[edit]
And that fixed my error!

Thank you so much! Now, to see if the project actually works. Something tells me I'll be troubleshooting this for a while.

Still troubleshooting. Here's the issue I've run into. Code compiles and uploads to Arduino. But this project will not join the network.

Sorry for the long multipart post, but I wanted to not only capture my knowledge, I wanted to give you guys as much information as you might need to understand and possibly help me solve my problem. I'm not sure what will be important or relevant. Also, since this is an instructables project, there may be others with my problem, and there is a high possibility of others encountering the same problems I have. I want to make sure that they have the full knowledge of what I've done, and enough information to not have to re-solve the same problems.

I downloaded another project (WiFly Transparent Terminal) and it will allow me to manually join the network. This took me awhile as the WiFly had trouble with my network configuration and I had to change it. Here's it's code:

/*
 * WiFly UART-SPI bridge Example
 * Copyright (c) 2010 SparkFun Electronics.  All right reserved.
 * Written by Chris Taylor
 *
 * This code was written to demonstrate the WiFly Shield from SparkFun Electronics
 * 
 * This code will initialize and test the SC16IS750 UART-SPI bridge, and allow
 * transparent communication with the device from a terminal.
 *
 * http://www.sparkfun.com
 */

#include <string.h> // Required for strlen()

// SCI16IS750 Registers 
#define THR        0x00 << 3
#define RHR        0x00 << 3
#define IER        0x01 << 3
#define FCR        0x02 << 3
#define IIR        0x02 << 3
#define LCR        0x03 << 3
#define MCR        0x04 << 3
#define LSR        0x05 << 3
#define MSR        0x06 << 3
#define SPR        0x07 << 3
#define TXFIFO     0x08 << 3
#define RXFIFO     0x09 << 3
#define DLAB       0x80 << 3
#define IODIR      0x0A << 3
#define IOSTATE    0x0B << 3
#define IOINTMSK   0x0C << 3
#define IOCTRL     0x0E << 3
#define EFCR       0x0F << 3

#define DLL        0x00 << 3
#define DLM        0x01 << 3
#define EFR        0x02 << 3
#define XON1       0x04 << 3  
#define XON2       0x05 << 3
#define XOFF1      0x06 << 3
#define XOFF2      0x07 << 3

// Arduino SPI pins
#define CS         10
#define MOSI       11
#define MISO       12
#define SCK        13

// Communication flags and variables
char incoming_data; 
char TX_Fifo_Address = THR; 

char clr = 0;
char polling = 0;

// SC16IS750 Configuration Parameters
struct SPI_UART_cfg
{
  char DivL,DivM,DataFormat,Flow;
};

struct SPI_UART_cfg SPI_Uart_config = {
  0x60,0x00,0x03,0x10};

void setup()
{
  // Initialize SPI pins
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK,OUTPUT);
  pinMode(CS,OUTPUT);
  digitalWrite(CS,HIGH); //disable device 

  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
  clr=SPSR;
  clr=SPDR;
  delay(10); 

  Serial.begin(9600);
  Serial.println("\n\r\n\rWiFly Shield Terminal Routine");

  // Test SPI communication
  if(SPI_Uart_Init()){ 
    Serial.println("Bridge initialized successfully!"); 
  }
  else{ 
    Serial.println("Could not initialize bridge, locking up.\n\r"); 
    while(1); 
  }
}

void loop()
{
  // Poll for new data in SC16IS750 Recieve buffer 
  if(SPI_Uart_ReadByte(LSR) & 0x01)
  { 
    polling = 1;
    while(polling)
    {
      if((SPI_Uart_ReadByte(LSR) & 0x01))
      {
        incoming_data = SPI_Uart_ReadByte(RHR);
        Serial.print(incoming_data,BYTE);
      }  
      else
      {
        polling = 0;
      }
    }

  }
  // Otherwise, send chars from terminal to SC16IS750
  else if(Serial.available())
  {
    incoming_data = Serial.read();
    select();
    spi_transfer(0x00); // Transmit command
    spi_transfer(incoming_data);
    deselect();
  }

}



char SPI_Uart_Init(void)
// Initialize SC16IS750
{
  char data = 0;

  SPI_Uart_WriteByte(LCR,0x80); // 0x80 to program baudrate
  SPI_Uart_WriteByte(DLL,SPI_Uart_config.DivL); //0x50 = 9600 with Xtal = 12.288MHz
  SPI_Uart_WriteByte(DLM,SPI_Uart_config.DivM); 

  SPI_Uart_WriteByte(LCR, 0xBF); // access EFR register
  SPI_Uart_WriteByte(EFR, SPI_Uart_config.Flow); // enable enhanced registers
  SPI_Uart_WriteByte(LCR, SPI_Uart_config.DataFormat); // 8 data bit, 1 stop bit, no parity
  SPI_Uart_WriteByte(FCR, 0x06); // reset TXFIFO, reset RXFIFO, non FIFO mode
  SPI_Uart_WriteByte(FCR, 0x01); // enable FIFO mode

  // Perform read/write test to check if UART is working
  SPI_Uart_WriteByte(SPR,'H');
  data = SPI_Uart_ReadByte(SPR);

  if(data == 'H'){ 
    return 1; 
  }
  else{ 
    return 0; 
  }

}

void SPI_Uart_WriteByte(char address, char data)
// Write byte to register address on SC16IS750
{
  long int length;
  char senddata[2];
  senddata[0] = address;
  senddata[1] = data;

  select();
  length = SPI_Write(senddata, 2);
  deselect();
}

long int SPI_Write(char* srcptr, long int length)
// Send entire string to SC16IS750
{
  for(long int i = 0; i < length; i++)
  {
    spi_transfer(srcptr[i]);
  }
  return length; 
}

void SPI_Uart_WriteArray(char *data, long int NumBytes)
// Send entire string to THR of SC16IS750
{
  long int length;
  select();
  length = SPI_Write(&TX_Fifo_Address,1);

  while(NumBytes > 16) // Split array into 16 character chunks
  {
    length = SPI_Write(data,16);
    NumBytes -= 16;
    data += 16;
  }
  length = SPI_Write(data,NumBytes);

  deselect();
}

char SPI_Uart_ReadByte(char address)
// Read from SC16IS750 register
{
  char data;

  address = (address | 0x80);

  select();
  spi_transfer(address);
  data = spi_transfer(0xFF);
  deselect();
  return data;  
}

void SPI_Uart_println(char *data)
// Write string to SC16IS750 followed by a carriage return
{
  SPI_Uart_WriteArray(data,strlen(data));
  SPI_Uart_WriteByte(THR, 0x0d);
}

void SPI_Uart_print(char *data)
// Write string to SC16IS750, no carriage return
{
  SPI_Uart_WriteArray(data,strlen(data));
}

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait for the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

void select(void) 
{
  digitalWrite(CS,LOW);
}

void deselect(void)
{
  digitalWrite(CS,HIGH);
}

To join the network, I must issue the following commands in order.

"$$$" (no carriage return), returns "CMD"
"set wlan phrase flannigan", returns "AOK" (flannigan is the passphrase for my wireless network)
"join chezsondra", returns
"DHCP: Start
DHCP in 15ms, lease=86400s
IF=UP
DHCP=ON
IP=192.168.1.135:80
NM=255.255.255.0
GW=192.168.1.1" (obviously, chezsondra is the name of my wireless network, and obviously, these have been changed for this experiment)

Now, I know my soldering was fine and the hardware works because I can ping websites and do other network functions of the WiFly shield. So, great, SUCCESS!

...except that when I compile and run the Twitter Mood Light software, it doesn't work. Here's the error messages I get back.
connecting to network...
Entering command mode.
WiFly Shield
initializing SC16IS750 bridge...
success!

connecting to network...
Entering command mode.
warning: failed to find CMD
warning: failed to find Reboot
warning: failed to find READY
Entering command mode.
warning: failed to find CMD
warning: found ERR
warning: failed to find IP=
Failed to associate with 'chezsondra'

Retrying...
connecting to network...
Entering command mode.
warning: failed to find CMD

Ad nauseam. It appears that it goes into CMD mode, but then doesn't realize that it's in CMD mode, because if you try to enter CMD with the '$$$' command while you're already in CMD mode, you just get an ERR message (ERR: ?-Cmd). It also appears to be trying to use the command "reboot", which returns this in manual mode and resets the WiFly:

"RebootWiFly Ver 2.21, 07-11-2010
MAC Addr=00:06:66:13:c8:12
Auto-Assoc roving1 chan=9 mode=NONE FAILED
READY
Auto-Assoc roving1 chan=9 mode=NONE FAILED"

Now that I've figured out that everything works as intended and my network is configured properly to allow the WiFly shield to connect -- and it does -- this code should be plug and play. At least, the networking part should be. But it's not.

I can't figure out why it doesn't marry up to the network, but I can tell it's in one of the following files:
WiFly.h

#ifndef _WiFly_h
#define _WiFly_h


#include "WProgram.h"
//#include "HardwareSerial.h"

class HtmlParser;


class WiFly
{
public:
  // public interface
  WiFly(const char* ssid, const char* auth_phrase, int sleepTime, HardwareSerial &print);

  bool Reset();
  bool HttpWebRequest(const char* server, const char* getCommand, HtmlParser* parser);
  void Sleep();

private:

  void SPI_UART_Init();
  bool TestSPI_UART_Bridge();

  void WriteByteToRegister(char address, char data);
  void WriteToWiFly(const char *data);
  void WriteToWiFlyCR(const char *data);
  void WriteToWiFlyCRLF(const char *data);

  char ReadCharFromWiFly(char address);
  int  WriteChunk(const char* data, int length);

  void AutoConnect();
  void FlushRX(void);

  char spi_transfer(volatile char data);
  void select();
  void deselect();

  void EnterCommandMode();
  void ExitCommandMode();
  bool WaitUntilReceived(const char* OKresult, const char* errorResult = 0);


  const char* m_network;
  const char* m_password;
  const int m_sleepTime;

  HardwareSerial* m_printer;
};


#endif // #ifndef _WiFly_h

Or WiFly.cpp. This file is too long to post entirely, but will be posted in parts.

WiFly.cpp (1/3)

/* 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Title : WiFly.cpp
Author : http://www.instructables.com/member/RandomMatrix/

Description : A wrapper for initialising the ìWiFly GSXî 802.11G Module, communicating with it via its SPI-to-UART chip 
              connecting to a wifi network and making simple GET HttpWebRequests.

 The WiFly Shield equips your Arduino the ability to connect to 802.11b/g wireless networks. 
 The featured components of the shield are a Roving Network's RN-131G wireless module and an SC16IS750 SPI-to-UART chip. 
 The SPI-to-UART bridge is used to allow for faster transmission speed and to free up the Arduino's UART.

 code and comments based on the following sources:
    http://www.arduino.cc/en/Tutorial/SPIEEPROM
    http://www.lammertbies.nl/comm/info/serial-uart.html
    http://www.tinyclr.com/downloads/Shield/FEZ_Shields_WiFly.cs
    http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=158
    http://www.sparkfun.com/datasheets/Components/SMD/sc16is750.pdf
    http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um.pdf
    http://www.sparkfun.com/datasheets/Wireless/WiFi/rn-131G-ds.pdf
    http://www.societyofrobots.com/microcontroller_uart.shtml

*** Warning ***
The code presented here is in no way a library for the ìWiFly GSXî 802.11G Module.
It does what I need it to do, but writing a full library is beyond the intended scope of the project.

Use at your own risk.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
*/


#include "WiFly.h"
#include "HtmlParser.h"
#include "WProgram.h"
#include <string.h>

// SC16IS750 Register Definitions
// see http://www.lammertbies.nl/comm/info/serial-uart.html
#define THR        0x00 << 3  // THR, Transmitter holding register (WO)
#define RHR        0x00 << 3  // RHR, Receiver holding register (RO)
#define IER        0x01 << 3  // IER, interrupt enable register (R/W)
#define FCR        0x02 << 3  // FCR, FIFO control  (WO)
#define IIR        0x02 << 3  // IIR, interrupt identification register  (RO)
#define LCR        0x03 << 3  // LCR, line control (R/W)
#define MCR        0x04 << 3  // MCR, modem control (R/W)
#define LSR        0x05 << 3  // LSR, line status register (RO)
#define MSR        0x06 << 3  // MSR, modem status register (RO)
#define SPR        0x07 << 3  // SPR, scratchpad register (R/W)

// see http://www.sparkfun.com/datasheets/Components/SMD/sc16is750.pdf
#define TXFIFO     0x08 << 3  // Transmit FIFO Level Register
#define RXFIFO     0x09 << 3  // Receive FIFO Level Register
#define DLAB       0x80 << 3
#define IODIR      0x0A << 3  // I/O pin Direction Register
#define IOSTATE    0x0B << 3  // I/O pin States Register
#define IOINTMSK   0x0C << 3  // I/O Interrupt Enable Register?
#define IOCTRL     0x0E << 3  // I/O pins Control Register
#define EFCR       0x0F << 3  // Extra Features Register

#define DLL        0x00 << 3 // divisor latch LSB
#define DLM        0x01 << 3 // divisor latch MSB?
#define EFR        0x02 << 3 // Enhanced Feature Register
#define XON1       0x04 << 3  
#define XON2       0x05 << 3
#define XOFF1      0x06 << 3
#define XOFF2      0x07 << 3

// SPI pin definitions
#define CS         10 // Slave Select pin - allocated on each device which the master can use to enable and disable 
                      // specific devices and avoid false transmissions due to line noise. 
#define MOSI       11 // Master In Slave Out (MISO) - The Slave line for sending data to the master, 
#define MISO       12 // Master Out Slave In (MOSI) - The Master line for sending data to the peripherals, 
#define SCK        13 // Serial Clock (SCK) - The clock pulses which synchronize data transmission generated by the master

#define ASSOCIATE_TIMEOUT 5000

// These times are taken from Boot-up Timing Values from the datasheet, 
// http://www.sparkfun.com/datasheets/Wireless/WiFi/WiFlyGSX-um.pdf
#define DEFAULT_TIME_TO_READY (600)
#define DEFAULT_TIME_TO_JOIN (800)
#define DEFAULT_TIME_TO_AUTHENTICATE (300)
#define DEFAULT_TIME_TO_WAIT (200)
#define DEFAULT_TIME_UNTIL_TIMEOUT (5000)

#define COMM_OPEN "*OPEN*"
#define COMM_CLOSE "*CLOS*"
#define AOK "AOK"
#define ERR "ERR"

//The THR is actually a 64-byte FIFO accordning to http://www.sparkfun.com/datasheets/Components/SMD/sc16is750.pdf
#define THR_MAX_BYTES (64)

// SC16IS750 communication parameters
struct SPI_UART_cfg
{
  char DivL;
  char DivM;
  char DataFormat;
  char Flow;
};

struct SPI_UART_cfg SPI_Uart_config = {0x60,0x00,0x03,0x10};

// Wifi parameters
char auth_level[] = "3";
char port_listen[] = "80";

WiFly::WiFly(const char* ssid, 
             const char* auth_phrase,
             int sleepTime,
             HardwareSerial& print):
m_network(ssid),
m_password(auth_phrase),
m_sleepTime(sleepTime),
m_printer(&print)
{
}

WiFly.cpp (2/3)

bool WiFly::Reset()
{
  // SPI pin initialization
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK,OUTPUT);
  pinMode(CS,OUTPUT);

  deselect(); //disable device 

  // see http://www.arduino.cc/en/Tutorial/SPIEEPROM
  // http://www.sparkfun.com/datasheets/Components/SMD/sc16is750.pdf
  /* 
  Now we set the SPI Control register (SPCR) to the binary value 01010000. 
  In the control register each bit sets a different functionality.
  The eighth bit disables the SPI interrupt, 
  the seventh bit enables the SPI, 
  the sixth bit chooses transmission with the most significant bit going first, 
  the fifth bit puts the Arduino in Master mode, 
  the fourth bit sets the data clock idle when it is low, 
  the third bit sets the SPI to sample data on the rising edge of the data clock, 
  and the second and first bits set the speed of the SPI to system speed / 4 (the fastest).
  After setting our control register up we read the SPI status register (SPSR) and data register (SPDR)
  in to the junk clr variable to clear out any spurious data from past runs:*/

  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
  
  char clr = SPSR;
  clr = SPDR;
  delay(10); 

  // Data registers simply hold bytes. For example, the SPI data register (SPDR) 
  // holds the byte which is about to be shifted out the MOSI line, and the data which has just been shifted in the MISO line.

  m_printer->println("WiFly Shield");
  m_printer->println("initializing SC16IS750 bridge..."); 

  SPI_UART_Init();

  // Test SC16IS750 communication
  const bool ok = TestSPI_UART_Bridge();
  

  if(!ok)
  { 
    m_printer->println("Could not initialize SC16IS750 bridge"); 
    return false;
  }

  m_printer->println("success!"); 
  m_printer->println(""); 

  AutoConnect();

  return true;
}


// Test if the SPI<->UART bridge has been set up correctly by writing a test 
// character via SPI and reading it back.
// returns true if success

bool WiFly::TestSPI_UART_Bridge()
{
  // Perform read/write test to check if SPI<->UART bridge is working

  // write a character to the scratchpad register.
  WriteByteToRegister(SPR, 0x55);

  char data = ReadCharFromWiFly(SPR);

  if(data == 0x55)
  { 
    return true; 
  }
  else
  { 
    m_printer->println("Failed to init SPI<->UART chip");
    return false; 
  }
}

// A series of register writes to initialize the SC16IS750 SPI-UART bridge chip
// see http://www.tinyclr.com/downloads/Shield/FEZ_Shields_WiFly.cs

void WiFly::SPI_UART_Init(void)
{
  WriteByteToRegister(LCR,0x80); // 0x80 to program baudrate
  WriteByteToRegister(DLL,SPI_Uart_config.DivL); //0x50 = 9600 with Xtal = 12.288MHz
  WriteByteToRegister(DLM,SPI_Uart_config.DivM); 

  WriteByteToRegister(LCR, 0xBF); // access EFR register
  WriteByteToRegister(EFR, SPI_Uart_config.Flow); // enable enhanced registers
  WriteByteToRegister(LCR, SPI_Uart_config.DataFormat); // 8 data bit, 1 stop bit, no parity
  WriteByteToRegister(FCR, 0x06); // reset TXFIFO, reset RXFIFO, non FIFO mode
  WriteByteToRegister(FCR, 0x01); // enable FIFO mode
}

/*
  Send the correct commands to connect to a wireless network using the parameters used on construction
*/
void WiFly::AutoConnect()
{
  m_printer->println("connecting to network..."); 

  delay(DEFAULT_TIME_TO_READY);

  FlushRX();

  // Enter command mode
  EnterCommandMode();

  // Reboot to get device into known state
  WriteToWiFlyCR("reboot");
  WaitUntilReceived("*Reboot*");
  WaitUntilReceived("*READY*");
  
  FlushRX();

  // Enter command mode
  EnterCommandMode();

  // turn off auto joining
  WriteToWiFlyCR("set wlan join 0");
  WaitUntilReceived(AOK, ERR);

  // Set authentication level to <auth_level>
  WriteToWiFly("set w a ");
  WriteToWiFlyCR(auth_level); 
  WaitUntilReceived(AOK, ERR);

  // Set authentication phrase to <auth_phrase>
  WriteToWiFly("set w p ");
  WriteToWiFlyCR(m_password);
  WaitUntilReceived(AOK, ERR);

  // Set localport to <port_listen>
  WriteToWiFly("set i l ");
  WriteToWiFlyCR(port_listen);
  WaitUntilReceived(AOK, ERR);

  // Deactivate remote connection automatic message
  WriteToWiFlyCR("set comm remote 0");
  WaitUntilReceived(AOK, ERR);

  // Join wireless network <ssid>
  WriteToWiFly("join ");
  WriteToWiFlyCR(m_network);  
  delay(DEFAULT_TIME_TO_JOIN);

  bool ok = WaitUntilReceived("IP=");
  delay(DEFAULT_TIME_TO_WAIT);

  FlushRX();
  
  if(ok == false)
  {
    m_printer->print("Failed to associate with '");
    m_printer->print(m_network);
    m_printer->println("'\n\rRetrying...");
    FlushRX();
    AutoConnect();
  }
  else
  {
    m_printer->println("connected!");
    ExitCommandMode();
  }

  // TODO save this configuration
}

/*
  Parameters: The server to telnet into, the get command that needs to be sent, a custom HtmlParser that
  is called every time a character is received. The parser is responsible for processing the HTML
  that is returned.

  Http is just TCP/IP on port 80

  "Open <ipaddress> 80"

  or using DNS,
  "Open www.google.com 80"

  Twitter requires more of the Http protocol than other sites.
  For example, the "Host" field is required in case there's more than one
  domain name mapped to the server's IP address so it can tell which
  website you actually want.

  "GET / HTTP/1.1\n"
  "Host: server\r\n"
  "\r\n"

*/
bool WiFly::HttpWebRequest(const char* server, const char* getCommand, HtmlParser* parser)
{
  m_printer->println(getCommand);
  FlushRX(); 
  FlushRX(); 

  // Enter command mode
  EnterCommandMode();
  FlushRX(); 

  // open a TCP connection, port 80 for HTTP
  WriteToWiFly("open ");
  WriteToWiFly(server);
  WriteToWiFlyCR(" 80");

  bool openOK = WaitUntilReceived(COMM_OPEN);

  if (openOK == false)
  {
    m_printer->println("open port failed!");
    delay(1000);
    WriteToWiFlyCR("close");
    WaitUntilReceived(COMM_CLOSE);

    ExitCommandMode();
    return false;
  }

WiFly.cpp (3/3)

  // eg. "GET /search.json?q=foo HTTP/1.1\r\n"
  WriteToWiFlyCRLF(getCommand);

  // eg. "Host: search.twitter.com\r\n"
  WriteToWiFly("Host: ");
  WriteToWiFlyCRLF(server);

  // "\r\n"
  WriteToWiFlyCRLF("");

  // now wait for the response

  int timeOut = 0;
  bool ok = false;

  while(timeOut < 5000)// timeout after 5 seconds
  {
    if((ReadCharFromWiFly(LSR) & 0x01))
    {
      char incoming_data = ReadCharFromWiFly(RHR);
      m_printer->print(incoming_data,BYTE);

      bool done = parser->Parse(incoming_data);
      if (done)
      {
        ok = true;
        break;
      }

      timeOut = 0; //reset the timeout
    }
    else
    {
      delay(1);
      timeOut++;
    }
  }

  FlushRX(); 

  // disconnect TCP connection.
  WriteToWiFlyCR("close");
  WaitUntilReceived(COMM_CLOSE);

  ExitCommandMode();

  return ok;
}

/*
  send the WiFly module to sleep to put into "Ultra-low power" mode (4uA sleep)
*/
void WiFly::Sleep()
{
  WriteToWiFlyCR("set sys sleep 1");
  
  WriteToWiFly("set sys wake ");
  char buffer[10];
  itoa(m_sleepTime, buffer, 10);
  WriteToWiFlyCR(buffer);
}

void WiFly::select()
{
  digitalWrite(CS,LOW);
}

void WiFly::deselect()
{
  digitalWrite(CS,HIGH);
}

// send data to the Wifly and append "\n"
void WiFly::WriteToWiFlyCR(const char* data)
{
  WriteToWiFly(data);
  WriteByteToRegister(THR, 0x0d); // CR
}

// send data to the Wifly and append "\r\n"
void WiFly::WriteToWiFlyCRLF(const char* data)
{
  WriteToWiFly(data);
  WriteByteToRegister(THR, 0x0d); // CR
  WriteByteToRegister(THR, 0x0a); // LF
}

/*
  wrapper for WriteChunk
  see below
*/
void WiFly::WriteToWiFly(const char* data)
{
  int length = strlen(data);

  while (length > 0)
  {
     int written = WriteChunk(data, length);
     data += written;
     length -= written;
  }
}

/*
  The transmitter section consists of the Transmit Holding Register (THR) and the Transmit
  Shift Register (TSR). The THR is actually a 64-byte FIFO. The THR receives data and
  shifts it into the TSR, where it is converted to serial data and moved out on the TX pin. If
  the FIFO is disabled, the FIFO is still used to store the byte. Characters are lost if overflow
  occurs.
*/
int WiFly::WriteChunk(const char* data, int length)
{
  select();
  spi_transfer(THR);

  length = min(length, THR_MAX_BYTES);

  for(int i = 0; i < length; ++i)
  {
    spi_transfer(data[i]);
    delay(1); // This seems to decrease error characters
  }

  deselect();

  return length;
}

// Write <data> to SC16IS750 register at <address>
void WiFly::WriteByteToRegister(char address, char data)
{
  select();
  spi_transfer(address);
  spi_transfer(data);
  deselect();
}


/*
  The ReadCharFromWiFly function allows us to read data back out of the WiFly. 
*/
char WiFly::ReadCharFromWiFly(char address)
{
  address = (address | 0x80);

  select();
  spi_transfer(address);
  char data = spi_transfer(0xFF);
  deselect();

  return data;  
}

// Flush characters from SC16IS750
void WiFly::FlushRX()
{
  while((ReadCharFromWiFly(LSR) & 0x01))
  {
    char _flushed = ReadCharFromWiFly(RHR);
  }  
}

/*
  The spi_transfer function loads the output data into the data transmission register, 
  thus starting the SPI transmission. It polls a bit to the SPI Status register (SPSR) 
  to detect when the transmission is complete using a bit mask, SPIF. 
  It then returns any data that has been shifted in to the data register
*/
char WiFly::spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait for the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}


/*
  Continue reading data from the wifly until either we receive the OKresults or the errorResult or we timeout
  There is some capability to ignore noise by just requiring that the sequence of characters are received in the 
  correct order, but with possibility other characters arriving too.
  returns true if success
*/
bool WiFly::WaitUntilReceived(const char* OKresult, const char* errorResult /* = 0 */)
{
  // find the length of the strings
  int OKLength = strlen(OKresult);
  int errorLength = strlen(errorResult);

  // keep track of when to timeout
  int timeOut = 0;

  // keep track of how many correct characters have been received
  int OKCounter = 0;
  int errorCounter = 0;

  while(timeOut < DEFAULT_TIME_UNTIL_TIMEOUT)// timeout after 5 seconds
  {
    // read from the wifil
    if((ReadCharFromWiFly(LSR) & 0x01))
    {
      char incoming = ReadCharFromWiFly(RHR);

      if (incoming == OKresult[OKCounter])
      {
        // found the next character in the success string
        OKCounter++;
      }

      if (OKCounter == OKLength)
      {
        // done
        return true;
      }

      if (errorResult != 0)
      {
        if (incoming == errorResult[errorCounter])
        {
          // found the next character in the fail string
          errorCounter++;
        }

        if (errorCounter == errorLength)
        {
          m_printer->print("warning: found ");
          m_printer->println(errorResult);
          return false;
        }
      }
    }
    else
    {
      delay(1);
      timeOut++;
    }
  }

  m_printer->print("warning: failed to find ");
  m_printer->println(OKresult);
        
  return false;
}


/*
  Enter command mode by sending: $$ 
  Characters are passed until this exact sequence is seen. If any bytes are seen before these chars, or
  after these chars, in a 1 second window, command mode will not be entered and these bytes will be passed 
  on to other side.
*/
void WiFly::EnterCommandMode()
{
  FlushRX();
  delay(1000); // wait 1s as instructed above
  m_printer->println("Entering command mode.");
  WriteToWiFly("$$");
	WaitUntilReceived("CMD");
}


/*
  exit command mode 
  send the "exit" command and await the confirmation result "EXIT"
*/
void WiFly::ExitCommandMode()
{
  WriteToWiFlyCR("exit");
  WaitUntilReceived("EXIT");
}

For those playing with the WiFly Shield and having problems joining their own networks, here's what was going on with my situation. It's not really relevant to the problem at hand as these problems have been solved. This post is just to add to the body of knowledge and help anyone else who might encounter my same problem in the future.

Initially, the WiFly would not return any good information through the serial port. I couldn't seem to issue any commands and it wouldn't return anything other than garbage characters. I initially thought I had a defective Shield or had poor solder joints or might have damaged it somewhere along the line. Obviously, this was not the case.

What I found was that although the USB power was enough to light up the board and make it appear to be fully functional, it is not enough to actually power it. 9v power must be provided to the board to enable working operation.

Once that was solved, the initial command to enter command mode, $$$, must be sent without a carriage return. All other commands past this point must be sent with a carriage return. This is not entirely clear in the manual, and can be confusing, especially if you have already accidentally entered CMD mode and did not realize it -- the Shield will stay in command mode across projects and will stay there until power is completely disconnected or the 'reboot' or 'exit' command is sent.

After that, my network configuration was an issue. It was a custom Tomato implementation using two routers and WDS mode to use the second router to extend range to the front of the house and onto the front lawn. I used WPA1 with AES, as WPA1 is one of the few modes that works with Tomato in WDS mode. Unfortunately, the WiFly Shield only supports the following security protocols: WEP-128 (open mode only, NOT shared mode), WPA2-PSK (AES only),WPA1-PSK (TKIP only),WPA-PSK mixed mode. Mixed mode AES/TKIP does not work. Fortunately, WPA1 with TKIP does work on my network and does work with the WiFly Shield.

I have encountered the same problems. Now I'm stuck at the same place as jackmccauley. Has any of you solved this problem?

Hers the error from serial monitor:

WiFly Shield
initializing SC16IS750 bridge...
success!

connecting to network...
Entering command mode.
warning: failed to find CMD
warning: failed to find Reboot
warning: failed to find READY

Trying to get all this down while it's fresh in my brain.

I sat down tonight with another talented programmer (though he had no Arduino experience either) and we spent a few hours picking away at this. We made some headway, we're getting fairly consistent behavior now and we even managed to have it connect to the network and ping the twitter server. Once.

The short answer is that it's primarily related to timing. Basically, the board is looking for a response, but it's not catching the response at the right time. There's some commenting in the code about this, and we're speculating that because we're using an Uno board instead of the Duemilanove the project was designed to use, we're getting these issues.

The other problem is that the code is absolutely terrible. The error handling might as well not exist, and the original programmer is very optimistic about when things are going to occur. For instance, when you send $$$ to the board to invoke command mode, you must make sure that no commands are sent one second before or after the $$$ command or it won't work. The code of course waits exactly one second, which means if it runs even a little fast, the code will never work. Just to let you know, sometimes it takes a second, but usually it runs a little fast. This is the kind of fault tolerance evident in all the code.

We're poking through it, but we suspect that the WiFly.cpp code will require a complete rewrite, which may take some time and if someone wants to help out, that would be appreciated. You can grab the updated file here: http://ge.tt/8BJz1F9

I am in the exact same boat as you guys. I am using the Uno and the Moodlight code. I have gotten it to compile after a ton of this and that. And appear to be in the same place you last posted about. I tried to grab your edited code, but the link expired. I'd love to know where you got.

I have gone through every bit of info online that I can find to get this to compile. Most of that was the small changes in this thread as well as the necessity to make the necessary replacements with "#include <Arduino.h>".

I am down to one final issue, and am hoping that someone has some insight.

My final compile error is:

...WiFly/WiFly.cpp: In member function 'bool WiFly::HttpWebRequest(const char*, const char*, HtmlParser*)':

...WiFly/WiFly.cpp:362: error: 'BYTE' was not declared in this scope

In Wifly.Cpp, on line 362, I see the following:

m_printer->print(incoming_data,BYTE);

If I comment this line out, I can get the code to compile. But, when I run the code on the arduino, I see the following in the serial monitor:

Wi AOK
WiFly Shield
initializing SC16IS750 bridge...
success!

connecting to network...
Entering command mode.
warning: failed to find CMD
warning: failed to find Reboot
warning: failed to find READY
Entering command mode.
warning: failed to find CMD
warning: failed to find AOK
warning: failed to find AOK
warning: failed to find AOK
warning: failed to find AOK
warning: failed to find AOK
warning: failed to find IP=
Failed to associate with 'h-bomb-2'

So, it appears to be running, but I have issues with the network connection.

Clearly, I don't want to be commenting out that line, but am unsure of why it won't compile with that line of code in place.

Any ideas? Has anyone had any luck getting this running in the last year?

In Wifly.Cpp, on line 362, I see the following:

m_printer->print(incoming_data,BYTE);

If I comment this line out, I can get the code to compile. But, when I run the code on the arduino, I see the following in the serial monitor:

Don't comment out that code. Make the correct change (to use the write() method).

Thanks for the response. Things aren't dead!
I will give that a shot.

The code is sort of a mess, so I will see what I can do.

If I can get it compiled and working, I will be sure to upload the revised version so others can start there and not have to go through this comedy of errors...

Thank you.