Testing boolean return value from function

I have a library that I need to modify, its the WiflyHQ library in the open method.

The wifly gets stuck from time to time and cannot get a prompt. When it tries to open, it fails and logs out that it has crashed and must be rebooted. It never reboots by itself so I decided to first try adding the line:

reboot();

which you see in the bold red letters commented out, but that didnt work apparently. So I've decided to test the condition in my sketche's loop function.

So I added this:

if (wifly.promptFailed==false) {
    Serial.println("wifly didnt open, will reboot it...");
    wifly.reboot();
  }

but I get this error on compiling:

TimeAlarmCO2WiFiPost.ino:69:13: error: within this context
Error compiling.

Ive declared the boolean in the WiflyHQ.h file like this:

boolean promptFailed;

Why cant I do this?

boolean WiFly::open(const char *addr, uint16_t port, boolean block)
{
    char buf[20];
    char ch;

    if (connecting) {
	/* an open is already in progress */
	return false;
    }

    startCommand();

    /* Already connected? Close the connection first */
    if (connected) {
	close();
    }

    simple_utoa(port, 10, buf, sizeof(buf));
    debug.print(F("open ")); debug.print(addr); debug.print(' '); debug.println(buf);
    send_P(PSTR("open "));
    send(addr);
    send(" ");
    send(buf);
    send_P(PSTR("\r"));

    if (!getPrompt()) {
	debug.println(F("Failed to get prompt"));
	debug.println(F("WiFly has crashed and will reboot..."));
	[b]//Add reboot code
	//reboot(); Didn't work for some reason
	promptFailed = false;[color=red][/color][/b]
	while (1); /* wait for the reboot */
	return false;
    }

    if (!block) {
	/* Non-blocking connect, user will poll for result */
	connecting = true;
	return true;
    }

    /* Expect "*OPEN*" or "Connect FAILED" */

    while (readTimeout(&ch,10000)) {
	switch (ch) {
	case '*':
	    if (match_P(PSTR("OPEN*"))) {
		DPRINT(F("Connected\n\r"));
		connected = true;
		/* successful connection exits command mode */
		inCommandMode = false;
		return true;
	    } else {
		finishCommand();
		return false;
	    }
	    break;
	case 'C': {
		buf[0] = ch;
		gets(&buf[1], sizeof(buf)-1);
		debug.print(F("Failed to connect: ")); debug.println(buf);
		finishCommand();
		return false;
	    }

	default:
	    if (debugOn) {
		debug.print(F("Unexpected char: "));
		debug.print(ch,HEX);
		if (isprint(ch)) {
		    debug.print(' ');
		    debug.print(ch);
		}
		debug.println();
	    }
	    break;
	}
    }

    debug.println(F("<timeout>"));
    finishCommand();
    return false;
}
1 Like

I do not have the wifly library, and you didnt include a link to it or the actual library name, not its class/method - so I am guessing.

If promptFailed is a method then you must use the "()" after it. -

if (wifly.promptFailed()==false) {
    Serial.println ...
}

Quite apart from that if you have a function/method return a boolean the way to us it is

if ( function() ) { things if true }

or if you need the opposite

if ( ! function() ) { things if false }

The "==" operator expects two values, one on either side and will return a boolean

The library is here:

promptFailed is a boolean property I added, not a function.

The method is wifly.open() and I did try it as:

If (!wifly.open())...

But it asked me for its 3 arguments.

No, that's the whole message I got.

I posted the link to the library and since I only added a property declaration in the.h file and 1 line in the.cpp like I said, I didn't see the need to post the thousands or so lines of the wiflyhq.cpp file.

I tried posting the whole h and cpp file but I can't because it's too long a file.

Ok here is what I did. I marked them in red. I tried 2 things:

FIRST

  1. Tried calling reboot from the library itself when that error ocurred by adding the reboot line by itself.

That doesnt seem to work. It keeps crashing and I havent been able to get it to crash while connected to the computer. Actually it was connected to the computer when I tried it but the serial monitor stopped logging after a while and it stopped logging after about 5 samples. The module crashed at about the 12th sample

  1. Adding a boolean flag and checking for it in my sketches loop method.

I just scrolledup to see the whole error:

In file included from TimeAlarmCO2WiFiPost.ino:6:0:
/Users/quique123/Documents/Arduino/libraries/WiFlyHQ/WiFlyHQ.h: In function 'void loop()':
/Users/quique123/Documents/Arduino/libraries/WiFlyHQ/WiFlyHQ.h:332:13: error: 'boolean WiFly::promptFailed' is private
boolean promptFailed; //Added by me Oct 30 2015
^
TimeAlarmCO2WiFiPost.ino:69:13: error: within this context
Error compiling.

WiflyHQlib.txt (85.6 KB)

Ok, I've moved the boolean to the public section. Now here is a related issue which affects this one.

As you noticed, I had tried placing the reboot(); line in the library file itself, wiflyhq.cpp exactly where the code logs the line that it has crashed and must be rebooted. I just got confirmation that the code is run and the reboot function is called but the module doesnt seem to reboot. I got this in the serial monitor:

Failed to get prompt
WiFly has crashed and will reboot...
rebooting...

where the first two lines are from the wifly::open() method and the 3rd and last line is from a comment I added at the beginning of the wifly::reboot() method as shown here:

/** Reboots the WiFly.
 * @note Depending on the shield, this may also reboot the Arduino.
 */
boolean WiFly::reboot()
{
    debug.println(F("rebooting..."));
    if (!startCommand()) {
	return false;
    }
    send_P(PSTR("reboot\r"));
    if (!match_P(PSTR("*Reboot*"))) {
	finishCommand();
	return false;
    }
    delay(5000);
    inCommandMode = false;
    exitCommand = 0;
    init();
    return true;
}

Im thinking this means the boolean code will be called but the shield will not reboot anyway.

This should mean there is something wrong with the module itself, right?

I have another idea, but I need your input. If I have the Arduino reset itself using the wdt, does that "power cycle" the arduino? Because if so, that might be equivalent to hitting the reset button on the wifly module seeing as how the actual wifly.reboot() doesnt work.

So I was thinking of adding the code in the setup():

wdt_enable(WDTO_8S);

and this code in the loop somewhere. Perhaps in the test for the boolean flag I had before like so:

void  loop(){  
  Alarm.delay(10); // wait one second between clock display
  if (wifly.promptFailed==false) {
    Serial.println("wifly didnt open, will reboot it...");
    wdt_reset();  //pat the dog
  }
}

does that "power cycle" the arduino

No.

OK, is there a way to power cycle the Arduino from code?

So I guess I have to cross my fingers and hope using wdt or something I found called software_Reset() to see if this will do anything to the WiFi module.

At the moment I'm running other tests to see if instead of rebooting, perhaps closing and reopening my connection will un-hang the WiFi module.

I don't have any experience with the WiFly but from my experience with the W5100 and Ethernet library you could toggle the WiFly Reset pin low for >160us(from the datasheet) with an Arduino pin and then call wifly.begin() or whatever other initialization is needed. If you do a wdt reset of the Arduino first and then a reset of the WiFly that should be just as good as a full power cycle.

Ok that sounds promising. From what I saw, the ic has its reset at pin 40, but it translates to pad position #5?

To set it to low I would have to write LOW to it, but how do I do it for 160us? Just add a delay of about 200uc after the write low call?

How would I simply set it back to what it was?

Ok im looking into this writing LOW to pin. I can see it is pin 5 on the wifly pad. But that module is connected to a shield in my case:

but I dont understand how to access pin 5 of the module (red pcb) from the shield connected to my UNO (blue pcb). What am I missing here?

A jumper wire, perhaps ?

If I understand the schematic correctly it looks like that shield connects the wifly reset to the arduino reset. Not very helpful for this case. The easiest solution would be to bend the reset pin of the shield so that it misses the Arduino header and then connect a jumper wire(female to male) to the header on the shield for the Arduino pin you want to use to reset the wifly. The problem with this is that then the reset button on the shield will no longer reset the Arduino(should still reset the wifly though) and the shield covers the reset button on the Arduino but that may or may not be an issue for you.

Q1/ Wait, so you're saying that tapping the wifi shield's reset button resets the arduino because its connected to the arduino's reset pin?

Q2/ If that's the case then wouldnt it be easier to just reset the arduino in code? Or does that not work both ways> :slight_smile: , meaning that resetting the Arduino in code doesnt "translate" that reset to the wifi shield reset, does it?

Q3/ Not too fond of bending. What about connecting a pin from the headers on the shield to pin5 on the wifi module?

Q4/ Otherwise I guess I could test resetting the Arduino in addition to rebooting the wifi module. Im thinking that maybe the wifly.reboot() function which sends the reboot\r to the wifi module could be sending it that command but maybe the Arduino needs to be reset as well and perhaps the reboot() only reboots the wifi and not the Arduino.

Marciokoko:
How would I simply set it back to what it was?

The wifly module has a 100k pull-up on the reset pin so you can also change the pinMode to INPUT if you want after the reset is complete. This is my code for resetting my Ethernet module:

void W5x00reset() {
  pinMode(pinW5x00reset, OUTPUT);
  digitalWrite(pinW5x00reset, LOW);
  delayMicroseconds(W5x00resetDuration);
  pinMode(pinW5x00reset, INPUT);  //leave the pin floating because the W5x00 has its own pullup to 3.3v
  delay(ethernetBeginDelay);
  ethernetBegin();
}

Marciokoko:
Q1/ Wait, so you're saying that tapping the wifi shield's reset button resets the arduino because its connected to the arduino's reset pin?

It looks like from the schematic of the shield that pressing the reset button resets the Arduino and the wifly module at the same time. I could be wrong because the schematic is blurry.

Marciokoko:
Q2/ If that's the case then wouldnt it be easier to just reset the arduino in code? Or does that not work both ways> :slight_smile: , meaning that resetting the Arduino in code doesnt "translate" that reset to the wifi shield reset, does it?

No, resetting the Arduino in code will not change the state of the reset pin

Marciokoko:
Q3/ Not too fond of bending. What about connecting a pin from the headers on the shield to pin5 on the wifi module?

You still need to disconnect the Arduino reset from the wifly reset because you don't want the Arduino pin pulling the Arduino reset LOW. You cut the reset trace on the shield or disconnect the pin 5 of the wifly module from the shield header.

Marciokoko:
Q4/ Otherwise I guess I could test resetting the Arduino in addition to rebooting the wifi module. Im thinking that maybe the wifly.reboot() function which sends the reboot\r to the wifi module could be sending it that command but maybe the Arduino needs to be reset as well and perhaps the reboot() only reboots the wifi and not the Arduino.

It really depends on the cause of the issue. I find that with the W5100 usually just calling Ethernet.begin() will get it working again. Toggling the W5100 reset pin is just a last resort to make sure I will always have a connection.

Actually looking at the schematic zoomed in I'm thinking the reset button may only reset the Arduino and maybe the wifly reset is not connected to any pin. You could test this with a multimeter continuity test. If the wifly reset is not connected to any pin on the shield then you would probably need to solder to the pad 5 on the module.

Delta_G:
Write it HIGH again. If it wasn't LOW before there aren't too many options for what it could have been

The wifly reset pin is only 3.3V tolerant so if your Arduino is running at 5V I wouldn't recommend writing it HIGH. Instead, change pinmode to INPUT and let the wifly pullup set the pin to 3.3V as in my W5100 reset code above.