Particle.function loop

@enque, one reason for the interrupt sample not working is this code

    attachInterrupt(D2, motion_begin, RISING);
    attachInterrupt(D2, motion_end, FALLING);

It's not possible to attach two different ISRs with different trigger modes to one pin.
For this you'd rather use a CHANGE trigger.

But I also can't help the feeling that you think Particle.function() actually calls your ledToggle() function ... well, it doesn't.
Could you please re-read the docs about Particle.function() and just put in your own words what you understand what it does?
It's important to get these fundamentals correct if you ever want to write your own code.

And your int ledToggle() has to return an int which it doesn't in your code above.

1 Like

OK, sorry for the delay in getting back. I just started a new job. In my own words/layman’s terms I would say that Particle.Function sets up a function so that it can be triggered through the web. So I was able to get serial monitor to work as a troubleshooting tool, and I can see the function responding appropriately to my website. However my particle.publish is not being called. When I added.

int ledToggle(String command){

    Serial.print(command);
    Serial.println();
    
    if (command == "on"){
        send_message = false;
        Serial.println(send_message);
        return 1;
    }
    else if (command == "off"){
        send_message = true;
        Serial.println(send_message);
        return 0;
    }
    else{
        return -1;
    }
    
}

Now I see “on 0” or “off 1” when the website posts. I expected to see “on true” and “off false” but I adapted my expected value and still particle.publish is not executing. Is my send_message variable not passed into the loop?

Did you change the HTML file? The code you posted should send either “on” or “off” as the value of command, not “on 0” or “off 1”. Are you seeing the output from Serial.println(send_message), or only from Serial.print(command)? It’s also not clear which code you are running now. Is it the code you posted in the original question, or the last code you showed, where you said “Here is the code I adapted from your example”?

So the serial first prints out the string you passed it, either ‘on’ or ‘off’. That gets printed correctly. Now, in your ‘if’ clauses, you switched the values. ‘on’ gets ‘false’ and ‘off’ gets ‘true’, which should be the other way around I assume.
As for the ‘true/false’ vs ‘1/0’, that shouldn’t make a difference. They’re handled equally.
Your function call is correct, now you’ve got to find where the error is in the loop. I suggest placing a few serial prints in there as well, to see how far it gets.

The html file is unchanged. Serial.print(command) returns “on” or “off”. Serial.print(send_message) returns “0” or “1”. Thats why when I print them back to back I get things like “on 0” (seperate lines)

@Moors7 Yeah, you described what is happening. With serial.print peppered in it seems that send_message isnt passed into loop()

Sorry, I misunderstood your post. So, I’m not sure what’s going on. The code below, works for me, using the HTML that you posted. I don’t have a PIR, so I just shorted motion_pin to ground (after sending “off” from the web page), and the green LED came on.

volatile bool send_message = false;

int calibrationTime = 30;
long unsigned int lowIn;
long unsigned int pause = 5000;
boolean lockLow = true;
boolean takeLowTime;

int motion_pin = D2;
int RedLED = D5;
int GreenLED = D4;

void setup() {
  Serial.begin(9600);
  pinMode(motion_pin, INPUT_PULLUP);
  pinMode(RedLED, OUTPUT);
  pinMode(GreenLED, OUTPUT);
  Particle.function("led", ledToggle);

  digitalWrite(GreenLED, LOW);
  digitalWrite(RedLED, LOW);
  // delay(calibrationTime * 1000);
  delay(5000); // I substituted this for testing purposes
}

void loop() {
  if (digitalRead(motion_pin) == HIGH) {
    digitalWrite(RedLED, HIGH);
    if (lockLow) {
      //makes sure we wait for a transition to LOW before any further output is made:
      lockLow = false;
      delay(50);
    }
    takeLowTime = true;
  }

  if (digitalRead(motion_pin) == LOW) {
    digitalWrite(RedLED, LOW);  //the led visualizes the sensor's output pin state

    if (takeLowTime) {
      lowIn = millis();          //save the time of the transition from high to LOW
      takeLowTime = false;       //make sure this is only done at the start of a LOW phase

      if (send_message == true) {
        Serial.println("lighting the green LED");
        //Particle.publish("movement");
        digitalWrite(GreenLED, HIGH);
      }
      delay(1000); // respect publish limit
    }
    //if the sensor is low for more than the given pause,
    //we assume that no more motion is going to happen
    if (!lockLow && millis() - lowIn > pause) {
      //makes sure this block of code is only executed again after
      //a new motion sequence has been detected
      lockLow = true;
      delay(50);
    }
  }
}

int ledToggle(String command) {
  if (command == "on") {
    send_message = false;
    return 1;
  } else if (command == "off") {
    send_message = true;
    return 1;
  } else {
    return -1; // got a command that's not recognized
  }
}

Thanks for your help. Trying to rule out any differences between your and my code, I copied it over and tested it. It still didn’t function as I had expected, but I think I have found my issue.

if (send_message == true){
   Serial.println("lighting the green LED");
   Particle.publish("movement");
   digitalWrite(GreenLED, HIGH);
}

The above within my loop was never running, which made me think that send_message wasn’t being passed up into the main loop(), but when I moved it within the If{} statement where the motion detector is read, it seems to work.