Closed circuit monitoring


#1

What would be the best practice, code wise, to monitoring a closed/open circuit and publish the event only once (at state change)?


#2

Save the last state, and compare the new state to it? If they differ, do something? For debouncing, you could use a simple delay, or millis timer.


#3

Could I utilize a delay in such a way that it only allows one publish through until the state changes again?

Any code examples?


#4

Typically shouldn’t use a delay for that purpose, since you won’t know when the next state change is going to be, and it could miss that. The delay would mainly be used to debounce mechanical switching.

As for a code example, I haven’t got one right of the bat, but it’s not too hard. Pseudo-code down below, but this is only to give you an idea of how it could be done. Not tested or anything. (Some pieces missing as well, it’s just to get the concept across.)

bool oldState = false;

void setup(){
  oldState = digitalRead(pin);
}

void loop(){
  bool currentState = digitalRead(pin);
  if (currentState != oldstate){
    delay(100);
    Particle.publish("state changed");
  }

}

#5

Bear with me, as I am trying to grasp the functions of the code from the documentation.
Below is what I currently have to trigger one event. Would the code you listed serve to notify a state change ONCE and not continuously update the cloud? Also, could this be implemented into my child’s code below? :smiley:

int ledPin = D7;

int buttonPin = D1;

void setup()
{
  pinMode( buttonPin , INPUT_PULLUP); 
  pinMode( ledPin , OUTPUT ); 
}

void loop()
{   
   int buttonState = digitalRead( buttonPin );

  if( buttonState == LOW){    
    digitalWrite( ledPin, HIGH);
    Particle.publish("START","Pressed",60,PRIVATE);
    delay(1000);
  } 
  else {      
        digitalWrite( ledPin, LOW);        
  }
}

#6

The following code has worked perfectly for me to monitor a open/closed circuit.

Trigger on-board LED and publish event, once, respective to the state change.

int pwr = D0;
int read = D5;
int led1 = D7;
int state;

void setup() {

  pinMode(pwr, OUTPUT);
  pinMode(read, INPUT_PULLDOWN);
  pinMode(led1, OUTPUT);
  digitalWrite(led1, LOW);
  digitalWrite(pwr, HIGH);
  
}

void loop() {
  
  delay(2500);
  
  if (digitalRead(read) == LOW) {
      
      if (state != 0) {
          
          digitalWrite(led1, LOW);
          Particle.publish("Machine_State","STOP",60,PRIVATE);
          state = 0;
          
        }
      
    }
  
  else if (digitalRead(read) == HIGH) {
      
      if (state != 1) {
          
          digitalWrite(led1, HIGH);
          Particle.publish("Machine_State","START",60,PRIVATE);
          state = 1;
          
        }
      
    }
  
}

#7

One last question, regarding the last code segment.

Whenever I switch between states (open/close) I receive one publish per as expected.

However, in the event of power failure at the Photon I receive a publish if the read pin is HIGH after boot but nothing when the read pin is LOW after boot. Any ideas?

It looks to me as though the loop should perform the check and publish accordingly.

Thanks!


#8

You’d need to store the previous state in a non-volatile manner - currently on power loss the previous state will vanish and start with its initial value of LOW (0).
Non-volatile is either in EEPROM, or better in Backup RAM (providing you have a battery backup connected - e.g. as coin cell on VBAT).


#9

So would this LOW value not be published because it is not a change of state?


#10

It won’t publish because you check to see if the value is different from 0, which is isn’t since it’s 0. That’s why I checked the state in the setup for the first time. That way you have a reference for the loop.


#11

Wouldn’t the reference be relative to the last state? So it would publish upon state change but I wouldn’t necessarily know which position I was in.


#12

Given you have a HIGH/LOW pin state, you know the current state you’re in.

Let’s say you measure a LOW in setup. If in the loop you measure a LOW, don’t do anything. If you measure a HIGH, then that state is different from the previous state (LOW from the setup), which you can act upon. Then set the new oldState to be HIGH and restart the loop. Like my example.

Currently, your code has no start state defined (int state;), so it’ll set that to 0 (which it may very well not be). That’s why I suggest checking the current state in the Setup when you run the program, so the loop has something to go by.