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

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:
https://github.com/spark/firmware/blame/develop/wiring/inc/spark_wiring_cloud.h

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

Thanks, that makes sense. I went through and cleaned things up a bit. Everything is working great now.

#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  // How often to sample in milliseconds

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

// Variables
int lastPub;
int pubDelay = 5000;  // How often to publish in milliseconds
int tempf;
int humidity;
int targettemp = 60;
int blue = D7;
int garageDoorRelay = D5;
int furnaceRelay = D6;

// furnaceHeat shows whether the furnace is running or not
int furnaceHeat = 0;
// furnaceActive enables the furnace to run
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", tempf);
  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() {
  // Check if we need to start the next sample
  if (millis() > DHTnextSampleTime) {
    if ( !bDHTstarted ) {  // start the sample
      DHT.acquire();
      bDHTstarted = true;
      digitalWrite(blue, HIGH);
    }

    if ( !DHT.acquiring() ) {  // has sample completed?
      humidity = DHT.getHumidity();
      tempf = DHT.getFahrenheit();

      // Turn the furnace on or off if necessary
      heatGarage();

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

  if ( (millis() - lastPub) > pubDelay ) {
    blinkPub();
    lastPub = millis();
  }
}

int blinkPub() {
  // 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");

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

// POST functions
// These  function automagically get called upon a matching POST request
int garageDoor(String command) {
  if ( command == "activate" ) {
    activateGarageDoor();
    return 1;
  }
  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.length() > 0) {
    setFurnaceTemp(command);
    return 1;
  } else {
    return -1;
  }
}

// POST helper functions
int activateGarageDoor() {
  digitalWrite(garageDoorRelay, LOW);
  delay(250);
  digitalWrite(garageDoorRelay, HIGH);
  Particle.publish("Garage Door", "Active");
  return 1;
}
int heatGarage() {
  if (furnaceActive) {
    if (targettemp >= tempf) {
      digitalWrite(furnaceRelay, LOW);
      furnaceHeat = 1;
      Particle.publish("Furnace", "On");
      return 1;
    } else {
      digitalWrite(furnaceRelay, HIGH);
      furnaceHeat = 0;
      Particle.publish("Furnace", "Off");
      return -1;
    }
  } else {
    digitalWrite(furnaceRelay, HIGH);
    furnaceHeat = 0;
    Particle.publish("Furnace", "Off");
    return -1;
  }
}
int setFurnaceTemp(String command) {
  targettemp = command.toInt();
  return 1;
}
int furnaceOn() {
  furnaceActive = true;
  return 1;
}
int furnaceOff() {
  furnaceActive = false;
  return 1;
}
1 Like

I’m having a similar if not exact same problem not being able to read variables. I’m a noob and am struggling to understand how to apply the solution to my situation.
I have two DHT22 sensors reading temps from my refridgerator and interior space. Everything is working as expected except I’m not able to query the particle variables. (and I’m getting odd spikes in the readings, but that’s for another post)
Can anyone help me apply the solution above to my code? Much appreciated;

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

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

//token for ubidots
#define TOKEN "abc123abc123abc123abc123" 

#define DHT1PIN 2                               // fridge temp
#define DHT2PIN 4                               // internal temp

#define DHTTYPE DHT22                           // DHT 22 (AM2302)

Ubidots ubidots(TOKEN);

DHT dhtFridge(DHT1PIN, DHTTYPE);
DHT dhtInternal(DHT2PIN, DHTTYPE);

// Define variables
double fridgeTemp = 0;
double internalTemp = 0;

void setup()
{
  Particle.variable("fridgeT", &fridgeTemp, DOUBLE);     //make fridge temps avail via var
  Particle.variable("internalT", &internalTemp, DOUBLE); //make internal temps avail via var
  dhtFridge.begin();
  dhtInternal.begin(); 
  Serial.begin(9600);
  delay(10000);
   } 

void loop()
{
  //Read humidity into humidity vars  
  float fridgHumid = dhtFridge.getHumidity();
  float internalHumid= dhtInternal.getHumidity();

  //Read Farenheit into Temp vars
  float fridgeTemp = dhtFridge.getTempFarenheit();
  float internalTemp = dhtInternal.getTempFarenheit();

  ubidots.add("fridgeTemp", fridgeTemp);	    //define fridgeTemp as ubidot var
  ubidots.add("internalTemp", internalTemp);	//define interalTemp as ubidot var
  ubidots.sendAll();                            //send vars to ubidot
  delay(60000);                                 //delay sixty sec

  // Publish temp var for reading remotely
  Particle.publish("fridgeTemp", String(fridgeTemp) + " °F");
  Particle.publish("internalTemp", String(internalTemp) + " °F");
}

This form is deprecated, try this instead

  Particle.variable("fridgeT", fridgeTemp);     //make fridge temps avail via var
  Particle.variable("internalT", internalTemp); //make internal temps avail via var

And don't redeclare the used variables locally, that just hides the global variable that you exposed and hence they won't be updated. Only the local ones will receive the value, but will vanish once loop() finishes.

void loop() {
  ...
  //Read Farenheit into Temp vars
  float fridgeTemp = dhtFridge.getTempFarenheit();
  float internalTemp = dhtInternal.getTempFarenheit();
  ...
}

Just remove float - BTW, your global vars are double, so why are the locals float anyway?

2 Likes

Perfect! that did the trick. Learn something everyday. I appreciate the help. As for the formatting of the variables, that was a leftover from some comments I saw earlier in the thread about “overloading” the variables. Obviously didn’t work. I’m not sure why I left the local var’s as float. Must have been another remnant of testing…

1 Like