Hi all,
NNzz:
It's stuck on WiFly.begin().
Had exactly the same problem, think I got it fixed - so I thought I'd document my steps.
So, I get a WiFly, and I get the code from GitHub. With the intent to use it on the Arduino MEGA 2560, I resolder D13, D12, D11, D10 on the shield to D52, D50, D51, D53 on the MEGA 2560 as explained in src/WiFly/README.txt. I copy the folder WiFly-Shield/src/WiFly from the code to arduino-0022/libraries; and I decide to try src/WiFly/examples/tools/SpiUartTerminal.pde... and, I experience the freeze on WiFly.begin().
Well, since the main communication between the Arduino and the WiFly is via SPI, I decide to check the SPI pins on an oscilloscope. I would have expected at least the SCLK clock (D13 on Uno, D52 on Mega) to be shown pulsing - but surprisingly, all of the pins showed DC voltage. Then I thought about trying the default SPI examples in arduino-0022, so I chose SPI/examples/BarometricPressureSensor.pde
. Immmediately after building and uploading this sketch, I could see SCLK pulses on D52 on the Mega; so my conclusion was, there must be a problem with the SPI initialization in the WiFly library.
Thus, I began a somewhat tedious process of comparing the default SPI library in the Arduino IDE, and the SPI related parts of the WiFly library. My initial guess was, that the SCLK pulses start immediately after a succesful .begin()
has been initiated; however, actual pulses (that I could catch on the scope) usually occur when a .transfer()
command executing in the loop()
. So I made me a small .pde program, to have the same .begin in setup(), and .transfer in loop() implemented through either library for comparison - and I could realize that, as concluded earlier, .begin() from WiFLy simply never returns - here's the test code I used, called it spi_test_wi.pde
:
// comment/uncomment the define as needed:
#define WIFLY
//#define DFLTSPI
#ifdef DFLTSPI
// from Examples/SPI/BarometricPressureSensor.pde
// the sensor communicates using SPI, so include the library:
#include <SPI.h>
void setup() {
// start the SPI library:
SPI.begin();
}
#endif
#ifdef WIFLY
// from Examples/WiFly/WiFly-examples/tools/SpiUartTerminal.pde
#include "WiFly.h" // We use this for the preinstantiated SpiSerial object.
void setup() {
// start the SPI library:
SpiSerial.begin();
// if these functions are made public in SpiUart.h, they
// will then show pulses in this loop here..
while(!SpiSerial.uartConnected()){
SpiSerial.configureUart(9600);
}
}
#endif
void loop() {
#ifdef DFLTSPI
SPI.transfer(0x00);
#endif
#ifdef WIFLY
// class SpiUartDevice : public SpiDevice, public Print
// overloads SpiDevice, which has SpiDevice::transfer
SpiSerial.transfer(0x00); // ok if setup doesn't lock
////SpiSerial.writeRegister(LCR, 1 << 7); //private :(
////SpiSerial.print(0x00); //ok if setup doesn't lock; big delays
//SpiSerial.write("hello"); //ok if setup doesn't lock; big delays
//SpiSerial.configureUart(9600); //private
#endif
;
//asm("nop"); //delay? not much ..
}
So, I decide to look closer in SpiSerial.begin();
- that function eventually calls SpiUartDevice::initUart
, where a comment can be read: "// Lock up if we fail to initialise SPI UART bridge.", this lock up being entering a while(1)
loop. So, I basically decide to comment this loop in arduino-0022/libraries/WiFly/SpiUart.cpp
:
void SpiUartDevice::initUart(unsigned long baudrate) {
/*
Initialise the UART.
If initialisation fails this method does not return.
*/
// Initialise and test SC16IS750
configureUart(baudrate);
if(!uartConnected()){
//~ while(1) {
//~ // Lock up if we fail to initialise SPI UART bridge. <======
//~ };
}
// The SPI UART bridge is now successfully initialised.
}
... and move the running of uartConnected()
check in the main .pde code; however, since this function is by default private, it needs to be made public for that - so in arduino-0022/libraries/WiFly/SpiUart.h
simply move the uartConnected()
and configureUart()
above the private
keyword:
...
void ioSetState(unsigned char bits);
void configureUart(unsigned long baudrate);
boolean uartConnected();
private:
void writeRegister(byte registerAddress, byte data);
...
Now, we can go back to the good old SpiUartTerminal.pde
; except now we'd need to modify the connection procedure in setup()
as such:
...
Serial.println("Attempting to connect to SPI UART...");
SpiSerial.begin(); //hack in SpiUart.cpp so it don't lock
// hack below: repeat configuration until it passes
while(!SpiSerial.uartConnected()){
SpiSerial.configureUart(9600);
}
// end hack
Serial.println("Connected to SPI UART.");
...
Finally, with these changes, I could see SCLK pulses immediately after upload; and of course, the entire connection procedure passed - and I could execute the WiFly commands and connect to a wireless router as described in WiFly Tutorial - Wireless SpeakJet Server - SparkFun Electronics. (Note I had to change my router from WEP 64 bit to WEP 128 bit, as that is the only WEP WiFly supports; and then there is difference between key/passphrase command). Here tested telnet
wireless access via SpiUartTerminal.pde
, worked fine.
With this done, I also tried the Examples/WiFly/WiFly-examples/WiFly_WebServer
, which samples analog inputs and sends them to a client over wireless - the good thing is that the above SpiUart.cpp
hack seems to propagate to the WiFly
class as well; unfortunately, I couldn't measure more than 2.7 kByte/sec transfer speed over wireless, even with specifying WiFly.configure(WIFLY_BAUD, 38400);
.
In any case, glad I could get this to run - so hope this writeup would be of use to others ,
Cheers!