Implications of a MCP23008

Howdy people. I have an application that employs an NCD relay board with an attached Particle Photon to control a remote water pump. Every 5 minutes my code checks to see if a float switch in a water tank is open or closed and sends a ‘0’ if it is open (no more water needed) or a ‘1’ if it is closed (need to refill the tank). Everything has been working as designed with one exception:

Every once in a while - every day or two - my code sends a single ‘1’ even though the float switch is open. At the next 5-minute interval, it resumes sending zeros. A couple of years ago someone suggested - for reasons I can no longer recall - that I include in my code a provision to reset the MCP23008 chip on the relay board and I did so (every hour). At first I wondered if that reset caused the Photon to ‘see’ a closed circuit from the float switch, but I doubt it. If that’s the explanation, then I would expect to see the phantom ‘1’ ever hour (when the float switch is actually open) rather than every day or two.

Can anyone offer a possible explanation? Be advised that there is never any turbulence in the water tank that might cause the float switch to ‘bounce’.

My code:

#include <NCD2Relay.h>

NCD2Relay controller;

SYSTEM_THREAD(ENABLED);

String data = String(10);
static unsigned long lastPumpUpdate = millis();
int status;
unsigned long publishInterval = 300000;
unsigned long lastPublish = millis();
unsigned long lastReset = millis();

STARTUP(WiFi.selectAntenna(ANT_AUTO));

void setup()
{
waitUntil(Particle.connected);
controller.setAddress(0,0,0);
int status = controller.readInputStatus(3); // Read input terminal 3
Particle.publish(“IO”, String(status), 60, PRIVATE);
lastPublish = millis();
lastReset = millis();
lastPumpUpdate = millis();
}

void loop()
{
if ( millis() > lastReset + 3600000 ){ // Reinitialize the MCP23008 chip on the NCD relay board every hour
controller.setAddress(0,0,0); // Reinitialize the MCP23008 chip on the NCD relay board
lastReset = millis(); // Reset last initialization time to current program time
}
if ( millis() > lastPublish + publishInterval ){ // Send float switch status every 5 minutes
int status = controller.readInputStatus(3); // Read input terminal 3
Particle.publish(“IO”, String(status), 60, PRIVATE);
lastPublish = millis();
}
}

Hi Brian,

Not exactly sure what would be causing that. I have never heard of the input randomly showing as closed when it’s actually open.

  1. How long is the cable connecting the float switch to the input?
  2. What type of cable is it? Is it Cat 5/Cat 6? Is it shielded?

I ask this because I wonder if it’s picking up static which is causing erroneous readings.

You could try adding in something like:

if ( millis() > lastPublish + publishInterval ){ // Send float switch status every 5 minutes
     int status = controller.readInputStatus(3); // Read input terminal 3
     if(status == 1){
           status = controller.readInputStatus(3);
     }
     Particle.publish(“IO”, String(status), 60, PRIVATE);
     lastPublish = millis();
}

This would just take a second reading which may be enough to ensure this isn’t a random inaccurate reading.

The wire connecting the float switch to the NCD board is - believe it or not - 12 gauge Romex (don’t ask, 'cause I don’t know), about 15 feet in length buried underground.

Your suggestion is both simple and brilliant! I will do that. But you might want to take a gander at the attached screenshots. One shows the Particle Console event log for the last time this happened and the other shows the Google sheet that is populated by IFTTT for the same time period. The event log shows no transmissions - either a ‘1’ OR a ‘0’ - during the 20-minute interval when the Google sheet says it received two. How in the world can the Particle Cloud receive anything that appears to have never been sent? Of course, that’d be a question for those guys and not you, but maybe you can hazard a guess.


FWIW, here’s the ‘handler’ code at the other end. Unless I’m missing something, that code should only execute upon receipt of something from the Cloud which, in turn, will only send it if it received something from the tank. The publishing of “Tank On” or “Tank Off” occurs nowhere else in my code.

void myHandler(const char *event, const char *data)
{
if (manualTimer){ // Do not react to publishes if command was sent to manually turn pump on for time period.
return;
}
lastTankUpdate = millis();
if ( linkUp == false ){
linkUp = true; // If the ink was previously down, it just now came up
Particle.publish(“Link”, “Up”, PRIVATE); // Send status to IFTTT for notification and logging
delay(10000); // Wait 10 seconds before sending auto-off
}
String d = String(data);
int status = d.toInt();
if (status & 1){
controller.turnOnRelay(1);
pumpOn = true;
if (relayState == 0){
relayState = controller.readRelayStatus (1);
pumpOnTime = millis(); // Set start time
Particle.publish(“Status”, “Tank On”, PRIVATE); // Send status to IFTTT for notification and logging
}
}else{
controller.turnOffRelay(1);
pumpOn = false;
if (relayState == 1){
relayState = controller.readRelayStatus (1);
Particle.publish(“Status”, “Tank Off”, PRIVATE); // Send status to IFTTT for notification and logging
}
}
}

So do you ever see a particle event that shows the input closed when it actually isn’t or are you only seeing this on the Google Sheet? Basically what I’m asking is are these phantom triggers ever actually coming out of the board or are they just appearing on the cloud side of things?

Hmmm. Interesting question. I only see this in the Google sheet (never have determined if the pump actually turned on). But if some phantom triggers are happening on the cloud side of things, the precise 5-minute timing is curious. I’m thinking that I should post this on the Particle forum. I started with NCD only because I needed confirmation that it had nothing to do with resetting the MCP23008, which you have confirmed.

Post a link here to your community post on Particle if you would so we can follow along there.

Phantom or random events might indicate that the power supply has excessive ripple or is being glitched if it is not getting clean power from a UPS. There might also be a grounding problem. It’s worth checking outside the box.

Intermittent problems are THE WORST.

1 Like

Do you have any pull-down resistors connected between pin 3 and ground (around 10 kohms or 100 kohms)?

GPIO pins on most chips go into a high-impedance mode (high resistance between the pin and the logic circuitry) when configured as an input to limit current flow into the chip. Thus, the pin voltages are easily fluctuated by any stray electro-magnetic interference around (which is everywhere, all the time, to some degree) which causes random levels to be read periodically.

The MCP23008 actually has pull-up resistors built into it that can be enabled through software (would require small modifications to your wiring and code), though the NCD library you’re using does not make use of them.