No signal strength information for Electron 2G on Device OS 1.0.0

Tags: #<Tag:0x00007f1ca2112630>


I have a 2G Electron (with the ublox SARA-G350 module) running Device OS 1.0.0 and I am unable to get the cellular signal strength information. The problem manifests itself in two ways:

  1. The radio access technology variable returned by the CellularSignal class is 0 (which stands for NET_ACCESS_TECHNOLOGY_UNKNOWN or NET_ACCESS_TECHNOLOGY_NONE). This causes getStrength() and getQuality() to return -1.0 and getStrengthValue() and getQualityValue() return 0.0.

  2. The rssi member variable of Cellular.RSSI() is set to 1 „indicating a Cellular module or time-out error“.

The test code I ran was this:

void setup()
    CellularSignal sig = Cellular.RSSI();
    int rat = sig.getAccessTechnology();

    char accessTechText[8];
    snprintf(accessTechText, 8, "%i %i", rat, sig.rssi);

    Particle.publish("Access technology", accessTechText, 0, PRIVATE);

void loop()


and this is the output I get:

event: Access technology
data: {"data":"0 1",<removed>}

additionally I noticed that the spark/device/diagnostics/update diagnotics event reports:


I have previously been using the rssi variable of Cellular.RSSI() successfully on 0.7.0 but only noticed this regression after I updated to 1.0.0. I have been unable to downgrade from 1.0.0 to find out exactly which version broke this functionality. I am using a Particle SIM card.

I was unable to find anything about this on the forum or the Github issue tracker. I wanted to post this here to confirm that this is a bug before filing an issue on Github. I’m also open to any workarounds until a fix is released.


Check the firmware updates thread, I believe there was a change in the way RSSI is used for 1.0.0.


Thanks for the suggestion. The 1.0.0 release does have a notice about changes to WiFi.RSSI() but it specifically mentions that “Electron is not affected”. The changelog also mentions “Network Signal Quality/Strength rework and diagnostics #1423” which might have something to do with the regression.

I guess I’ll just file a bug report and hope a fix makes it in time for the next release. Until then I’d love any suggestions for a workaround. I’m deploying a device in the field this week and it would be really beneficial to have some indication of signal strength so I can choose between two types of antennas.

I just tested Device OS 1.0.1-rc.1 and have verified that the bug is still present.


I am stuck with the same problem.
I contacted Particle but they don’t seem very interested/concerned in the problem or the fact they they broke one of their apis which is a bit worrying. They talked about a fix for version 1.0.2 but who knows.

I am really interested in a workaround for this so if anyone has any ideas!


TL,DR; This issue is fixed in Device OS v1.0.1

I’ve been digging into this issue and found a reliable way to reproduce it:

  1. Use v1.0.0 firmware
  2. Power off completely
  3. Power up and only turn on the modem initially
  4. Wait a bit (20s LTE, 60s 2G/3G to be sure) and let the modem automatically register to the network in the background
  5. Particle.connect() now, or Cellular.connect() to cause the system to go through the registration process.
  6. It should see that it’s already registered and not run *REG=2 which will later cause the RSSI command to fail return 1.
  7. Successive hard/soft resets of the STM32 and skipping step 4 will not clear this issue.

Example app to reproduce on v1.0.0 (running the same app on v1.0.1 will not show this RSSI=1 issue)

#include "Particle.h"
SerialLogHandler logHandler(LOG_LEVEL_ALL);

void setup()

void loop()
    static uint32_t lastUpdate;
    if (Cellular.ready() && millis() - lastUpdate > 5000UL) {
        lastUpdate = millis();
        CellularSignal sig = Cellular.RSSI();
        int rat = sig.getAccessTechnology();
        bool pgd = PMIC().isPowerGood();
        char rssiTest[32];
        snprintf(rssiTest, 32, "RAT:%d RSSI:%d QUAL:%d PGD:%d", rat, sig.rssi, sig.qual, pgd);
        Serial.printlnf("%s", rssiTest);
        if (Particle.connected()) {
            Particle.publish("rssi-test", rssiTest, PRIVATE);

The issue stems from this response:

     1.145 AT send      11 "AT+CEREG?\r\n"
     1.157 AT read  +   15 "\r\n+CEREG: 0,1\r\n"
     1.167 AT read OK    6 "\r\nOK\r\n"

When it should look like this:

   115.198 AT send      11 "AT+CEREG?\r\n"
   115.206 AT read  +   34 "\r\n+CEREG: 2,1,\"1234\",\"1234567\",8\r\n"
   115.208 AT read OK    6 "\r\nOK\r\n"

Root Cause of the problem

  1. In 0.8.0-rc.x we changed the Cellular.RSSI() API to calculate the correct RSSI in dB based on the type of RAT (Radio Access Technology) we are currently registered to the cellular tower with.
  2. Later in 0.8.0-rc.x we introduced LTE support and refactored a bunch of the mdm_hal.cpp firmware.
  3. By optimizing some code in mdm_hal.cpp it opened up a corner case that prevented the verbose URC response of +CEREG from being returned, which contains the RAT we are currently connected to.
  4. If the modem is power cycled and allowed to register before the Device OS knows about it (the modem does this registration with the tower automatically), Device OS firmware will initially see it’s already registered and never issue the AT+CEREG=2 command for LTE (or AT+CREG=2 / AT+CGREG=2 for 2G/3G).
  5. Because we don’t get the verbose CEREG: response which contains the RAT, even though we have a valid RSSI value, we error out of converting the RSSI into a proper dB value and return RSSI=1 error case.


Unconditionally issue AT+CEREG=2 for LTE (etc… for 3G/3G) upon registration
This has been fixed in v1.0.1 here:

Other causes of RSSI=1

You still may temporarily see RSSI=1 while you have no cellular signal. Right now the Cellular.API() will return 1 for most most cases (AT timeout or the modem is returning 99 for RSSI). It will return 0 if Cellular.ready() is false, but should return 2 if the modem is returning 99 for RSSI (this needs to be fixed still but it shouldn’t cause any problems). If AT commands are failing due to a bug where AT+USOST is used while there is no signal, the Cellular.RSSI() command will temporarily and legitimately return RSSI=1.

U260 vs E402 RSSI, E402 returns 1

I would love to hear your thoughts on this if it appears fixed for you in v1.0.1 @Gudmundur @ArthurGuy @wesner0019


I am pretty sure it wasn’t fixed in 1.0.1.

Although version 1.0.1 has broken the startup connect sequence (permanent listening mode) so I am not going to be touching that version again I am afraid!


Do you have a test app that reliably reproduces the issue for you?

Is this issue posted somewhere in more detail? I’m definitely very interested to know more here.


The easiest way to see if its still an issue is to use the built in diagnostics on the web console, the returned data packet has the signal strength data which is all -1’s.
I have been in contact with support about this issue and they think 1.0.2 will fix it in a few weeks.

The listening mode issue can be reproduced by turning an electron on! Most of the time it will enter listening mode and get stuck.


1.0.2.-rc.1 is now going to be 1.1.0-rc.1 due to observing SemVer 2.0.0 rules properly.

The easiest way to see if its still an issue is to use the built in diagnostics on the web console, the returned data packet has the signal strength data which is all -1’s.

The issue that most have reported is CellularSignal sig = Cellular.RSSI() returns sig.rssi = 1 which was a different issue for E402, U260, U270, U201 as I mentioned above is resolved in v1.0.1. Here are some results of v1.0.1 and tinker on various devices checked in Console.






I tried a 2G device as well since that’s what you reported to the support team, and I can confirm the -100 err values. It would also report sig.rssi = 1 but for a similar but different root cause (see below).


The G350 has this issue because it does not report the RAT (aka AcT) in the CGREG, CREG and COPS URCs as they are not supported on the G350:

   187.907 AT send      10 "AT+COPS?\r\n"
   187.945 AT read  +   25 "\r\n+COPS: 0,0,\"T-Mobile\"\r\n"
   200.808 AT read  +   28 "\r\n+CREG: 2,5,\"1234\",\"1234567\"\r\n"
   200.819 AT read OK    6 "\r\nOK\r\n"
   200.819 AT send      11 "AT+CGREG?\r\n"
   200.855 AT read  +   29 "\r\n+CGREG: 2,5,\"1234\",\"1234567\"\r\n"
   200.865 AT read OK    6 "\r\nOK\r\n"

Perhaps we can default to RAT = ACT_GSM for G350 to resolve this issue. I’ll test this out and if it looks good I’ll pull this fix into v1.1.0-rc.1.

With this change I can now see this result for G350:

Just for completeness, if you are wondering what the "at":x lookup is, here is the enum used in Device OS:

typedef enum {
} hal_net_access_tech_t;

@ArthurGuy if you would like to test this fix for your G350 (or other devices) I would appreciate it:

Just use the Particle CLI to flash this patched v1.0.1 Device OS firmware as follows:

particle flash --usb system-part1-1.0.1-electron-g350-rssi-fix.bin
particle flash --usb system-part2-1.0.1-electron-g350-rssi-fix.bin
particle flash --usb system-part3-1.0.1-electron-g350-rssi-fix.bin

It should work with any less than or equal to v1.0.1 compiled app.

Since 0.6.1 we have had a default 5 minute timeout for Listening Mode on Electron. This is helpful for cases where the SIM card is loose and not making good contact on power up. Please check your SIM contacts and see if any appear to be lower than the rest (it’s very possible to bend these accidentally with these development boards). The E Series modules have an embedded SIM (a chip soldered to the PCB) to make this more robust. Another thing you can do to tighten up the contacts is remove the SIM, and press the metal band down with your thumbnail right in the middle forming a slight V. Re-insert the SIM and it should be tighter now.


Thanks for the updated firmware, I will give this a go tomorrow and report back.

The listening mode definitly isn’t a hardware problem, changing versions from 1.0.1 to 1.0.0 fixed it instantly.
But tomorrow’s test will allow me to double check this.


@BDub i sometimes still see the RSSI = 1 on occasion. I’ve seen it where its that for a few seconds then it gets resolved and works as normal. Sometimes (now) pretty rare where it stay stuck on RSSI = 1 but I have recovery code to look for this if it lasts longer than 90 seconds the modem does a hard reset by holding the reset pin low on the module for ~12 seconds. After the hard reset the modem recovers and connects as normal

Im not sure what the cause of the RSSI =1 is in the above cases and it could be a legit cause. Just my observations so far.

void hardResetRestart() {
  if (inHardReset && millis() - hardResetMillis > 15000) {
    pinMode(RESET_UC, OUTPUT);
    digitalWrite(RESET_UC, HIGH);
    inHardReset = false;
    //serialDebug("hr start");



The patched 1.0.1 firmware fixes the signal strength issue!

Sadly the listening bug is still there. Blue pulsating followed by blue flashing until the internal timer kicks in presumably.
If the device has been successfully connected and is then reset it normally works but if its been in standby or powered off for a few seconds then it often ends up stuck in this mode. Sometimes it will recover but from the connection data this can take quite a while.

The length of time it spends pulsating white when turned on also varies a lot which seems rather odd but this is unrelated to the listening bug.

The only user code running on the electron is a delay of 30 seconds followed by a sleep of 5 minutes.

It’s a very intermittent and hard to pin down problem but it is software based as downgrading to 1.0.0 fixes it.


This does sound like a typical RSSI signal strength dropout issue. Is your device mobile or is there a chance for random interference by something like a large truck blocking a normally weak signal temporarily?

I would love to see some device logs of this case to see if the AT+CSQ and AT+CEREG? results are still working properly when you experience this. What device is this on as well?

You can enable full device logs over serial with this line added globally:

SerialLogHandler logHandler(115200, LOG_LEVEL_ALL);

That’s great news :slight_smile: Thanks for testing.

This is definitely the dark blue and not the cyan blue color when it’s connecting to the Cloud? Logs in your case here would also be helpful (see above).

If this is also the G350 device, the power requirements here are much higher than any other device (3G / LTE). One thing you can try to isolate some power issues is run the device off of battery only, completely disconnected from USB. When it’s plugged into USB and running on battery, the power will be supplied by the USB input and switch over to battery if the USB browns out. Obviously this will be hard to capture logs this way, but maybe try both… logs while connected to USB, and also observe what it does when you power off completely and just plug in the battery. If you want to try logging from the TX pin while it’s on battery only, you can try this line:

Serial1LogHandler logHandler(115200, LOG_LEVEL_ALL);

Sounds easy enough, but could you provide the exact code so I know exactly what sleep mode and parameters you are using?


thanks @BDub for the patched firmware. I had to port a Boron application back to electron 2G and I was annoyed with rssi=1 until I found this post. I confirm that it works as expected.
Let me also use the opportunity to share a snapshot of the (beaten up) Electron --> Feather adapter that I assembled so I can replace a Boron LTE by an Electron 2G in my tracker+info display system during a trip. I also had to solder a micro USB break-out since the one on the Electron broke few months ago.