Particle.Function () losing its value


#3

I’m not sure why it would be working now. This is not how you compare Strings in C++.

https://docs.particle.io/reference/firmware/photon/#equalsignorecase-

There’s actually several different comparison methods depending on your needs:

https://docs.particle.io/reference/firmware/photon/#string-class

I believe your way, you are comparing to a pointer to the location in memory that holds the String object.

Edit: The value of the String object variable itself is neither “on” nor “off”, so you should get to the return 5 condition no matter what you call the function with.


#4

Your right. It stopped working again. I used the web connected LED as a guide. When i put in “on”. I get 1 for the Particle.variable(“Armed”,…). Then after a few min. it goes back to 0.

Here is the code from the guide.

int ledToggle(String command) {
    /* Particle.functions always take a string as an argument and return an integer.
    Since we can pass a string, it means that we can give the program commands on how the function should be used.
    In this case, telling the function "on" will turn the LED on and telling it "off" will turn the LED off.
    Then, the function returns a value to us to let us know what happened.
    In this case, it will return 1 for the LEDs turning on, 0 for the LEDs turning off,
    and -1 if we received a totally bogus command that didn't do anything to the LEDs.
    */

    if (command=="on") {
        digitalWrite(led1,HIGH);
        digitalWrite(led2,HIGH);
        return 1;
    }
    else if (command=="off") {
        digitalWrite(led1,LOW);
        digitalWrite(led2,LOW);
        return 0;
    }
    else {
        return -1;
    }
}


#5

Can you give more information about this? What do you mean by after a few minutes? Are you doing anything other than requesting the variable again? What @DevRandom said about the String comparison is incorrect; it is ok to use == to compare String objects (but not c strings). I don’t know if it will make a difference, but you should at least change your Particle.variable declarations to the current syntax. I see nothing in your code that would cause armedcommand to lose its value. Btw, I don’t know why you’re using isitarmed at all; you can just use armedcommand instead.


#6

So in the last post I did remove isitarmed from my code. It was not needed, but I wasn’t sure how often a particle.function updated with a loop. Anyways. I use the console or the web app to call the variable "armed’ to check if the function is working correctly. It is not very inconsistent. It might stay at 1 (“on”) for a 1-5 min., then it goes to zero. I have no idea why.


#7

Me neither. Please post the actual code that you’re using now, that gives this behavior.

This line is incorrect, btw, you should be using digitalWrite, not analogWrite.


#8

The analogWrite(Power,HIGH) was something left over from troubleshooting…

This seems to be working as of now.

int BackDoor = A0;
int Front= A3;
int Garage = A1;
int Basement = A2;
int Bedroom = A4;
int LED = D7;
int BDvalue;
int FDvalue;
int GValue;
int BaseValue;
int BedValue;
int power = A5;
int isitarmed;
int armedcommand;

void setup() {
 pinMode(BackDoor,INPUT);
 pinMode(Front,INPUT);
 pinMode(Garage,INPUT);
 pinMode(Basement,INPUT);
 pinMode(Bedroom,INPUT);
 pinMode(power,OUTPUT);
 Particle.variable("Bdoor", &BDvalue, INT);
 Particle.variable("Fdoor", &FDvalue, INT);
 Particle.variable("Gdoor", &GValue, INT);
 Particle.variable("Armed", &armedcommand, INT);
 analogWrite(power, HIGH);
 Particle.function("Arm",Armed);
}

void loop() {   
BedValue = analogRead(Bedroom);
delay (1000);

BaseValue = analogRead(Basement);  
delay (1000);

GValue = analogRead(Garage);  
delay (1000);

BDvalue = analogRead(BackDoor);  
delay (1000);

FDvalue = analogRead(Front);  
delay (1000);



if (armedcommand == 1) {

    if (BaseValue <3000) {
     Particle.publish("Door_Open","Basement",60,PRIVATE);
     delay(10000);
    }
    else {
    }
    if (GValue <3000) {
        Particle.publish("Door_Open","Garage",60,PRIVATE);
        delay(10000);
    }
    else {
    }
    if (BDvalue <3000) {
        Particle.publish("Door_Open","Back_Door",60,PRIVATE);
        delay(10000);
    }
    else {
    }
    if (FDvalue <3000) {
        Particle.publish("Door_Open","Front_Door",60,PRIVATE);
        delay(10000);
    }
    else {
    }
    if (BedValue <3000) {
        Particle.publish("Door_Open","Bedroom_Door",60,PRIVATE);
        delay(10000);
    }
    else {
    }
  }
}

int Armed(String command){
    if (command=="on") {
        armedcommand=1;
        return 3;
    }
    else if (command=="off") {
        armedcommand=0;
        return 2;
        }
    else {
        return 5;
    }
}

#9

It seems to be working for me too. What type of sensors are you using to detect the door states?

All the else clauses you have in the if (armedcommand == 1) block are unnecessary, so should be deleted unless you plan to add code to them.

Do you really want to publish on a timed basis like you are, or would it be better to only publish when one of the doors changes from closed to open or vise versa?


#10

Actually the StringClass has several equality (and over logical) operator overloads like “==” that allow for that kind of comparison.

As a side note: If I had an alarm system I’d want to arm via a Particle.function() I’d treat any parameter apart from exactly one less obvious than off as an arm command. After all, I guess you rather want the alarm inadvertently armed than not.
You may add an additional parameter like “check” to return you the current status.

like this

int Armed(String command) {
  if (command == "secretDisarm") { // explicit disarm command
    armedcommand = 0;
  }
  else if (command != "check") {   // arm by default (only "secredDisarm" and "check" won't)
    armedcommand = 1; 
  }

  return armedcommand;            // return the state that actually is set in all cases
}

I also don’t really see why you are using analogRead() instead of digitalRead(). Are your sensors giving you bad (non digital) readings?
I would understand if you had some “absence”/“fault” check on the sensors where you check for a minimum reading of a closed sensor, but that seems missing too.
BTW, when using analogRead() you should not set pinMode(pin, INPUT).

There is no need to wait 1000ms between your pin reads? Also these other 10sec delays impair your ability to detect other events.
If possible I’d even go for interrupts to check for state change on the sensors.

In the other thread you already were advised to drop the three-parameter Particle.variable() syntax and check the docs for the current syntax.


#11

Not at all your problem, but you are more likely to see that snippet (out in the wild) look like this

int Armed(String command){
    if (command=="on") {
        armedcommand=1;
        return 1;  // one is the equivalent of True in binary and matches the value put into armedcommand
    }
    else if (command=="off") {
        armedcommand=0;
        return 0;  // zero is the equivalent of False in binary and matches the value put into armedcommand
        }
    else {
        return -99;  // value that is obviously not expected!!
    }
}

and use camelCase consistently for easier to read code

2¢ please…

:slight_smile:


#12

I know some C++ implementations overload the operator but I didn’t see anything about it in the particle reference (and I did look before posting my earlier reply). Did I miss it?


#14

It’s not really documented, but since the software is open source you can find more than what’s documented


Garage Door Detector Problem
#15

Lots of questions to answer. Thanks you guys for helping me… But I think I have most of them.

The reason I went to analog over digital was probably due to my lack of understanding of the loop functions. I tested it and it works either way.

As for the Particle.variable syntax, the guide still shows three variables. So I must not be looking at the right place. Please let me know where else to look.

As for the 10 sec delays. This was to avoid IFTTT sending me 100’s of notifications when I door opened. I am up for any other ways around this, but with my two kids going in and out and never closing a door it was my only work around.


#16

The Particle.variable syntax is here. Look at the beginning of that section for the current syntax (the pre-0.4.7 syntax that you’re using is shown further down).


#17

You’d usually do that with a state-change-check.
e.g.

bool lastState = false;
...
  if (BaseValue < 3000 && lastState != true) {
    lastState = true;
    Particle.publish("Door_Open","Basement",60,PRIVATE);
    delay(1000);  // to cater for event rate limit
  }
  else if (BaseValue >= 3000) {
    lastState = false;
  }

but with digitalRead() that would get even simpler.


#18

I updated the code with Bool and removed some of the stuff I don’t need. Seems to be working the way I want it.

Thanks again for all the help.

int BackDoor = A0;
int Front= A3;
int Garage = A1;
int Basement = A2;
int Bedroom = A4;
int BDvalue;
int FDvalue;
int GValue;
int BaseValue;
int BedValue;
int armedcommand;

void setup() {
 pinMode(BackDoor,INPUT);
 pinMode(Front,INPUT);
 pinMode(Garage,INPUT);
 pinMode(Basement,INPUT);
 pinMode(Bedroom,INPUT);
 Particle.variable("Bdoor", BDvalue);
 Particle.variable("Fdoor", FDvalue);
 Particle.variable("Gdoor", GValue);
 Particle.variable("Armed", armedcommand);
 Particle.function("Arm",Armed);
}

void loop() {   
BedValue = analogRead(Bedroom);
BaseValue = analogRead(Basement);  
GValue = analogRead(Garage);  
BDvalue = analogRead(BackDoor);  
FDvalue = analogRead(Front);  

bool lastState = false;

  if (BaseValue < 3000 && lastState != true && armedcommand==1) {
    lastState = true;
    Particle.publish("Door_Open","Basement",60,PRIVATE);
    delay(10000);  // to cater for event rate limit
  }
  else if (BaseValue >= 3000) {
    lastState = false;
  }
 else {
 }
 
bool lastState1 = false;

  if (GValue < 3000 && lastState1 != true && armedcommand==1) {
    lastState1 = true;
    Particle.publish("Door_Open","Garage",60,PRIVATE);
    delay(10000);  // to cater for event rate limit
  }
  else if (GValue >= 3000) {
    lastState1 = false;
  }
 else {
 }
 
 bool lastState2 = false;

  if (BedValue < 3000 && lastState2 != true && armedcommand==1) {
    lastState2 = true;
    Particle.publish("Door_Open","Bed Room",60,PRIVATE);
    delay(10000);  // to cater for event rate limit
  }
  else if (BedValue >= 3000) {
    lastState2 = false;
  }
 else {
 }
 
 bool lastState3 = false;

  if (FDvalue < 3000 && lastState3 != true && armedcommand==1) {
    lastState3 = true;
    Particle.publish("Door_Open","Front",60,PRIVATE);
    delay(10000);  // to cater for event rate limit
  }
  else if (FDvalue >= 3000) {
    lastState3 = false;
  }
 else {
 }
 
 bool lastState4 = false;

  if (BDvalue < 3000 && lastState4!= true && armedcommand==1) {
    lastState4 = true;
    Particle.publish("Door_Open","Back",60,PRIVATE);
    delay(10000);  // to cater for event rate limit
  }
  else if (BDvalue >= 3000) {
    lastState4 = false;
  }
 else {
 }
}

int Armed(String command){
    if (command=="on") {
        armedcommand=1;
        return 3;
    }
    else if (command=="off") {
        armedcommand=0;
        return 2;
        }
    else {
        return 5;
    }
}

#19

I am using 1000ms for the delay - 10000ms seems a bit much and that was the reason for suggesting the state-change-check in the first place.

BTW, the bool in my sample was meant to be global (hence the indent level of zero) while the if() statement is indented one level.

Also revealing to see well meant advice not been considered
Particle.Function () losing its value


#20

I rewrote it and will test it tonight. It makes more sense using bool only once.


#21

Ok. this seems to be working. I had to put the delay back at 5000 to prevent an IFTTT notification every second. I think I did something wrong with the bool that didn’t prevent publish events constantly. I also added a function to check the individual values of each door if I need to check. I did get the digital signal to work, but I left the analog signal for now.


int BackDoor = A0;
int Front= A3;
int Garage = A1;
int Basement = A2;
int Bedroom = A4;
int BDvalue;
int FDvalue;
int GValue;
int BaseValue;
int BedValue;
int armedcommand;


void setup() {
 pinMode(BackDoor,INPUT);
 pinMode(Front,INPUT);
 pinMode(Garage,INPUT);
 pinMode(Basement,INPUT);
 pinMode(Bedroom,INPUT);
 Particle.function("Arm",Armed);
 Particle.function("Door",doorvalue);
}

void loop() {   
BedValue = analogRead(Bedroom);
BaseValue = analogRead(Basement);  
GValue = analogRead(Garage);  
BDvalue = analogRead(BackDoor);  
FDvalue = analogRead(Front);  

bool lastState = false;

  if (BaseValue < 3000 && lastState != true && armedcommand==1) {
    lastState = true;
    Particle.publish("Door_Open","Basement",60,PRIVATE);
    delay(5000);  // to cater for event rate limit
  }
  else if (BaseValue >= 3000) {
    lastState = false;
  }
 else {
 }

  if (GValue < 3000 && lastState != true && armedcommand==1) {
    lastState = true;
    Particle.publish("Door_Open","Garage",60,PRIVATE);
    delay(5000);  // to cater for event rate limit
  }
  else if (GValue >= 3000) {
    lastState = false;
  }
 else {
 }
  if (BedValue < 3000 && lastState != true && armedcommand==1) {
    lastState = true;
    Particle.publish("Door_Open","Bed Room",60,PRIVATE);
    delay(5000);  // to cater for event rate limit
  }
  else if (BedValue >= 3000) {
    lastState = false;
  }
 else {
 }
  if (FDvalue < 3000 && lastState != true && armedcommand==1) {
    lastState = true;
    Particle.publish("Door_Open","Front",60,PRIVATE);
    delay(5000);  // to cater for event rate limit
  }
  else if (FDvalue >= 3000) {
    lastState = false;
  }
 else {
 }
  if (BDvalue < 3000 && lastState!= true && armedcommand==1) {
    lastState = true;
    Particle.publish("Door_Open","Back",60,PRIVATE);
    delay(5000);  // to cater for event rate limit
  }
  else if (BDvalue >= 3000) {
    lastState = false;
  }
 else {
 }
}

int Armed(String command){
    if (command=="on") {
        armedcommand=1;
        return 3;
    }
    else if (command=="off") {
        armedcommand=0;
        return 2;
        }
    else {
        return 5;
    }
}

int doorvalue(String command){
    if (command=="garage"){
    return GValue;
    }
    else if (command=="backdoor") {
        return BDvalue;
    }
    else if (command=="frontdoor"){
        return FDvalue;
    }
    else if (command=="bedroomdoor"){
        return BedValue;
    }
    else if (command=="basementdoor"){
        return BaseValue;
    }
}


#22

Yes, you did.
You still have lastState as local variable and you need one instance of a lastState variable per state you want to keep track of (aka per sensor).

Your doorvalue() is missing a return value for the case you submit an unsupported command.

And I will repeat what I keep saying to others too:
When you have code blocks that do the absolutely same thing but only differ in variable names, then you should use arrays, loops and possibly enums to reduce code by reusing the active part of the code and just substitute the variables.

Potential candidates for that kind of cleanup:

 pinMode(BackDoor,INPUT);
 pinMode(Front,INPUT);
 pinMode(Garage,INPUT);
 pinMode(Basement,INPUT);
 pinMode(Bedroom,INPUT);
 // and
 BedValue = analogRead(Bedroom);
 BaseValue = analogRead(Basement);  
 GValue = analogRead(Garage);  
 BDvalue = analogRead(BackDoor);  
 FDvalue = analogRead(Front);  
 // and multiple instances of this block
 if (BaseValue < 3000 && lastState != true && armedcommand==1) {
    lastState = true;
    Particle.publish("Door_Open","Basement",60,PRIVATE);
    delay(5000);  // to cater for event rate limit
 }
 else if (BaseValue >= 3000) {
    lastState = false;
 }
 // and
 if (command=="garage"){
    return GValue;
 }
 else if (command=="backdoor") {
     return BDvalue;
 }
 else if (command=="frontdoor"){
     return FDvalue;
 }
 else if (command=="bedroomdoor"){
     return BedValue;
 }
 else if (command=="basementdoor"){
     return BaseValue;
 }

So your line count could easily be reduced by two thirds (I boiled it down to ~40 lines).


#23

Update. Adding resisters from each sensor to ground has helped the problem too. Even with the code above, I was getting two notifications. I put a 10ohm resister to ground on each sensor. Semi-related to another problem I had. Garage Door Detector Problem