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;
}
}
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.
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.
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.
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;
}