So I have a switch input triggering a spark.publish event, how would I write the program to only send out one spark.publish event until the switch is rest and the process would start over? I am fairly new to this style of programming so any advice would be great.
You can try something like this:
void loop() {
bool pressed = digitalRead(D2);
static bool publishedEvent = false;
if (pressed) {
if (!publishedEvent) {
Spark.publish("myEvent", "myData");
publishedEvent = true;
}
}
else {
publishedEvent = false;
}
}
The weakness here is that buttons tend to bounce, so even though we are only publishing one event per button press, the button may “bounce” causing the appearance of many presses.
This can be avoided by recording the last time the event was sent using millis()
and checking that the current time is at least (say) 100 ms later.
I figured out that if you use a delay() command after what the button input is triggering this will help with the bounce. I will have to give your suggestion a try, thanks.
Yes, a short delay() works well here too - good call!
another easy way would be a interrupt on a rising or falling edge, still have to watch for bounce though
volatile int state = false;
int buttonPin = D0;
void setup()
{
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(buttonPin, buttonPressed, FALLING);
}
void loop()
{
if(state){
Spark.publish("myEvent", "myData");
state = false;
}
}
void buttonPressed()
{
state = true;
}
well let's debounce it then...
void buttonPressed()
{
static unsigned long lastPressedTime=0;
if (millis() - lastPressedTime > 100UL);
{
lastPressedTime = millis();
state = true;
}
}
we hate using blocking code like delay( )
Thanks for all the helpful info, I will hopefully have a chance tonight to get to try some of these codes out and get them to work for me.
Ok so I ran both of the programs suggested and here are the results, I will show both programs and what happened in each.
int X0 = D0;
volatile int state = false;
void setup ()
{
pinMode(X0, INPUT_PULLUP);
attachInterrupt(X0, buttonPressed, FALLING);
Spark.publish("X0", NULL, 0, PRIVATE);
}
void loop()
{
if(state)
{
Spark.publish("X0");
state = false;
delay(1000);
}
}
void buttonPressed()
{
state = true;
}
So this program gave me the following:
1.Upon start-up it sends out a publish event
2.When X0 goes to LOW (button pressed & released) it sends multiple (2-3) publish events out.
3.When X0 goes to LOW (button pressed & held) it sends out publish events until the button is released.
int X0 = D0;
void setup()
{
pinMode(X0, INPUT_PULLUP);
Spark.publish("X0", NULL, 0, PRIVATE);
}
void loop()
{
bool pressed = digitalRead(X0);
static bool publishedEvent = false;
if (pressed){
if (!publishedEvent){
Spark.publish("X0");
publishedEvent = true;
}
}
else {
publishedEvent = false;
}
}
So this program gave me the following:
1.1.Upon start-up it sends out multiple publish events, then stopped.
2.When X0 goes to LOW (button pressed & released) it sends out only one published event.
3.When X0 goes to LOW (button pressed & held) is sends out only one published event but only after the button has been released.
So far this last program is closer to what I am looking for but it still has a few bugs to work out. I would like it to send out the publish event even if the button is pressed and held. My scenario is that I would like to have my core notify me via IFTTT and using spark.publish to send a notification to my phone in the event a switch contact has been made or broken, i.e. if a door has been opened and left opened.
What should I try next. Thanks.
You do know that publishing to the Spark cloud is rate-limited to an average of once per second with a burst of upto four allowed, right?
Do you think you are exceeding that rate in the second sketch?
For sketch 1 you’d need to debounce the pin e.g. by doing this
...
#define DEBOUNCE 100
volatile unsigned long timeTriggered = 0;
...
void loop()
{
if (timeTriggered > 0 && (millis() - timeTriggered) > DEBOUNCE)
{
Spark.publish("X0");
timeTriggered = 0;
}
}
void buttonPressed()
{
timeTriggered = millis();
}
While your results 1. and 2. are as expected without debounce 3. does not make sense unless your code posted is not exactly the same as you tested or the falling edge detection gets retriggered where it shouldn’t (e.g. button issue like bad contact while holding or less likely firmware problem).
In sketch 2, since you are using INPUT_PULLUP
you need to negate your if (pressed)
since pressed will always be HIGH
/true
unless the button is pressed to pull LOW
/false
.
And you need debouncing here too.
Your results:
- I’d expect only two events, the one from
setup()
and one fromloop()
due to above reason. - I’m a bit surprised here as it seems that you don’t get button bounce
- This again seems odd due to the lack of bounce, but the bit about ‘after release’ makes sense again due to above reason
@bko I know that there is a rate limit and in the second sketch I know I am not exceeding it.
@ScruffR I will have to give your advice a try and see what happens, and both of these sketches are identical to what i had tried, i simply copied and pasted them here.
Again thanks for the help, this style of programming is a bit of a learning curve but I’m catching on.