Electron cellular connection routine

electron
Tags: #<Tag:0x00007fe22479cad0>

#1

Dear all, I’m starting my first project with Electron.

This project was previously based and operative with Arduino, but I’m now moving to Electron.

Basically it is an environmental remote monitoring box, where the sensors are red every 5 minutes and the data sent to our web cloud by TCP client. At our server a PHP script takes care of data receiving and DB uploading.

Being pretty new to E., I was really looking for some support and advice about the most reliable connection routine in 2G/3G network.

I will use a 3rd party SIM and I will use my own cloud server.

Looking other Topics and forum’s discussions I was able to arrange this code, which I present here (the very essential part). What do you think about this code?

Really thanks for any support.
Best
Michele

#include <cellular_hal.h>

// network and APN data
SYSTEM_MODE(MANUAL); // do not autoconnect to particle cloud
SYSTEM_THREAD(ENABLED); // enable threading
STARTUP(cellular_credentials_set("mobile.vodafone.it", "", "", NULL)); // custom APN configuration

// Global Functions ============================================================

/*
* Connect to the network
*/
bool SIM_connect()
{
    int i;

    Serial.println("starting the modem...");
    Cellular.on(); // turns on the modem

    delay(5000);

    Serial.println("now connecting to network...");

    while(!Cellular.ready()) //wait until condition is true
    {
        Serial.print("connection try n°: ");
        Serial.println(i);
        Cellular.connect(); // make network connection to APN
        delay(1000);
        i++;
        if (i == 4) break; // retry 3 times before giving up
    }

    if (Cellular.ready()) {
        Serial.println("OK connected to network");
        return true;
        }
    else {
          Serial.println("error, NOT connected");
          return false;
          }

} // end of function


/*
* Disconnect from the network
*/
void SIM_disconnect()
{
        Serial.println("now disconnecting the network...");
        Cellular.disconnect(); // close network connection to APN

       delay(5000);

        Serial.println("now powering off the modem...");
        Cellular.off(); // modem power off

        delay(5000);

        if (!Cellular.ready()) {
          Serial.println("OK disconnected to network");
          } else Serial.println("error while disconnecting");

} // end of function


/*
* Read data from the sensors
*/
void DataRead()
{
    // here I read the sensors, both analog and digital
}


/*
* Send data to our cloud server
*/
void DataSend()
{
    // here I send data to my cloud by TCP client
}


// Setup =======================================================================

void setup()
{
    unsigned long now = millis(); // give some time after wake-up
    if (now < 20000) {
    return;
    }
    Serial.begin(9600);

} 



// Main Loop ===================================================================

void loop()
{
    if (SIM_connect()) // if true, read and send data
    {
      DataRead(); // now read the sensors
      DataSend(); // now send the data
      SIM_disconnect(); // now disconnect
    }

    System.sleep(SLEEP_MODE_DEEP,360); // Put the device into deep sleep. The device LED will shut off during deep sleep

} 


#2

I’d not do this but rather go with something along this line

  // could be put in a loop, but shouldn't be required
  Cellular.connect();
  if (waitFor(Cellular.ready, 300000)) { // a cold connec can take up to 5 minutes
    Serial.println("OK connected to network");
    return true;
  }

  Serial.println("Couldn't connect for 5 minutes");
  return false;

Also, with your if (now < 20000) return; in setup() the code will in 99.9% not reach the following instructions as that instruction is executed pretty much immediately - let alone after 20 seconds - after wake from deep sleep.


#3

@ScruffR many thanks for your reply ! I will change that as you suggest.

Also, with your if (now < 20000) return; in setup() the code will in 99.9% not reach the following instructions as that instruction is executed pretty much immediately - let alone after 20 seconds - after wake from deep sleep.

Do you suggest to replace with a delay(20000)? Or rather, there is no need to wait after the deep sleep wake up… ?

Moreover, what about a Watchdog? Do you think in this project (remote location, periodical network connection, …) it is better to implement it? I have no experience of Electron reliability, my previous Arduino had some issues with recurrent connections and time by time hanged.


#4

An external watchdog is usually a good thing for mission critical applications.

I don’t see a reason for the delay in setup().


#5

All right, got it. I will read carefully the Forum topics about external watchdog (I see there are many of them).

One more thing, with this kind of project and application, giving also the DEEP SLEEP function, is there a real need to have the main code in the loop() or I can use put everything inside the setup() ?

I’ve understood that any wake up from DEEP SLEEP send the device back to setup (like a… reset?). Correct?


#6

Correct!

Using loop() is not a hard requirement.


#7

Yep !

What if I put a function to check LiPo voltage and save battery, like this one, still ok to have it all in setup() ?

/*
* Battery saving function
*/
void FuelCheck()
{
    if(Fuel.getSoC() < 30) // If the battery SOC is below 30%:
    {
      System.sleep(SLEEP_MODE_DEEP, 3600);  // put the Electron into Deep Sleep for 1 Hour.
    }
}

#8

To answer any related questions that may occure I’ll just outline what setup() and loop() actually are.
Simply put, they are merely some functions that are called by the system like this

void main() {
  STARTUP();
  // do some preparation 
  setup();
  while (true) {
    loop();
    // do some other stuff (e.g. serialEvent() and cloud related)
  }
}