WiFi.RSSI(); Not updating?

Hi all,

I am trying to read my wifi signal strength and display it as it updates.

I find that i can read the strength on start up of my board, but it will not update as i move away from my router or get closer.

#include <SPI.h>
#include <WiFi.h>

char ssid[] = ""; //  your network SSID (name) 
char pass[] = "";    // your network password (use for WPA, or use as key for WEP)

WiFiServer server(12000);  //a higher port number given, not clashing with https

int status = WL_IDLE_STATUS;


void setup() 
{
  Serial.begin(9600);                       //Begins serial communication with the board

    if (WiFi.status() == WL_NO_SHIELD)       // check for the presence of the shield:
    {  
    Serial.println("WiFi shield not present"); 
    while(true);
    } 

 
  while ( status != WL_CONNECTED)       // attempt to connect to Wifi network:
    {    
    Serial.print("Attempting to connect to SSID: "); 
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);     // Connect to WPA/WPA2 network. Change this line if using open or WEP network:  
    delay(5000);                         // wait 5 seconds for connection:
    } 
  }

void loop() {
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Can anyone spot what im doing wrong?

(Apologies for my hacked up code, it's from a larger program)

Many thanks

You can add Serial.print() statements to the WiFi source, to see what is happening.

Thanks for the reply PaulS

I have this in my original code:

void loop() {
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Is this what you mean?

Is this what you mean?

No. I mean that you put similar statements in WiFi.cpp and wifi_drv.cpp, to learn what RSSI() is doing, and the functions it calls.

Thanks for the prompt reply again.

I still do not understand why this doesn't work, or where to go with it.

Could you suggest somewhere to learn about this? Searching WiFi.cpp hasn't brought up any 'nice' examples.

Sorry for my incompetence, I am not experienced with this.

Sorry for my incompetence, I am not experienced with this.

If you can't edit a library, and add
Serial.print("I got here...");
statements, or perhaps something just a bit more useful, then I don't see how you are going to use the RSSI information that you get, should you start getting correct information (assuming that you are not now getting correct information - a point I'm not willing to concede).

What makes you think that there is a problem? RSSI is not a measure of distance, so moving the receiver towards or away from the WiFi router is not necessarily going to cause a change in RSSI values.

Sorry I should have explained the reasoning beforehand.

I will transmit the signal strength to Processing, here I will produce a simple signal strength bar chart, similar to the ones you see on cell phones. Eventually this will go onto an android application.

I know my RSSI value is chancing since I am using an application on a android devise to show that the RSSI value is changing as I move physical locations.

You might want to put a second or so delay in the rssi reading loop, otherwise you may not be able to see what is being sent.

You might want to put a second or so delay in the rssi reading loop,

I have tried this and I still see no update.

If i reposition the wifi sheild further away from the router it does show a signal change if i manually restart the board.

I still cannot get the RSSI read to update within the program.

I still cannot get the RSSI read to update within the program.

Besides wishing, what are you doing?

The RSSI read does not update as i change physical locations from my router.

For example, the signal displayed in the serial monitor, from this code, does not change/update as i move a large distance away from the router (eg. 3 bricked rooms).

void loop() {
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
  delay(500);
}

But when i manually reset my board and wait for a reconnection the RSSI updates to a new value, to a more realistic value.

I'm assuming the program I have written does not tell the wifi board to make a new reading?

In response too:

Besides wishing, what are you doing?

I am wishing that the kind arduino community might be able to point out my error :-).

Thanks for your time PaulS.

I am wishing that the kind arduino community might be able to point out my error :-).

If there IS an error in your code, the only way to debug it is to modify the library to show what it is doing.

You seem unwilling to do that. I do not understand why.

you might want to search thru the below postings for similar issues and resolutions.

https://www.google.com/search?hl=en&as_q=rssi&as_epq=&as_oq=&as_eq=&as_nlo=&as_nhi=&lr=&cr=&as_qdr=all&as_sitesearch=http%3A%2F%2Farduino.cc%2Fforum%2F&as_occt=any&safe=images&tbs=&as_filetype=&as_rights=

I had the same problem, and while PaulS seems to think that updating the library is a piece of cake, I for one do not find it trivial. It calls 50 other files, and you're soon in a sticky and unwieldy situation. I mean, if it were so simple (like a hello world), wouldn't less people rely on libraries to get things done?

So sorry you had to endure his jabbings. Anyways, I found a workaround: add a "WiFi.begin(ssid, pass);" after (or before) assigning the rssi value in your loop.

void loop() {
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);

WiFi.begin(ssid, pass);
delay(1);
}

And for others with this problem, I am using a Leonardo board, with the WIFI shield model R3, a macbook running Arduino 1.0.4, and my blood type is A+.

Cheers.

In WiFi.cpp

int32_t WiFiClass::RSSI()
{
    return WiFiDrv::getCurrentRSSI();
}

In WiFiDrv.cpp

int32_t WiFiDrv::_networkRssi[WL_NETWORKS_LIST_MAXNUM] = { 0 };
int32_t WiFiDrv::getCurrentRSSI()
{
	WAIT_FOR_SLAVE_SELECT();

    // Send Command
    SpiDrv::sendCmd(GET_CURR_RSSI_CMD, PARAM_NUMS_1);

    uint8_t _dummy = DUMMY_DATA;
    SpiDrv::sendParam(&_dummy, 1, LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _dataLen = 0;
    int32_t rssi = 0;
    SpiDrv::waitResponseCmd(GET_CURR_RSSI_CMD, PARAM_NUMS_1, (uint8_t*)&rssi, &_dataLen);

    SpiDrv::spiSlaveDeselect();

    return rssi;
}

I guess there is no way to know if RSSI is kept up to date inside the WiFi chip/firmware so Paul's "find that line in library" is not working here. This is my frustration too. I can only trace things down to this layer right above the WiFi chip firmware. I have no way of knowing what happens in there. Don't ask me to learn a whole new environment just to understand the firmware.

But, you could put Serial.print() statements in the code, to find out where the code does or does not get to. At least then, when reporting a bug, you have a lot more information on what is happening/is not happening.

In this case there is not anything the OP could have printed other than the WiFi.RSSI(). The WiFi.RSSI() has one line of code, which calls another function. That function sends out an SPI command to ask for current RSSI. The rest is in the WiFi firmware. I really hate to see the Arduino team come up with zero documentation again on this expensive piece of toy that you can only use very lightly and not be able to depend on it seriously since there is no documentation of its complete even partial behavior. As a programmer, not knowing the complete behavior or a library is the biggest problem.

In this case there is not anything the OP could have printed other than the WiFi.RSSI().

Why not print "In getCurrentRSSI!", in getCurrentRSSI(). That would have, at a minimum, answered the question of whether getCurrentRSSI() was even called.

Then, one could go into the SpiDrv class, and see what waitResponseCmd() is doing. I'm sure that it calls a function specific to the GET_CURR_RSSI_CMD command. One could figure out what that function is doing.

Certainly it is not trivial to determine why WiF.RSSI() isn't updating, but it certainly beats just complaining. Even if one gets stuck, and can't determine the solution, providing more data is almost always better than providing less data.

Or maybe I'm just being too sensitive to the "it didn't work; fix it for me" posts.

All,

I was having the same problem and noticed the same thing. I have found two ways of handling this, but the below seems to be the best. I have to tip my hat to huckleberry for the great tip on the work around as it lead to my,... I guess you could call it, a solution. What I noticed from huckleberry's solution, however, is that it doubled my loop time, this is because the WiFi.begin(ssid,passphrase); calls other functions which impose multiple layers of delays. However, what I found is if you modify the wifi_drv.cpp to be the following:

int32_t WiFiDrv::getCurrentRSSI()
{
           
    startScanNetworks(); //<-This is all I added!
    WAIT_FOR_SLAVE_SELECT();

It will jog the wifi chip to get a new RSSI value. I don't think the originally programmed code that follows this change is actually functioning as intended, but it works with a minimal trade-off in performance. The other fix would be to replace the line I added above to be the setPassPhrase command found in the same file, but that requires a whole host of changes to store the pass phrase and it can just get ugly. I think this is cleaner, as far as workarounds go. I suspect the issue with this code is how the wifi chip handles the receipt of _dummy which is 0xFF. I don't think it does anything with it. One might want to play with getRSSINetoworks(uint8_t networkItem) function in the same class, but I haven't found a way to know or determine what parameter to pass it in the sketch file that would represent my network (It wants a freaking unsigned int?). Tips here would be appreciated, but only if someone KNOWS that the RSSI value is being updated. :stuck_out_tongue:

Hopefully, a proper fix will make it into the next release.

(BTW, I am using the mega2560rev3 with the WiFiShield in case that matters, but seeing this solution, I can't see how it would!)

Hope this helps!

WiFi.scanNetworks(); returns the number of visible networks
Each network can then be enumerated like so

Note: It's not really a network, it's an access point.

#include <LiquidCrystal.h>
#include <WiFi.h>

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);
char ssid[] = "myssid";
char password[] = "password";

void setup() {
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Setup...");

  if (WiFi.status() == WL_NO_SHIELD) {
    lcd.setCursor(0, 0);
    lcd.print("No Shield");
    lcd.setCursor(0, 1); lcd.print("Fatal stop!");
    while(true);
  }

}

void loop() {
  
  //try connect forever
  if (WiFi.status() != WL_CONNECTED) {
    doConnect();
  } 

  // net is connected
  while(WiFi.status() == WL_CONNECTED) {
    //get connected net
    uint8_t numNets = WiFi.scanNetworks();
    lcd.clear();
    lcd.setCursor(0, 0); lcd.print(WiFi.SSID());
    lcd.setCursor(13, 0); lcd.print(WiFi.RSSI());
    
    //enumerate all nets
    for (uint8_t thisNet = 0; thisNet < numNets; thisNet++) {
      lcd.setCursor(0, 1); lcd.print("                ");
      lcd.setCursor(0, 1); lcd.print(thisNet); lcd.print(" "); lcd.print(WiFi.SSID(thisNet));
      lcd.setCursor(13,1); lcd.print(WiFi.RSSI(thisNet));
      delay(1000);
    }
  }
}

void doConnect() {
  //attempt to connect to WLAN forever
  uint8_t tryNum = 1;
    
  do {
    lcd.setCursor(0, 0); lcd.print("Try connect     "); 
    lcd.setCursor(13, 0); lcd.print(tryNum++);
    WiFi.begin(ssid, password);
    delay(1000);
  } while (WiFi.status() != WL_CONNECTED);

}

Tips here would be appreciated, but only if someone KNOWS that the RSSI value is being updated. :stuck_out_tongue:

The RSSI number is valid immediately after the call to scanNetworks.
How long it remains valid...Most likely, until something changes or scanNetworks is called again.

Strange how perspectives differ though. I am primarily a network engineer who sometimes develops software.
I never assumed the the WiFi shield would update RSSI automagically.
Typically it an O/S scans for access points periodically, as a background service.
It just appears to happen automagically to an end user.

Arduino is more an API than O/S.
If you want to expend precious runtime, RAM and power
scanning for access points in the background,
you have to write the functionality yourself.