I have three digital pins, each sensing whether a particular appliance is on or off. I wanted to publish an event to the cloud, showing the on/off status of each of those appliances, whenever any one of the appliances switched from on to off. The amount of code necessary to store the status of each of the pins, read each of the pins, see if any had changed, and to publish an event if any had changed, while doable appeared excessive. I came up with an elegant solution which I’d like to share with the community.
I map the pins D1, D2, D3 to appliance1, appliance2, and appliance3 because, apparently, the attachInterrupt function doesn’t work with D0
the syntax for the attachInterrupt() function is:
attachInterrupt(pin_name, function_to_call, MODE)
, where MODE is something like UP (the pin goes from low to high), DOWN (the pin goes from high to low), or CHANGED (the pin changes). I used CHANGED because I want to publish when any one of the three pins changes.
I put this in setup:
attachInterrupt(appliance1, STAT_CHANGE, CHANGE) ;
attachInterrupt(appliance2, STAT_CHANGE, CHANGE) ;
attachInterrupt(appliance3, STAT_CHANGE, CHANGE) ;
What this is saying is when the photon detects a change in one of the pins, call stat_change. Stat change sets the boolean variable changed to true, this triggers the if statement in the loop, and the status of all three pins is published.
The STAT_CHANGE function is defined below the loop (and declared at the top of the program) and changed is defined as volatile boolean changed = 0 ;
There are limitations on the types of functions attachInterrupt() can call… the function can’t take any arguments and it can’t return any value. You also want the function to be fast. I use I use it to set indicate changed as true.
void STAT_CHANGE()
{
changed=TRUE;
}
I define three strings appliance_status1 through 3, and a string to hold my published results “sout” in the header, and In the body of the loop I do this:
if (changed)
{
changed=false
clear the strings: appliance_status1 through three = "" and clear sout (the output string)
appliance_status1 = (digitalRead(appliance1)) ? "ON|||" : "OFF|||" ;
appliance_status2 = (digitalRead(appliance2)) ? "ON|||" : "OFF|||" ;
appliance_status3 = (digitalRead(appliance3)) ? "ON" : "OFF" ;
sout = sout+=appliance_status1+=appliance_status2+=appliance_status3 ;
Particle.publish("appliance_is",sout) ;
}
delay(5000)
}
When the “If this then that” website sees the “appliance_is” event it adds a line to my spreadsheet in Google Docs. The tripple pipe symbol ||| which you see at the end of “ON||” and “OFF|||” above puts each of the results in a separate column on the spreadsheet… that’s another trick good for another post.
The attachInterrupt() function has some limitations… you should read the documentation before using it. But this works great… and as I said… the resulting code is elegant (in my opinion).
I know I’ve sort of glossed over this… but with some tinkering you can figure it out. Happy programming!