Extend contact closure from one site to another


For Ryan or Travis:

I am still learning C++ (but have made some considerable progress and have signed up for a local college course in same). But it is not yet clear to me how to continuously monitor the value of a variable while the code is doing all of its other stuff.

Here’s what I want to do: every time the firmware on the Electron at the well receives an inbound event from the Election at the tank (Serial.println(“IO Event Received”);), set a dedicated variable to 0 (zero) and then start incrementing that variable every couple of minutes continuously until a new incoming event arrives from the tank. If the variable’s value should ever reach, let’s say, 10 minutes (no message from the tank for 10 minutes), publish a new event, e.g. “DISCONNECTED” or “NO RESPONSE” that can be sent via an IFTTT applet as a text or email to those responsible for monitoring the system.

Obviously, I cannot let the firmware execute in a ‘while’ loop continuously if doing so precludes the manual on/off control functions from being called (would it?).

If this is do-able, then I might expand upon the idea by having the Electron at the well send periodic events to the tank too. The latter would have the same capability to report a link failure. This way, no matter which end loses its cellular connectivity or power (assuming they don’t both do so at the same time), notification would be received.

Any ideas how to do this would be appreciated.

P.S.: how do my two Electrons know about each other, i.e. the firmware running on the Electron at the tank doesn’t have any addressing statement that identifies where its events should be sent. It must be done in the Particle Cloud but if so, then by implication every message sent by one Electron would be automatically delivered to every other device associated with the same account, right?


You can use another globally declared static unsigned long at the top of your code, like:
static unsigned long lastTankUpdate = 0;

Set lastTankUpdate = millis() in the appropriate place inside the myHandler function.
myHandler is what’s called when the Well sees a publish (from the Tank) that it subscribed to in Setup().

Then add another IF statement in Loop() to check if the Well hasn’t “seen” a publish from the Tank:

if ( millis() - lastTankUpdate > 600000 ) {   // in (ms), can also be a variable that you remotely change with a function
  //  Do whatever you want for an Alarm HERE, but be careful to not cause continuous Alarms. A simple cheat is update lastTankUpdate = millis() after each Alarm.  

I’m sure there are better ways to do this, but that’s how my brain works with limited coding skills.

The Electrons only “know” about each other from the Publish/Subscribe relationship.
The Line Particle.subscribe("IO", myHandler, MY_DEVICES) from Setup() will “catch” any published events named “IO” from any of your devices in your Particle Account.
Devices can subscribe to each other. You can also search for the term “Callback” on the Particle Forum for other ideas.


So you play with this stuff on weekends too, huh? Good on ya Ryan!

Your recommendation seems very close to what I was thinking of trying, except for the ‘if’ statement; where should that go? It can’t be inside the myHandler routine if the latter is called only when it receives an event from the tank because this is about what to do if, in fact, nothing arrives from the tank. Can it be anywhere?


The IF statement goes in Loop().

Very Similar to Post #187


Something like this maybe?

void loop(){
if ( millis() - lastTankUpdate > 600000 ) {
lastTankUpdate = millis();
data = “No Link”;
Particle.publish(“Error”, data, PRIVATE);

Yup; that worked!

For testing, I changed the milliseconds to 60000 from 600000 (1 minute instead of 10) since the incoming events from the well are now every two minutes. Hot damn!!


Good morning Ryan and Travis,

You guys have been so incredibly helpful and patient with me while I learn how to set up, embellish and troubleshoot my application that I thought you might be interested to know about the progress I’ve made and its current status.

First of all, everything is working very well; it’s now completely hands-off, turning the pump on and off reliably according to the need defined by the float switch in the tank.

I have added features to the firmware that do the following, mostly due to the power of IFTTT applets that Ryan pointed me to:

  • Sends a notification via the IFTTT iOS app and an email every time the pump turns on or off.

  • Sends a notification via the IFTTT iOS app and an email whenever the Electron at the pump fails to hear from the Electron at the tank for more than 10 minutes.

  • Turns off the pump (if it had been on) whenever the Electron at the pump fails to hear from the Electron at the tank for more than 10 minutes. This is to avoid tank overflow.

  • Log all events to a Google spreadsheet for monitoring, reporting and archiving purposes (see attachment).

My next efforts will include trying to get the Electron at the tank to report if it fails to hear from the one at the well (got to figure out how to get the latter to send some kind of ‘keep-alive’ message to the former; do all particle.publish events from either end get sent to - are seen by - the other?).


Hi Brian,

Very cool. Thank you for sharing.

So just out of curiosity what was the silver bullet for the unreliable connection issues you were having previously?



The issue was the code relative to PaperTrail. Apparently it overwhelmed the Electron processor, had some kind of infinite loop or who knows what else. But now that I’m using IFTTT to log events, I no longer care about PaperTrail, so I deleted the header file and the statement(s).


BTW Travis, I had an email exchange with someone at Particle about whether they have any plans to support Verizon LTE with the E Series modules. I asked because we have an application relative to managing our community’s gates that would be very well addressed by a solution similar to what we’ve now put in place for the well. However, on the side of our little mountain where the gates are located, Verizon is the only cell service available.

Particle said they are currently in talks with Verizon about a roaming agreement. Apparently, they are trying to get the same terms as they have with AT&T and T-Mobile (so they can charge users the same $3/mo., I assume).

It looks like the E Series modules will not plug into NCD’s existing relay boards. Do you guys have any knowledge of or plans regarding support for the E Series?


Hi Brian,

So the 3rd gen Particle modules(Boron, Argon, and Xenon) are all “feather” footprint modules. Our boards were designed for the old Electron footprint, however we made Feather to Electron adapters here:

So if you want to use one of the new modules with your old boards or another one of our boards you just need one of those adapters. For what it’s worth Particle makes these adapters as well.

Sorry I forgot about the E series modules from Particle. Short answer is no, those are surface mount so there’s no way to install them in our board. A custom design would be required.


Thanks for the update!


Hey Travis, I’ve encountered a curious thing here that I hope you can explain:

Some time ago I modified the code that runs on the Electron at the storage tank and it has been running perfectly until last night. There is a loop that tests the variable ‘status’ (which is set to ‘controller.readAllInputs()’. The expected values assigned to ‘status’ are ‘0’ or ‘1’. Last night the values ‘62’ and ‘63’ (see attached screenshot) started to appear and those unexpected values put the code into an infinite loop (well over 1000 entries in the log between about 4:00 AM and 7:00 AM). We can’t be sure, but we think that this all began when we had a momentary power interruption.

I had to add the following code to make it stop:

if((status = 0) || (status = 1));{
Particle.publish(“IO”, publishData, 60, PRIVATE);
lastPublish = millis();

Can you help me understand those values? Is there a document somewhere that defines all possible values that I might ever expect to see?

Update: after the above experience, I looked at the pump’s Electron and checked the pump status using the ‘Pump_Status’ variable. It returned a ‘256’! What does that mean? In order to get something other than that, I had to use the ‘Pump_Min’ function to turn the pump on and then off, at which time the variable properly returned a ‘0’.


Hi Brian,

Sounds to me like the board definitely experienced some power supply issues at some point that caused it to “go haywire”.

The board has 6 inputs. When you use the readAllInputs function it returns the status of all inputs as a byte. Each input has a binary representation in the byte. So if you get back a 1 that means input 1 is closed and all other inputs are open. If you get back a 0 that means all inputs are open. If you get back 62 then that means inputs 2, 3, 4, 5, and 6 are closed. It’s just binary. It sounds like the MCP23008 chip on the board which uses 2 IOs to control the on board relays and the other 6 to monitor as inputs got messed up in the power supply anomaly. So what you were seeing is all channels that were not connected to the float valve were reading as closed but it sounds like the float valve input was still functioning normally.

A good fix for this I believe since you’re only reading one input would be to replace the readAllInputs function with readInput(1). That way you are only reading the input you need to read and it should not give you that same issue.

Many of the functions in the library will return a 256 if the Electron is not able to communicate via I2C to the MCP23008 so if your application ever gets a 256 back it should notify the user that there is a hardware issue and recommend a power cycle to the hardware to recover.

Hopefully most of that makes sense but if not please let me know.

Thank you Brian,
Travis Elliott


Makes perfect sense, Travis. I just already made that change to read only input #1 but I get an error when trying to compile (see attached).

Regarding 256: can I perform a power cycle in code or do I have to go to the device and unplug it?


Hi Brian,

Sorry I should have checked the library(I was going off memory). The actual command is readInputStatus(1)

If you get a 256 from the request then more than likely this means the MCP23008 is in a failure state. You could attempt a soft reset but more than likely that won’t work and you’ll need an actual hardware reset. Probably your best bet would be some sort of cheap UPS there in the panel to protect the board from temporary power loss if that’s going to be a reoccurring problem.


We do have occasional power blips. I’ve thought about a UPS system and I happen to have a larger weatherproof cabinet to accommodate it. But, as I mentioned, invoking the timer function cleared the 256 error. Is a “soft reset” something I can do in code?


Yes, See Particle Docs here:


My apologies, Travis. I thought that the 256 error originated with NCD’s relay board, not from the Electron (since the latter has a Li-Po battery connected to it). If it’s coming from the latter, then I will implement Particle’s reset code.


Dammit. The tank is calling for water. Querying the ‘Pump_Status’ variable at the pump site returns a ‘1’ but the Relay #1 red LED is not on and no water was entering the tank. We cycled the power on the NCD PCB but no change. On manual bypass at the moment.

Any ideas?


Hi Brian,

Honestly at this point the firmware has evolved so much I really don’t know what’s going on anymore so it’s hard to provide much insight. You can send the firmware that’s running on the Pump board and I can take a look.