Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firmware Hard Fault crash with WiFi.scan callback class example #1062

Closed
kasperkamperman opened this issue Jul 14, 2016 · 4 comments · Fixed by #1354

Comments

@kasperkamperman
Copy link

commented Jul 14, 2016

Running the class to find the strongest AP example from the WiFi.scan documentation gives a Hard Fault crash.

This happens in SYSTEM_MODE(MANUAL);

I run firmware 0.5.1 on Particle Photon. I program and compile offline (DFU).
I have stored credentials for a Wi-Fi network that is unreachable (test case to write code to do the right thing when an access point is unavailable).

Adding a delay of 800ms to the end of the setup() function will solve the issue.

Test Case code:
https://gist.github.com/kasperkamperman/77d9c941f07ac05e78e4d400c96e5113

See also this post in the community forum:
https://community.particle.io/t/wifi-scan-callback-in-a-class-crash-with-system-thread-enabled/24372/4


Completeness:

  • Minimum test case added
  • Device, system and user firmware versions stated
@m-mcgowan

This comment has been minimized.

Copy link
Contributor

commented Sep 13, 2016

Could you try this against 0.5.2 please since there were some fixes that may relate to this. Thanks!

@kasperkamperman

This comment has been minimized.

Copy link
Author

commented Sep 14, 2016

I've tested it with 0.5.2 however it still gives the hard fault firmware crash.

@technobly

This comment has been minimized.

Copy link
Member

commented Feb 7, 2017

@kasperkamperman it turns out the issue was because your example was using MANUAL mode, and the Docs example doesn't completely show you all of the code (it assumes AUTOMATIC mode).

If you account for that, the reason the delay is necessary is to allow the Particle.connect() call to turn on the WiFi radio and start the connection to the WiFi access point before the WiFi.scan() is run for the first time.

  • WiFi.scan() should probably return 0 if !WiFi.ready();
  • The example in the Docs also doesn't seed strongest_rssi with a large negative value to allow it's bubble sort algorithm to work properly.

Here are a couple code examples:

#include "application.h"

//SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);

class FindStrongestSSID
{
    char strongest_ssid[33];
    int strongest_rssi;

    // This is the callback passed to WiFi.scan()
    // It makes the call on the `self` instance - to go from a static
    // member function to an instance member function.
    static void handle_ap(WiFiAccessPoint* wap, FindStrongestSSID* self)
    {
        self->next(*wap);
    }

    // determine if this AP is stronger than the strongest seen so far
    void next(WiFiAccessPoint& ap)
    {
        if ((ap.rssi < 0) && (ap.rssi > strongest_rssi) && (ap.ssid[0] != '\0')) {
            strongest_rssi = ap.rssi;
            strcpy(strongest_ssid, ap.ssid);
        }
    }

public:

    /**
     * Scan Wi-Fi Access Points and retrieve the strongest one.
     */
    const char* scan()
    {
        // initialize data
        strongest_ssid[0] = '\0';
        strongest_rssi = -999;
        // perform the scan
        WiFi.scan(handle_ap, this);
        return strongest_ssid;
    }
};

// Now use the class
FindStrongestSSID strongestFinder;
const char* ssid;

void setup() {
    Serial.begin();
    delay(5000);
    // necessary to turn on Wi-Fi in MANUAL and connect and wait for Wi-Fi ready in SEMI_AUTOMATIC
    WiFi.on();
    WiFi.connect();
    waitUntil(WiFi.ready);
}

void loop() {
    ssid = strongestFinder.scan();
    Serial.printlnf("BEST SSID: %s", ssid);
    delay(10000);
}

and

WiFiAccessPoint results[20];
char strongest_ssid[33];
int strongest_rssi;
bool scanit;

void scanStrongest() {
    scanit = true;
}

Timer scan(10000, scanStrongest);
    
void setup() {
    scan.start();
}

void loop() {
    // Every 10 seconds scan for the strongest SSID
    if (scanit) {
        scanit = false;
        int found = WiFi.scan(results, 20);
        strongest_ssid[0] = '\0';
        strongest_rssi = -999;
        for (int i=0; i<found; i++) {
            WiFiAccessPoint& ap = results[i];
            if (ap.ssid[0] != '\0') Serial.printlnf("SSID: %s (%d)", ap.ssid, ap.rssi);
            if ((ap.rssi < 0) && (ap.rssi > strongest_rssi) && (ap.ssid[0] != '\0')) {
                strongest_rssi = ap.rssi;
                strcpy(strongest_ssid, ap.ssid);
            }
        }
        Serial.printlnf("\r\nBEST SSID: %s (%d)\r\n", strongest_ssid, strongest_rssi);
    }
}
@kasperkamperman

This comment has been minimized.

Copy link
Author

commented Feb 14, 2017

Clear, thanks for diving into this.

@avtolstoy avtolstoy referenced this issue Jul 10, 2017
5 of 6 tasks complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.