Mesh struggles, Boron and xenons

Here’s a brief outline of the relevant parts of my code, in plain-speak. I really can’t share the real thing at the moment so hopefully this will do…

First is a boron:

system mode manual

setup {
  mesh.subscribe(topic, printToSerial)
  mesh.on
  mesh.connect
  (do some stuff that takes a while but doesn't need to use the cell, so saving battery)
  cellular.on
  cellular.connect
}

loop {
  particle.connect
  (some stuff happens, sends some previously collected data to cloud)
  cellular.off
  (hang out and wait for more data, log persistent)
  reset
}

printToSerial(event,data) {
  serial.println(data)
}

and then the xenons:

loop {
  (get data at interval)
  mesh.publish(topic,data)
}

So here’s where it gets weird: this all works, but incredibly inconsistently.

  1. There are 3 xenons and one boron, but only 2 ever check in at a time. Not the same 2, like sometimes they will be (over serial from the boron) showing me data from A and B, and then after a reboot or three A and C or B and C. But never A, B, and C. What might I be doing wrong?
  2. I don’t think the mesh devices connect before at least one full cycle of having cellular turn on…does mesh not work with cell off on the parent device until the child devices have checked in to the cloud or something? If so…why? Ultimately I’d like the xenons to be asleep almost all the time, wake up to check a sensor and forward the data to the boron, and then conk out for another nap. It seems like if I do this and they require cell to check in…
1 Like

Usually you want your gateway/repeater to keep running, so your reset at the end of loop() will at least contribute to the issue.
Also a lone Xenon is not really meant to pull up a mesh network. It may be able to keep a network alive but once the last device vanishes the mesh will do so too.

Thank you

Note that it’s the boron that’s running at all times (except for my brief resets, which are roughly every 30 minutes), though most of the time the cellular is disabled…

So I tested having cellular on full time (which I really can’t have in the final, but worth a test), and without having the boron reset: still not getting 3 devices online at the same time.

Test code I’m now using, same results:

— Boron —

SYSTEM_MODE(MANUAL);

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

    Mesh.subscribe ("subUnit", subUnitAction);
    Mesh.on();
    Mesh.connect();
    delay(500);
    if (!waitFor(Mesh.ready, 10000)) {
        Mesh.off();
        delay(30000);
        System.reset();
    }

    Cellular.off();
    delay(500);
    Cellular.on();
    Cellular.connect();
    delay(500);
    if (!waitFor(Cellular.ready, 90000))
    {
        Cellular.off();
        delay(30000);
        System.reset();
    }
}

void loop() {
  if (!Particle.connected()) {Particle.connect();}

  if (Cellular.ready() && Particle.connected()) {
		Particle.syncTime();
		waitUntil(Particle.syncTimeDone);

		// Particle.publish("test","test1", PRIVATE);
        delay(30000);
  }

void subUnitAction(const char *event, const char *data) {
	Serial.println (data);
}

— Xenon (three of these, same code on each but changing sensor1time to sensor2time and sensor3time) —

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

void loop() {
    particleSend();
    delay(5000);
}

void particleSend() {
	String dataString="";
		dataString.concat("sensor1time=");
		dataString.concat(String(Time.local()));
   Mesh.publish ("subUnit", dataString);
   Serial.println(dataString);
}

Can you try adding SYSTEM_THREAD(ENABLED)?

MANUAL mode would require regular calling of Particle.process() (at least for the cloud connection)

BTW, for cell connections a timeout of 90 seconds might not always be sufficient.
And your loop() is missing a closing curly brace, IMO.

You should also not call Particle.connect() over and over again while a previous connection attempt might still be ongoing.
Either use waitFor() there too or let it be a one-shot action with a flag that will be reset after a timeout or once you detect Particle.connected() == true (checking Cellular.ready() is not required when also checking Particle.connected()).

On a side note:
I’d rather use C strings instead of String objects.
i.e. your code above always causes the Stringto inflate with possible relocation of the string as a String object usually starts with a 16 byte dynamic buffer and once that gets full it will be “inflated” but may need relocation as there might not be enought adjacent memory for the buffer to grow (which is likely as you are creating a temporary String object for Time.local() which would typically be created directly next to the previous buffer).

This would be my alternative

char dataString[32];

void loop() {
  snprintf(dataString, sizeof(dataString), "sensor1time=%d", Time.local());
  Mesh.publish("subUnit", dataString);
  Serial.println(dataString);
}
1 Like

I have a setup with many (up to 10) sleepy end node Xenons and the difference is that the mesh gateway is powered and runs continuously (Xenon in Ethernet featherwing). The endnodes wake on a various cycles according to whether there is data sensed and will Mesh publish - I have a handshake with gateway which is the opportunity for any commands to be sent to the endnode before any data is sent back. This is all very quick.

Two observations on the differences with the code you have shared; 1. After a wake from sleep I call Mesh.connect() and check for Mesh.ready() before publishing. 2. I use a publish queue on the gateway (the RK library) to decouple the publish from the application loop.

1 Like
  • System thread now enabled on both the boron and the xenons
  • Particle process now called after the syncTime section
  • whoops, must have deleted that } when I was tidying up for the post!
  • 90 second cell time: I’ll adjust at some point, seemed to work well for me so far but I’m currently in a location with good signal
  • Particle connect: that makes sense, I’m now holding it back with a waitFor(Particle.connected, 30000);. Not sure if 30s is enough or too much. Also knocked off the extra cellular.ready as suggested, don’t know why I even had that :slight_smile:

Results: looking the same. Two xenons connected at a time but never 3, and which 2 still seems random. I do notice that sometimes the xenons alternate between rapid flashing blue and 3 blinks of orange. Maybe a hint?

Here’s the order things go from a fresh boot:

  • all devices start rapid green, two xenons’ worth of data start spilling out of the boron. Whichever 2 boot first, if I stagger the boot times.
  • boron does a normal cell and cloud connection, goes to breathing cyan and stays there
  • two or three xenons start flashing cyan (not rapid) for a bit, followed by 3 blinks of orange. Sometimes one xenon stays flashing green (the one that never connected), but not always.
  • Sometimes, eventually, the connected xenons start breathing cyan

Also: C String: makes sense!

Edit: I ended up pulling system_thread from the Boron after initial testing, seemed like it would break connection (mesh and cellular) after a minute or three and go in to an infinite flashing-green mode. Removing returned it to a stable constant connection.

Hmm…that might be a workable solution: IG make sure only one device is connected/attempting to publish at a time? It doesn’t quite seem the way I would expect a mesh to work, but in this use case it wouldn’t be a problem.

This worked! For any future explorers this is what my (testing) xenon loop looks like:

void loop() {
    Mesh.on();
    Mesh.connect();
 	waitUntil(Mesh.ready);
        getData();
        mesh.publish(topic,data)
        delay(10000); //10s is arbitrary, but required a delay to ensure send happens.
    Mesh.off();
	delay(5000); //arbitrary 'sleep' time
}
1 Like

IMO - you do not need the delay(10000); after Mesh.publish() as it is very quick - my logic listens for a command reply for 1-2 seconds and this always seems sufficient!

Definitely not 10 seconds: it didn’t work with no delay, so I set it to “definitely long enough” just to make sure.

put a delay of 10 second or so after each cellular.on,connect,etc and each mesh operation. Give it time to complete before checking status. this solved a lot of problems for us.

1 Like