Spark.publish with Time Based Trigger

Hi

I could use some help with spark.publish. I’m attempting to use it along with spark.subscribe for core to core communications. I’ve read most of the threads where folks have been sending requests related to a door opening or closing. The difference I’m trying to incorporate using the door example is that the spark.publish request is not sent unless the door has been open for x amount of time.

As I have it written at the moment, I borrowed some code from those other threads to keep the ISR simple, but its still not working.

Thanks as always.

int switchPin = D0;
int led = D7;
int switchStatus = 0;
volatile unsigned long last_interrupt_time = 0;
volatile int change_flag= 0;

unsigned long startTime;
unsigned long duration;


void setup() {
    pinMode(switchPin, INPUT_PULLDOWN);
    pinMode(led, OUTPUT);
    digitalWrite(led, LOW);

    attachInterrupt(switchPin, switchChange, CHANGE);
}


void loop() {
    if (change_flag) {
        switchStatus = digitalRead(switchPin);
        digitalWrite(led, switchStatus);  
        if (switchStatus == HIGH) {
            startTime = millis();
            duration = millis() - startTime;
    
            if(duration >= 5000)  {
                Spark.publish("switch-status","alert", 60, PRIVATE);
        
            }else
            {
            Spark.publish("switch-status","clear", 60, PRIVATE);
            }
        }else
        {
        }   
    change_flag = 0;
    }
}


void switchChange() {
    unsigned long interrupt_time = millis();
    if (interrupt_time - last_interrupt_time > 1000) {
        change_flag = 1;
        last_interrupt_time = interrupt_time;
    }
}

Hi @techbutler

It looks like you are setting startTime anytime the switch is HIGH and then immediately checking the duration. I think you want to say that duration = millis() - last_interrupt_time; instead; that would be the duration from the last change until now.

1 Like

Hi @bko

I’m afraid I’m not following. My intended use of last_interrupt_time is merely to keep within publish rate limits. It has nothing to do with the duration of time the pin needs to be HIGH before a publish request is made. So if I’ve got duration screwed up aside from last_interrupt_time, what would you suggest?

In your current code, duration is the time from one call to millis() to the next line of code where you call millis() again. It will almost always be 0 but could be 1 occasionally is millis() happened to increment.

If you want the duration to be the time since the last publish event, then set startTime when you send the publish events.

But I don’t want the duration to be the time since the last publish event… duration is meant to be the amount of time an event takes place BEFORE it is published. That’s why startTime needs to begin when the pin goes HIGH.

I tried this change to loop, but still no go…

void loop() {
    if (change_flag) {
        switchStatus = digitalRead(switchPin);
        digitalWrite(led, switchStatus);  
        if(switchStatus == HIGH) {
            startTime = millis();
            while(switchStatus == HIGH) {
            
                duration = millis() - startTime;
    
                if(duration >= 5000)  {
                    Spark.publish("switch-status","alert", 60, PRIVATE);
        
                }else
                {
                    Spark.publish("switch-status","clear", 60, PRIVATE);
                }
            }
        }else
        {
        }   
    change_flag = 0;
    }
}
```cpp

If I am understanding you as to what you want to do, I think the best answer is delay(5000); so that there is always a 5sec delay before publishing.

The code you wrote above looks like it loops forever since you only enter the while loop if if switchStatus is HIGH but you never change switchStatus inside the loop.

EDIT

The markup for code is:

  ```cpp
    //code here

This is the proof of concept code I ended up putting together (for just a switch) that allows one to publish digital sensor events where the duration of the HIGH or LOW is a factor, such as how long a door has been open.



int holdDelay = 5000;    // Sets the hold delay of switch
 
int ledPin     = D7;      
int switchPin  = D0;      
 

unsigned long startHold;
boolean allow = false;
int switchState;
int switchLaststate = LOW;

 

void setup() {
  pinMode(ledPin, OUTPUT);      
  pinMode(switchPin, INPUT);    
  Serial.begin(9600);
}
 

void loop() {
  switchState = digitalRead(switchPin);    
  digitalWrite(ledPin, switchState);
  
  if (switchState == HIGH && switchLaststate == LOW)  {  // for button pressing
    startHold = millis();                       // mark the time
    allow = true;                                // allow state changes
  }
     
  if (allow == true && switchState == HIGH && switchLaststate == HIGH)    {  // if button remains pressed
      if ((millis() - startHold) >= holdDelay)    {                   // for longer than delay time
         Spark.publish("switch-status","alert");                        // send publish request
         allow = false;                                                   // prevent multiple publishes                         
                                                    
      }
  } 
 
  switchLaststate = switchState;   
  
}