Best Practices in loop() Using (or not) delay()

Howdy.

I have a Boron 404X and am using it to send Bluetooth events of interest to "the cloud" - after scraping my knees on thinking of using HTTPS directly I switched over to the Particle.publish method. Here's my question -

The Boron is essentially looping on:

  • scanning BLE with a filter
  • if anything "interesting" is available, call Particle.publish

The "anything interesting" does include a BLE peer connection and reading characteristics, but nothing major.

Should I be running a "tight loop" with this? Meaning loop() includes no delay() of any kind, and just repeatedly kicks off the scan, etc. Or am I starving the system somehow if I don't delay or yield, etc.

Coincidentally, my Particle.publish webhook callback isn't, which I've seen quite a few posts on. I'm pretty sure it is configured correctly (subscribe in setup and publish in loop).

Hi,
In the console, for a particular device, you might see an item called "rate-limited publishes" under heading Last Vitals. This item will have a value in front of it, probably "0", or zero. The cloud limits your publishes to 1 per second. If you go over that, Last Vitals will report the occurrences of over limit. More about rate-limited publishes here:

https://docs.particle.io/reference/device-os/api/cloud-functions/particle-publish/

Within your loop(), you could delay between publish commands in a way similar to this:

void loop() {
  ...
  static system_tick_t lastPublish = 0;
  if (millis() - lastPublish >= 1000) {
    lastPublish = millis();
    if (Particle.connected()) {// if NOT connected - may block for up to 20 seconds (normal conditions) to 10 minutes (unusual conditions).
      Particle.publish("something_interesting", "the data");
    }
  }
  ...
}

If interested in libraries, there are some available which allow you to fire-and-forget when it comes to publishing events. One is: PublishQueueAsyncRK
https://github.com/rickkas7/PublishQueueAsyncRK
and another: PublishQueuePosixRK
https://github.com/rickkas7/PublishQueuePosixRK

1 Like

You should return from loop() as quickly as possible. You shouldn't force a delay before returning.

Also be careful about doing lengthy things from the BLE scan callback. It's better to save the things you found in the callback and then do the publish from loop instead. This will also make it easier to rate limit your publishes, or combine multiple things into a single publish to save on data operation.

3 Likes

Thanks for the feedback here. Yes, I'm not doing anything crazy (I don't think) in the BLE scan, but I am not using a callback at the moment:

BLE.setScanTimeout(50);

BleScanFilter filter;

filter.deviceName("DEVICENAME").minRssi(-80).serviceUUID(BLE_SERVICE);

Vector<BleScanResult> scanResults = BLE.scanWithFilter(filter);

for (BleScanResult result : scanResults) {
  Log.info("Found device: %s", result.address().toString().c_str());

  // Connect, read characteristics, disconnect

I don't expect to hear from more than one device at a given time, though that isn't guaranteed. Is connecting to a BLE device in loop() a bad idea? Either way my code is going to take cycles from something else.

1 Like

That is the correct way to do the BLE scan.

1 Like