Electron Signal Strength LED Algorithm

Hello,

I’m building a IoT device that will work indoors and I use an Electron for connectivity.

The Electron has a handy feature, where if you press the ‘mode’ button once it’s breating blue it will flash the signal strength in a series of green lights

https://docs.particle.io/guide/getting-started/start/electron/#display-signal-strength-
“The signal strength (RSSI) will be shown in a 0-5 green blinks, 5 being the strongest”

I need to reproduce this logic using 5 LEDs on my device, so that a user can visually see the indoor signal strength as they move the device around and decide where best to place it (i.e. so they can place it with someplace with a strong signal)

Getting the RSSI via the firmware/user app API is easy:
https://docs.particle.io/reference/firmware/electron/#rssi-

But can you please let me know what Algorithm/logic you use to translate the RSSI returned via the API into a 1-5 scale? so I can mirror the built-in, “mode” feature in my own 5 LED setup. I’d like to mirror this exactly so I’m confident in the logic.

Do you use the “qual” as well in your Algorithm?

Thanks very much,

Mark.

The easiest would be to map the range via tha map() function.

Give this a shot

  int strength = map(RSSI, -131, -51, 0, 5);

You may have to tweak the boundaries (-131/-51) a bit to get the mid point of each category right.

And this is the code from the firmware repo

void system_display_rssi() {
    /*   signal strength (u-Blox Sara U2 and G3 modules)
     *   0: < -105 dBm
     *   1: < -93 dBm
     *   2: < -81 dBm
     *   3: < -69 dBm
     *   4: < - 57 dBm
     *   5: >= -57 dBm
     */
    system_prepare_display_bars();
    int rssi = 0;
    int bars = 0;
#if Wiring_WiFi == 1
    rssi = WiFi.RSSI();
#elif Wiring_Cellular == 1
    CellularSignal sig = Cellular.RSSI();
    rssi = sig.rssi;
#endif
    if (rssi < 0) {
        if (rssi >= -57) bars = 5;
        else if (rssi > -68) bars = 4;
        else if (rssi > -80) bars = 3;
        else if (rssi > -92) bars = 2;
        else if (rssi > -104) bars = 1;
    }
    DEBUG("RSSI: %ddB BARS: %d\r\n", rssi, bars);

    system_display_bars(bars);
}
7 Likes

Thank you very much @ScruffR
That will work perfectly for me :smile:

2 Likes

If anyone uses React then you may find this interesting. I’ve started building some React components that work off the particle API data.

My first component is called “RssiSignalStrength” and translates the built in logic into a nice UI. It also shows the signal strength as a RGB value (which you can mirror with a custom RGB LED on the board - it will be useful for remote trouble shooting)

I intend to build more Particle API driven React components as I’m building a admin panel for my project in React, so watch this space.

2 Likes

is there a way to do this with printing out the strength:

int rssi=0;
char str;
CellularSignal sig = Cellular.RSSI();
    rssi = sig.rssi;
void setup() {
 Time.zone(-4);
 Serial.begin(9600); 
}

void loop() {
    if (rssi<0)
{
    if  (rssi>=-70) str="Excellent";
    else if(rssi>=-70 && rssi >-85) str=("Good");
    else if (rssi>-86&& rssi >=-100) str=("Fair");
    else if (rssi>-100) str=("Poor");
    else if (rssi>-110) str=("No Signal");
  
}
Serial.println(Time.format(Time.now(), "%Y-%m-%d %H:%M:%S"));
Serial.println(str);
}

something like this ? this however is not working

What exactly is not working?
Apart from the obvious error of placing active code outside of any function :wink:

The CellularSignal sig = Cellular.RSSI(); is giving me an error so not even able to get to the loop on printing out the strength, I was also wondering if this can be done in a case instead of all the if’s. Any help is welcome, Thank You

Yes, and what is the exact error message - don’t withhold crucial info please

Understand did mean to, I did get the code to verify after fixing bunch of things
instead of trying to use char or arrays I just had it do a print out Serial.write for the different setting I wanted. Thank You tho for looking at it.

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

void loop()
{
  system_display_rssi();
}

void system_display_rssi() {
 
    int rssi = 0;
 
#if Wiring_WiFi == 1
    rssi = WiFi.RSSI();
#elif Wiring_Cellular == 1
    CellularSignal sig = Cellular.RSSI();
    rssi = sig.rssi;
#endif
    if (rssi < 0) {
    if  (rssi>=-70){Serial.write("Excellent"); }
    else if(rssi>=-70 && rssi >-85) {Serial.write("Good");}
    else if (rssi>-86&& rssi >=-100) {Serial.write("Fair");}
    else if (rssi>-100) {Serial.write("Poor");}
    else if (rssi>-110) {Serial.write("No Signal");}
    }
}

The logic here will not work as you expect; the first else-if statement will never be executed. If rssi >= -70, the if statement will run, so the else-if statement will never be reached. The other conditions aren’t correct either. For instance, if rssi == -71, you would want the result to be “Good”, but given your logic, it would print “Fair”. You don’t need to “AND” any of the conditions together, you only need one condition for each statement. Something like this should do,

if (rssi < 0) {
    if  (rssi >= -70) {
        Serial.write("Excellent"); 
    }else if(rssi >= -85) {
        Serial.write("Good");
    }else if (rssi >= -100) {
        Serial.write("Poor");
    }else {
        Serial.write("No Signal");
    }
}
2 Likes

I can’t get my sketch to compile and I wondered if I need to add additional libraries for ‘system_display_bars’?

Would it be possible to display the Strength using an I2C 16x2 LCD Display using the lcd.print (char…) after defying the 5 chars? I’m not sure how this line displays the data, DEBUG(“RSSI: %ddB BARS: %d\r\n”, rssi, bars);.
Thank you.

I’m getting the following errors:
signalstrength.ino:69:29: error: ‘system_display_bars’ was not declared in this scope
system_display_bars(bars);
^
signalstrength.ino:66:9: warning: unused variable ‘strength’ [-Wunused-variable]
int strength = map(rssi, -131, -51, 0, 5); // was RSSI

// Manually added, not in Library
#include "Particle.h"

void setup() {
      
  Serial.begin(9600);
//    int rssi = 0;
//    int bars = 0;
}

void loop()
{
  
  system_display_rssi();
}
    /*   signal strength (u-Blox Sara U2 and G3 modules)
     *   0: < -105 dBm
     *   1: < -93 dBm
     *   2: < -81 dBm
     *   3: < -69 dBm
     *   4: < - 57 dBm
     *   5: >= -57 dBm
     */

void system_display_rssi()
{
    system_prepare_display_bars();
    int rssi = 0;
    int bars = 0;

#if Wiring_WiFi == 1
    rssi = WiFi.RSSI();
#elif Wiring_Cellular == 1
    CellularSignal sig = Cellular.RSSI();
    rssi = sig.rssi;
#endif
    if (rssi < 0)
    {
        if (rssi >= -57) bars = 5;
        else if (rssi > -68) bars = 4;
        else if (rssi > -80) bars = 3;
        else if (rssi > -92) bars = 2;
        else if (rssi > -104) bars = 1;
    }
    int strength = map(rssi, -131, -51, 0, 5); // was RSSI
    DEBUG("RSSI: %ddB BARS: %d\r\n", rssi, bars);

    system_display_bars(bars);
}

You need that function declared and implemented in your code.

The one in the code snippet I quoted above is only accessible to the system.