Hardware Based Interrupts with Particle Publish

Friends,

I have wired up a float switch and am trying to get it to work with particle publish. I’ve learned thus far that you shouldn’t publish from the interrupt directly because it freezes when the interrupt is tripped, but am having trouble on the software side of things.

I have the interrupt set to trip when the state changes, if the switch is up or down, and it works when I use serial.println ( I know this isn’t good, but was using it just to verify that it worked). I also do some software de-bouncing using the elapsedmillis() lib. Anyways, in the interrupt I set a variable, h, to denote the orientation of the switch. When I try to call that in the loop by probing that h variable it will publish even if the switch hasn’t been thrown, but id doesn’t start publishing until the first time the switch has been moved. Here is the code I am running as well as a useful post that help me a lot.

How do I get it to only publish once for each time the switch is thrown? I eventually would like to use the status of this to trigger various other functions, like triggering mosfets, or sending you a notification, if anyone has resources for how to design the code to make that part easy those are much appreciated as well.

// This #include statement was automatically added by the Particle IDE.
#include <elapsedMillis.h>

#define floatPinTop D2
volatile int flowup =1;
volatile int flowdown=0;
volatile int h = -1;
int laststate=-1;

elapsedMillis timer0;
#define interval 100

void setup() {
    Serial.begin(9600); 
    pinMode(floatPinTop, INPUT_PULLUP);
    attachInterrupt(floatPinTop, WaterAbove, CHANGE);

}

void loop() {
    
   
    delay(1000);
    laststate=-1;
    
    if(h==1){
        
        laststate=h;
        Particle.publish("TopFloat","FlowingUP");
       
        
        }
    if(h==0){
        laststate=h;
        Particle.publish("TopFloat","FlowingDOWN");
      
    }

}

void WaterAbove() {
    if (timer0 >interval){
        if((h==-1) || (h==0)){
            
            
            h=1;
            Serial.println("flowing up");
            timer0=0;
    
        }
    }
    if (timer0 >interval){
        if (h==1){
          
            Serial.println("flowing down");
            timer0=0;
            h=0;
        }
    }
}

Let’s say it triggers, and h == 1 now. Seeing as you never change that value, it will stay 1 and trigger on every iteration of the loop. The code is working as it should, just not as you’d like it :wink:
If you use that laststate variable, you should be able to make it work. In the IF, check for the h state, as well as h being different from the laststate. Then, in that IF, set laststate = h, so it won’t trigger again until h changes.

Makes sense?

4 Likes

Thanks Moors7, this is what i was trying to accomplish initially but got a little confused along the way. I tried what you recommended and it worked! here is the new if statement that is in the loop, for other ho may be having the same problem.

if(h==1){
        if(laststate!=h){
            laststate=h;
            Particle.publish("TopFloat","FlowingUP");
       
         }
        }
    if(h==0){
        if(laststate!=h){
            laststate=h;
            Particle.publish("TopFloat","FlowingDOWN");
        }
    }

Now how would i use this result to trigger other funtions? can i use this to trigger other interrupts?

You could ‘shorten’ it a bit, since the 'laststate != h` needs to be true for both cases, you could use that to encapsulate the lot.

if(laststate!=h){
    if(h==1){
        Particle.publish("TopFloat","FlowingUP");
    }

    else if(h==0){
        Particle.publish("TopFloat","FlowingDOWN");
    }
    
    laststate=h;
}

As for interacting with other ‘things’, it depends on what you want to do. IFTTT makes it easy for set up push notifications.

2 Likes

Thanks for the help @Moors7!

1 Like