Can't Get CellularData to Work

I’ve had no trouble with most of the Electron examples and my own variation on the publish example works fine with various bits of data, but as soon as I tried to add CellularData I get “‘CellularData’ does not name a type” errors. Seems like the lib for this is not loaded but I can see no extra #includes required. What am I missing?

(Bonus question: is #including Particle.h actually necessary. I see it in a lot of examples but everything seems to work alright without it.)

#include "Particle.h"

const int voltOut = A5;
const int ldrPin = A0;
const int ledPin = 7; // This is your internal LED
const int led = D0; // This is where your external LED is plugged in. The other side goes to a resistor connected to GND.

CellularData data;

void setup() {
    pinMode(voltOut, OUTPUT); //supply 3.3v at pin A5
    pinMode(ldrPin, INPUT); //assign A0 as an input
    pinMode(ledPin, OUTPUT);    
    digitalWrite(voltOut, HIGH); //initialize A5 at 3.3v
    pinMode(led,OUTPUT); // Our LED pin is output (lighting up the LED)

void loop() {

  if (!Particle.connected()) {
      return;
  }

    digitalWrite(ledPin,HIGH);

    int value = (analogRead(A0) / 10); 
    
    FuelGauge fuel;
    float voltage = fuel.getVCell();
    int SoC = fuel.getSoC();
    CellularSignal sig = Cellular.RSSI();
    
    
		if (Cellular.getDataUsage(data)) {
    

    //Particle.publish("CID", String(data.cid), 60, PRIVATE);
    Particle.publish("TXS", String(data.tx_session) + "," + String(data.rx_session) + ", " + String(data.tx_total) + ", " + String(data.rx_total), 60, PRIVATE);
    //Particle.publish("RXS", String(data.rx_session), 60, PRIVATE);
    //Particle.publish("TXT", String(data.tx_total), 60, PRIVATE);
    //Particle.publish("RXT", String(data.rx_total), 60, PRIVATE);
    }
    
    //Particle.publish("ID", String(System.deviceID()), 60, PRIVATE);
    Particle.publish("Sig", String(sig), 60, PRIVATE);
    Particle.publish("V", String(voltage) + "," + String(SoC), 60, PRIVATE);  // Actual battery voltage and derived State of Charge
    Particle.publish("LDR", String(value), 60, PRIVATE);
    
    //delay(1000); //makes sure there is enough time to complete sending before turning cell off.

    digitalWrite(ledPin,LOW);
    
    //Cellular.off();
    System.sleep(SLEEP_MODE_DEEP, 6000); //sleep for 10 minutes
}

Are you sure you've got an Electron selected as build target?
What IDE are you using?

As long your code lives in an .ino file the Wiring preprocessor will add that #include "Particle.h" for you, so you won't need to include it again, but once you are writing a .h or .cpp file you need to include it yourself.


BTW: Your setup() is missing a closing curly brace.

As far as I know it’s set for Electron. I’m using Build and I assume just selecting your device configures Build appropriately. I havn’t seen any other way to set the target device. And it works fine, communicating everything else as long as the CellularData stuff is commented out.

Actually, I say everything works fine as it had been for a few days, calling in every 10 mins, but now it only seems to wake up randomly every hour or two. No doubts something dumb I’ve done but I can’t see it.

Thanks for the knowhow on Particle.h. I thought as much but wasn’t sure.

Could you provide a screenshot of the open target drawer of Build where you selected the Electron?
Maybe you’ve set an old firmware version as target which hadn’t got that feature implemented.

OK, so it looks like I have an old firmware revision? Is this too old for CullularData to work?

Yup, this definetly is too old.
I think it got introduced with 0.5.0, but best is to directly go for 0.5.1 now.

1 Like

OK, trying to figure out how. The docs and community seem to be missing an all-in-one how-to. I have the CLI loaded and can flash my scripts that way. But then I read about DFU and DFU mode. I followed the instructions here: https://docs.particle.io/guide/getting-started/modes/electron/#dfu-mode-device-firmware-upgrade- But the install instructions link seems to be about installing the CLI, which I’ve already done and the usage guide doesn’t seem to mention it. The firmware seems to be used interchangeably between the OS and scripts, so I am not sure which is being referred to. Can you point me in the right direction?

After MUCH hair pulling over the CLI (I thought we’d left those behind in the 80’s?) I finally figured out how to update the firmware, and whaddya know, the CellularData stuff works. But, here’s the weird thing, the Devices draw is still reporting that the firmware is 0.4.8. I actually removed the device from Particle completely and reconnected it (going through all the setup.particle.io routine). It even has a new name, but it’s still showing as 0.4.8. And also the little pink dot next to it shows it thinks it’s in safe mode. But, ignoring all that it seems to working well again with full functionality.

Hm that is weird–sounds like a bug. @suda, another one to add to the backlog for investigation :wink: ^

@JethroNull, if you are on Windows or OSx, you could use the updater apps. That would save you all the hassle with CLI and dfu_util and stuff, but having CLI is a good thing for other purposes too.

As for your wrong report in Build this is a known issue. The common workaround is to OTA flash a tiny dummy sketch targeting the old version. The success-report of this will inform Build of the new version. Next time you refresh the browser Build should show the updated version as on-the-device.

BTW:

command line tools are still the choice tools for quick and in-depth tasks :wink:
GUIs make frequent tasks easier but usually limit you to these frequent tasks, because adding all the bells an whistles for rarely (if at all by the common user) used options would just mean too much effort for too little return value.


@will, this is a known issue since 0.5.0-rc.1 was tested by the Elite crew!

@ScruffR, despite hours of Googling I never came across that updater app. Thanks for that. It failed to install, but that may be because I was instaling from my Google Drive, that seems to upset some installers. I’ll get back to that later.

On the utility of command lines… hmm, i think it’s more personal taste. I’ve been a hardware guy for 30+ years and so have to tinker with the firmware on a regular basis (but I’ll admit to not being a hardcore coder) and it’s only been in the last two or three years that I’ve seen the command line come back with such passion. Mostly I think because of the rise of Github, NPM and Node.js (all good things, don’t get me wrong). But their development seems to have also come about at the same time as younger programmers have got all nostalgic for text-based stuff, 8-bit games and so on. Or maybe they just see the value in the stuff us old folk threw away! :wink:

@ScruffR perhaps you could help me a bit more. Now I have the latest firmware, code compiles with Cellular Data and so on. But I am not getting the results from it that I would expect:

Most of the time I just get zeros. I understood that this was likely if you turned the cellular engine off or, maybe, went into deep sleep. But, currently, I am just running stop mode sleep. I am also moving the values into variables at the end of each call to be sent on the next, so I’m not trying to write out the used data values as I go.

Over the last few hours, I did have one transmission with values in but otherwise it always returns 0. I also have a trap in case the Cellular.getDataUsage(data) is not returning anything (sends all “2”). This is my current code:

Am I misunderstanding something?

const int voltOut = A5;
const int ldrPin = A0;
const int ledPin = 7; // This is your internal LED
const int led = D0; // This is where your external LED is plugged in. The other side goes to a resistor connected to GND.

int txsess, rxsess, txtot, rxtot;

CellularData data;

void setup() {
    pinMode(voltOut, OUTPUT); //supply 3.3v at pin A5
    pinMode(ldrPin, INPUT); //assign A0 as an input
    pinMode(ledPin, OUTPUT);    
    digitalWrite(voltOut, HIGH); //initialize A5 at 3.3v
    pinMode(led,OUTPUT); // Our LED pin is output (lighting up the LED)
}

void loop() {

  if (!Particle.connected()) {
      return;
  }

    digitalWrite(ledPin,HIGH);

    int value = (analogRead(A0) / 10); 

    FuelGauge fuel;
    float voltage = fuel.getVCell();
    int SoC = fuel.getSoC();
    CellularSignal sig = Cellular.RSSI();

    Particle.publish("Data", String(txsess) + "," + String(rxsess) + "," + String(txtot) + "," + String(rxtot), 60, PRIVATE);
    Particle.publish("Sig", String(sig), 60, PRIVATE);
    Particle.publish("V", String(voltage, 2) + "," + String(SoC), 60, PRIVATE);  // Actual battery voltage and derived State of Charge
    //Particle.publish("LDR", String(value), 60, PRIVATE);

     //delay(1000); //makes sure there is enough time to complete sending before turning cell off.  Maybe only necessary when using deep sleep or off?

    CellularData data;
    if (Cellular.getDataUsage(data)) {

        txsess = data.tx_session;
        rxsess = data.rx_session;
        txtot = data.tx_total;
        rxtot = data.rx_total;
    }
    else{
        txsess = 2;
        rxsess = 2;
        txtot = 2;
        rxtot = 2;
    }
    Cellular.resetDataUsage();

     digitalWrite(ledPin,LOW);

    //Cellular.off();
    //System.sleep(SLEEP_MODE_DEEP, 600); //sleep for 10 minutes
    System.sleep(D0,RISING,600);
}

One thing I noticed was here

void loop() {
  ...
    CellularData data;   // <--- this hides the global variable with the same name - just comment this line
    if (Cellular.getDataUsage(data)) {

        txsess = data.tx_session;
        rxsess = data.rx_session;
        txtot = data.tx_total;
        rxtot = data.rx_total;
    }
    else{
        txsess = 2;
        rxsess = 2;
        txtot = 2;
        rxtot = 2;
    }
  ...
}

You have one global variable data and then you declare a new local version of it, which will hide the global variable, so when you read data into data you’ll lose that info once you drop out of loop().
Just remove the “redeclaration”.

But I’ll still have to look at your code a bit closer.

1 Like

Good point. I’ll fix that, though that wouldn’t be causing the problem would it?

I don’t think it would, but was the first thing that popped into my :eyes:

I`ve stripped down your code a bit and do see some good looking readings

int txsess, rxsess, txtot, rxtot;

CellularData data;
FuelGauge fuel;

void setup() {
}

void loop() {
    if (!Particle.connected()) return;

    double voltage     = fuel.getVCell();
    double SoC         = fuel.getSoC();
    CellularSignal sig = Cellular.RSSI();
    

    if (Cellular.getDataUsage(data)) 
    {
        txsess = data.tx_session;
        rxsess = data.rx_session;
        txtot = data.tx_total;
        rxtot = data.rx_total;
    }
    else
    {
        txsess = 2;
        rxsess = 2;
        txtot = 2;
        rxtot = 2;
    }

    Particle.publish("Data", String::format("%4d, %4d, %4d, %4d, %.1fV, %.1f%%", txsess, rxsess, txtot, rxtot, voltage, SoC), PRIVATE);

    Cellular.resetDataUsage();

    //Cellular.off();
    //System.sleep(SLEEP_MODE_DEEP, 600); //sleep for 10 minutes
    System.sleep(D0, RISING, 30, SLEEP_NETWORK_STANDBY);
}

One thing I added tho’ was SLEEP_NETWORK_STANDBY in order to cut down on data usage on reconnect.

1 Like

@ScruffR That clean up was very helpful, thanks, I actually learnt a lot just from that.

Data usage is working now. But I can't see how your improvements made the data usage work. Any ideas? Doesn't really matter, just curious. I changed

Cellular.resetDataUsage();

to:

data.tx_session = 0;
data.rx_session = 0;

so I could get a by comms and total update. That works nicely.

Other observations.

It does struggle to connect a lot more than before. Cycling fast cyan, slow cyan, 3 red and round again many times. This results is big data usage of course. That might just be network conditions.

I get a Device Came Online item in the log every 4th call (occasionally longer). That may be coincident with the above, not 100% sure.

Cyan breathing for many seconds (20-30) after sending data but before turning off. That is worrying for battery usage.

Bloody difficult to get it into Listening Mode to update the script now, even when it's in Connected Mode (i.e. not asleep). Is that something to do with adding SLEEP_NETWORK_STANDBY ? That doesn't seem likely. I'm going to try taking that back out, just to see if it affects any of the above.

But a big leap forward nonetheless, thanks @ScruffR

OK, tried it without SLEEP_NETWORK_STANDBY. Not only is that saving data but it’s also what making the DataUsage stuff work. However, it also seems to be what’s causing the occasional connection issues and the breathing cyan before shutdown.

In other words:

Without SLEEP_NETWORK_STANDBY
fast, completely reliable connections (well as far as I’ve tested)
no long breathing cyan after connection.

With SLEEP_NETWORK_STANDBY
lower data usage (I assume)
DataUsage commands work
less reliable connections
every 3-7 call cause “device came online” message
frequent long spells (20-30 seconds) of breathing cyan before going to sleep.

Here’s a grab of without SLEEP_NETWORK_STANDBY

And here’s with SLEEP_NETWORK_STANDBY

Just realised that the without version was calling in every 60 seconds, even though it was set to 30.... I think!

@ScruffR, can you help me with the formatting of the RSSI and SQ? I have a hard time with the printf type stuff. I've currently got:

CellularSignal sig = Cellular.RSSI();
double rssi = sig.rssi;
double qual = sig.qual;

and

Particle.publish("Data", String::format("%4d, %4d, %4d, %4d, %.1fV, %.1f%%, %d, %d", txsess, rxsess, txtot, rxtot, voltage, SoC, rssi, qual), PRIVATE);

If you look at the formatting of voltage and SoC which are doubles too, you might get the idea :wink:
Otherwise there always is this info I like to link to
http://www.cplusplus.com/reference/cstdio/printf/

It is odd that you seem to get worse reconnect behaviour with than without SLEEP_NETWORK_STANDBY. The opposite would be expected and I can't see such behaviour with my G2 Electron, but I can test again with my G3.
I also think that the device came online message is a cloud artefact and not really costing you extra data.