Trouble reading values from particle.variable() [SOLVED]

I’m not really sure what I’m doing wrong here. Wondering if someone can point out what I’m missing. I have a couple of variables that I’ve exposed to the cloud api but they don’t seem to be displaying.

Temperature and humidity always return 0, furnaceheat returns the bool value as an int so it ends up being displayed as a long weird positive or negative number.

// This #include statement was automatically added by the Particle IDE.
#include "PietteTech_DHT/PietteTech_DHT.h"

// DHT parameters
#define DHTTYPE  DHT22              // Sensor type DHT11/21/22/AM2301/AM2302
#define DHTPIN   D1         	      // Digital pin for communications
#define DHT_SAMPLE_INTERVAL   2000  // Sample every two seconds

// Use uFL External Antenna
STARTUP(WiFi.selectAntenna(ANT_EXTERNAL));

// Variables
int sampInt = 5000; //sample interval in milliseconds
int tempf;
int temperature;
int humidity;
int targettemp = 70;
int blue = D7;
int garageDoorRelay = D5;
int furnaceRelay = D6;
bool furnaceActive = false;
bool furnaceHeat = false;

//Post Function Declarations
int garageDoor(String command);
int furnOnOff(String command);
int setFurTemp(String command);

// Declaration
void dht_wrapper();

// Lib Initialize
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);

// globals
unsigned int DHTnextSampleTime; // Next time we want to start sample
bool bDHTstarted;		            // flag to indicate we started acquisition
int n;                          // counter

void setup() {
  //Hardware pin assignments
  pinMode(blue, OUTPUT);
  pinMode(garageDoorRelay, OUTPUT);
  pinMode(furnaceRelay, OUTPUT);

  // Variables Exposed to Cloud
  Particle.variable("temperature", temperature);
  Particle.variable("targettemp", targettemp);
  Particle.variable("humidity", humidity);
  Particle.variable("furnaceheat", furnaceHeat);

  // Functions exposed to Cloud
  Particle.function("garagedoor", garageDoor);
  Particle.function("furnonoff", furnOnOff);
  Particle.function("setfurtemp", setFurTemp);

  //DHT
  DHTnextSampleTime = 0;
  
  //Start out with our relays turned on
  digitalWrite(garageDoorRelay, HIGH);
  digitalWrite(furnaceRelay, HIGH);
}

void dht_wrapper() {
  DHT.isrCallback();
}

void loop()
{
  //Wait a bit between loops
  delay(sampInt);
  int temperature = tempf;
  // Check if we need to start the next sample
  if (millis() > DHTnextSampleTime) {
    if (!bDHTstarted) {		// start the sample
      DHT.acquire();
      bDHTstarted = true;
    }

    if (!DHT.acquiring()) {		// has sample completed?

      // get DHT status
      //int result = DHT.getStatus();
      int humidity = DHT.getHumidity();
      int tempf = DHT.getFahrenheit();
      //int tempc = DHT.getCelsius();
      //int tempk = DHT.getKelvin();
      //int dp = DHT.getDewPoint();
      //int dpslow = DHT.getDewPointSlow();
      

      //Turn the built in LED on to indicate publishing
      digitalWrite(blue, HIGH);

      //* Publish readings - uncomment/comment the values you'd like to publish

      Particle.publish("Humidity", String(humidity) + "%");
      Particle.publish("Temperature", String(tempf) + " °F");
      //Particle.publish("Temperature", String(tempc) + " °C");
      //Particle.publish("Temperature", String(tempk) + " °K");
      //Particle.publish("Dew Point", String(dp) + " %");
      //Particle.publish("Dew Point", String(dpslow) + " %");

      //Turn the built in LED off indicate publishing finished
      delay(250);
      digitalWrite(blue, LOW);

      n++;  // increment counter
      bDHTstarted = false;  // reset the sample flag so we can take another
      DHTnextSampleTime = millis() + DHT_SAMPLE_INTERVAL;  // set the time for next sample
    }
  }
}

// After Loop - POST functions
// These  function automagically get called upon a matching POST request
int garageDoor(String command)
{
  // look for the matching argument "activate"
  if(command == "activate")
  {
    // function to run
    activateGarageDoor();
    return 1;
  }
  else return -1;
}
int furnOnOff(String command)
{
  // look for the matching argument "activate"
  if(command == "on")
  {
    // function to run
    furnaceOn();
    return 1;
  }
  if(command == "off")
  {
    // function to run
    furnaceOff();
    return 1;
  }
  return -1;
}
int setFurTemp(String command)
{
    return 1;
}

// POST helper functions
int activateGarageDoor() {
    digitalWrite(garageDoorRelay, LOW);
    delay(250);
    digitalWrite(garageDoorRelay, HIGH);
    return 1;
}

int setFurnaceTemp() {
    return 1;
}
int furnaceOn() {
    bool furnaceActive = true;
    return 1;
}
int furnaceOff() {
    bool furnaceActive = false;
    return 1;
}

In the screenshot below you can see I’m able to see the variable without issue, but targettemp seems to be the only one that’s working.

Remove that delay(sampInt) and see what happens. It could just be blocking the system too much.

@mkokes looking over your code nothing jumps out at me. What happens when you throw Int TempF and int humidity inside of a debug and look at it from your logs on your dashboard, do you still get those values as 0?

If your not sure how to do that you can follow this example here http://dustinrcollins.com/debugging-code-for-the-particle-sparkphoton

Just tested, no luck still zeros

Within the loop I’m also publishing the values to the Cloud API and that seems to be working fine. The value are publishing successful and correctly.

Particle.publish("Humidity", String(humidity) + "%");
Particle.publish("Temperature", String(tempf) + " °F");

@mkokes huh, Is there some how a variable type mismatch on what your second screenshot is expecting? Cause it looks like what ever interface you have in your second screen shot is expecting an Int, but it may be getting sent over as a string instead. what happens if you change the expected type on what ever interface you are using in the Second screen shot of the initial post?

I believe particle.publish() only supports strings so I’m converting the value to a string there, but from what I can tell particle.variable() should support int and bool so I’m not doing any sort of conversion there.

@mkokes your right in the fact that particle.variable supports int and bool, try changing it so the particle.variables look like this.

Particle.variable("temperature", temperature, INT);
Particle.variable("targettemp", targettemp, INT);
Particle.variable("humidity", humidity, INT);
Particle.variable("furnaceheat", furnaceHeat, INT); //this one will have to convert from bool to int and that should fix the weird issue with the number... I think

I am wondering if it is not sending right as the variable types are not defined in the right way… it shouldn’t be needed to make it work, but i have seen weirder things happen.

thanks for sticking with me as we troubleshoot this.

If you are using the three parameter overload of Particle.variable() with INT you’d need to write it this way

Particle.variable("temperature", &temperature, INT);
Particle.variable("targettemp", &targettemp, INT);
Particle.variable("humidity", &humidity, INT);
Particle.variable("furnaceheat", &furnaceHeat, INT);

I have noticed that the two parameter overloads didn’t work for intand double at some point, but I’m not sure why and if this is meant to be, but @mdma might have a word to add :wink:

1 Like

Are you sure they were at one point not working? It doesn’t look like anything was changed for int/double since the original commit: https://github.com/spark/firmware/blame/develop/wiring/inc/spark_wiring_cloud.h

And that commit included an API test:

Hmm, I’m pretty sure of that.
I had used the two param overload for other types and one INT and while the others worked the INT didn’t so I used the three param overload without any alterations to my code and then it worked.
But since I had a solution I didn’t bother to further investigate, but I can try it out now.


Update

I tried again and it does work. Sorry for the confusion :blush:

I see it. You’re declaring the variables globally, and locally in loop(). Local gets priority in the function, so your globals aren’t updating.

3 Likes

Doh’, I completely missed that, but sure thing - this is the reason for not seeing the value.

Good catch :+1:

That did it! Thank you all very much for the help.

I’m able to retrieve integers now via curl, but the boolean value I’m using for the furnaceheat variable, returned as a odd looking integer. Is this normal or am I doing something wrong there as well?

curl returns this for furnaceheat

{
  "cmd": "VarReturn",
  "name": "furnaceheat",
  "result": 134616679,
  "coreInfo": {
    "last_app": "",
    "last_heard": "2016-01-14T15:24:09.505Z",
    "connected": true,
    "last_handshake_at": "2016-01-14T15:23:39.936Z",
    "deviceID": "1c002a001347343432313031",
    "product_id": 6
  }

That is a little weird. It could be reading 4 bytes while the bool is 1 byte, and you’re getting memory after it. A bool is 0 / -1 so if it converts to unsigned long or something it might turn into -127 in 4 bytes somewhere, or who knows? This is safer:

return (bool_value == true) ? 1 : 0;

That will convert the bool condition to an int. Just return bool_value ? 1 : 0; would work as well, but may not be proper syntax.

1 Like

perfect! thanks again!

Could you repost your current code, since in your code above you don’t ever set furnaceHeat to anything else than false.

No problem, not the ideal solution, but I ended up just using an int for furnaceHeat. Would’ve preffered to use a bool value, but this works.

// This #include statement was automatically added by the Particle IDE.
#include "PietteTech_DHT/PietteTech_DHT.h"

// DHT parameters
#define DHTTYPE  DHT22              // Sensor type DHT11/21/22/AM2301/AM2302
#define DHTPIN   D1         	      // Digital pin for communications
#define DHT_SAMPLE_INTERVAL   2000  // Sample every two seconds

// Use uFL External Antenna
STARTUP(WiFi.selectAntenna(ANT_EXTERNAL));

// Variables
int sampInt = 5000; //sample interval in milliseconds
int tempf;
int temperature;
int humidity;
int targettemp = 70;
int blue = D7;
int garageDoorRelay = D5;
int furnaceRelay = D6;

// furnaceHeat shows whether the furnace is running or not and furnaceActive enables the furnace to run
int furnaceHeat = 0;
bool furnaceActive = false;


//Post Function Declarations
int garageDoor(String command);
int furnOnOff(String command);
int setFurTemp(String command);

// Declaration
void dht_wrapper();

// Lib Initialize
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);

// globals
unsigned int DHTnextSampleTime; // Next time we want to start sample
bool bDHTstarted;		            // flag to indicate we started acquisition
int n;                          // counter

void setup() {
  //Hardware pin assignments
  pinMode(blue, OUTPUT);
  pinMode(garageDoorRelay, OUTPUT);
  pinMode(furnaceRelay, OUTPUT);

  // Variables Exposed to Cloud
  Particle.variable("temperature", temperature);
  Particle.variable("targettemp", targettemp);
  Particle.variable("humidity", humidity);
  Particle.variable("furnaceheat", furnaceHeat);

  // Functions exposed to Cloud
  Particle.function("garagedoor", garageDoor);
  Particle.function("furnonoff", furnOnOff);
  Particle.function("setfurtemp", setFurTemp);

  //DHT
  DHTnextSampleTime = 0;
  
  //Start out with our relays turned on
  digitalWrite(garageDoorRelay, HIGH);
  digitalWrite(furnaceRelay, HIGH);
}

void dht_wrapper() {
  DHT.isrCallback();
}

void loop()
{
  //Wait a bit between loops then grab the temperature
  delay(sampInt);
  temperature = tempf;
  
  // Turn the furnace on or off if necessary
  heatGarage();
  
  // Check if we need to start the next sample
  if (millis() > DHTnextSampleTime) {
    if (!bDHTstarted) {		// start the sample
      DHT.acquire();
      bDHTstarted = true;
    }

    if (!DHT.acquiring()) {		// has sample completed?

      // get DHT status
      //int result = DHT.getStatus();
      humidity = DHT.getHumidity();
      tempf = DHT.getFahrenheit();
      //int tempc = DHT.getCelsius();
      //int tempk = DHT.getKelvin();
      //int dp = DHT.getDewPoint();
      //int dpslow = DHT.getDewPointSlow();
      

      //Turn the built in LED on to indicate publishing
      digitalWrite(blue, HIGH);

      //* Publish readings - uncomment/comment the values you'd like to publish

      Particle.publish("Humidity", String(humidity) + "%");
      Particle.publish("Temperature", String(tempf) + " °F");
      //Particle.publish("Temperature", String(tempc) + " °C");
      //Particle.publish("Temperature", String(tempk) + " °K");
      //Particle.publish("Dew Point", String(dp) + " %");
      //Particle.publish("Dew Point", String(dpslow) + " %");

      //Turn the built in LED off indicate publishing finished
      delay(250);
      digitalWrite(blue, LOW);

      n++;  // increment counter
      bDHTstarted = false;  // reset the sample flag so we can take another
      DHTnextSampleTime = millis() + DHT_SAMPLE_INTERVAL;  // set the time for next sample
    }
  }
}

// After Loop - POST functions
// These  function automagically get called upon a matching POST request
int garageDoor(String command)
{
  if(command == "activate")
  {
    activateGarageDoor();
    return 1;
  }
  else return -1;
}
int furnOnOff(String command)
{
  if (command == "on") {
    //furnaceOn();
    return 1;
  }
  if(command == "off") {
    //furnaceOff();
    return 1;
  }
  return -1;
}
int setFurTemp(String command)
{
    if (command == "on") {
        setFurnaceTemp();
        return 1;
    } else {
        return -1;
    }
}

// POST helper functions
int activateGarageDoor() {
    digitalWrite(garageDoorRelay, LOW);
    delay(250);
    digitalWrite(garageDoorRelay, HIGH);
    return 1;
}
int heatGarage() {
    if (targettemp >= temperature) {
        if (furnaceActive = true) {
            digitalWrite(furnaceRelay, LOW);
            furnaceHeat = 1;
            return 1;
        } else {
            digitalWrite(furnaceRelay, HIGH);
            furnaceHeat = 0;
            return -1;
        }
    } else {
        digitalWrite(furnaceRelay, HIGH);
        furnaceHeat = 0;
        return -1;
    }
}
int setFurnaceTemp() {
    targettemp = 70;
    return 1;
}
int furnaceOn() {
    furnaceActive = true;
    return 1;
}
int furnaceOff() {
    furnaceActive = false;
    return 1;
}

delay(sampInt) is 5 seconds, while DHT_SAMPLE_INTERVAL is 2 seconds. It’s not good to put long delays in your main loop because it’s stopping everything else from running, but that will cause it to check the 2 second timeout every 5 seconds.

Try getting code to run in and out of the loop as fast as possible with few delays, and you’ll notice it’s more responsive. Also for timing, this method will work better when millis() rolls over.

if( (millis() - last) > TIMEOUT)
{
  last = millis();
  ...
}
1 Like