Incorrect data output with RHT03 temp/humidity sensor using Argon [SOLVED but now using DHT11]

I’m trying to adapt a simple code I’ve used successfully for the past two (2) years on the Electron to my Argon. In the case of my Electron, the data posts to Ubidots. I’ve successfully used Particle.publish with this same Argon when I had a simple temperature sensor connected but now I’m trying to switch it to an RHT03 temp/humidity sensor. With the following code I’m getting humidity readings of 0 and temperature readings of 32 (just now when I checked it’s reporting 66 for temp and 825 for humidity!) I’ve double checked to make sure I have the wiring connected properly (there are only 3 wires.)

Since I’m a hobbyist without much coding experience it wouldn’t surprise me if my problem is with my program. But I’m also wondering if it could be that the library for the RHT03 is not compatible with the Argon.

Any suggestions?

// This #include statement was automatically added by the Particle IDE.
#include <SparkFunRHT03.h>

const int RHT03_DATA_PIN = D3;//RHT data pin
RHT03 rht;//creates the RHT03 object

int tempF = 0;
int humidity = 0;

char *message = "Room Environment";
String aString;

void setup()

{
  rht.begin(RHT03_DATA_PIN);//initialize the RHT03 sensor
  
  
  // variable name max length is 12 characters long
  Particle.variable("tempF", tempF);
  Particle.variable("humidity", humidity);
}

void loop()

{
  int update = rht.update();//read the sensor
  int tempF = rht.tempF();
  int humidity = rht.humidity();

    Particle.publish("tempF", String(tempF));
    Particle.publish("humidity", String(humidity));
    
    delay(5000);
}

I would re-think your variable declarations to start. First, you declare int tempF=0; and int humidity = 0; as global variables and set them as the source for the Particle.variable()'s in the Setup. But everytime you run through loop, you re-declare the same variables with a local scope. Then you publish the variables but which variable is published; the locally scoped or globally scoped variable?

Also, I would remove the use of String and combine your separate Particle.publish() into a single combined publish. You can change the event name in the below sample as you see fit.

Maybe something like this:

// This #include statement was automatically added by the Particle IDE.
#include <SparkFunRHT03.h>

const int RHT03_DATA_PIN = D3;//RHT data pin
RHT03 rht;//creates the RHT03 object

//Global variables to store environmental data.
float tempF = 0;
float humidity = 0;

//Global variable to store millis timer information.
unsigned long lastPubMillis = 0;
unsigned long pubInterval = 5000;

//Global variables to store messages.
char *message = "Room Environment";
char msg[128];

void setup()
{
    rht.begin(RHT03_DATA_PIN); //initialize the RHT03 sensor
 
    // variable name max length is 12 characters long
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
}

void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) {
        int update = rht.update(); //read the sensor

        //Update your global environmental variables.
        tempF = rht.tempF();
        humidity = rht.humidity();

        //Create your message to publish and load into the message buffer.
        snprintf(msg,arraySize(msg)-1,"Temp:%4.2f;Humidity:%4.2f",tempF,humidity);

        //Send your data.
        Particle.publish("EnviromentData",msg);

        //Update your pub millis timer.
        lastPubMillis = millis();
    }
}
2 Likes

@ninjatill, thanks for your help. I’m tied up at the present with a rambunctious 4-year old grandson but I stole a minute to load your code as-is (with the added library). I’ll make time tonight to learn from your suggestions. With the new program my initial readings were t = 32 and h = 0 followed after a few minutes with t = 71 (sounds right) and h = 112. But then it becomes t = 795 and h = 1238 and now t = 234 and h = 3699. I’ll dive into this more tonight.

I also just remembered I have a temp/humidity sensor from the Grove Starter Kit. That box has been sitting under my desk so long I forgot what was in it!

If you look at the RHT library, the tempF and humidity functions return a float, not an integer. So you would need to declare your variables as floats instead.

I will update my example above with floats.

2 Likes

Yes, that issue is confusing to me. Somewhere along the line I cobbled together some code, using integers, for the same sensor in my campervan that is hooked to an Electron and it’s been working great for 2 years.

#include <Ubidots.h>

#define TOKEN ""

#include <SparkFunRHT03.h>//included from the library for the RHT

Ubidots ubidots(TOKEN);

    const int RHT03_DATA_PIN = D1;//provdes temp & humidity inside van
    RHT03 rht;//creates the RHT object
    
    const int pinOut = A2;//provdes temp under van, near macerator (critical component)
    const int pinFridge = A4;//you can guess this one
    
    int tempF = 0;//temp inside van
    int humidity = 0;//humidity inside van
    int tempOut = 0;//outside temp reading
    int tempFridge = 0;//yeah, that one
   
    int SoC = 0;//fuel gauge
    FuelGauge fuel;
   
    int lasttempF = 0;//I'll use these to see if we really need to upload data each time
    int lasthumidity = 0;
    int lasttempOut = 0;
    int lasttempFridge = 0;
    int lastSoC = 0;

    int tempFdelta;
    int humiditydelta;
    int tempOutdelta;
    int tempFridgedelta;
    int SoCdelta;

void setup() {
  
    //pinMode(A2, OUTPUT);//RHT - I only want sensors energized when Electron is awake to save power
    //pinMode(A3, OUTPUT);//TEMP OUT
    //pinMode(A4, OUTPUT);//TEMP FRIDGE
 
    rht.begin(RHT03_DATA_PIN);//initialize the RHT sensor
    
    ubidots.setMethod(TYPE_UDP);
    
    //Serial.begin(9600);//definitely worth checking if this works at my desk before going live
    //while(!Serial.available()) Particle.process(); // start the serial monitor, then press any key

}

void loop() {

    //digitalWrite(A2, HIGH);//power up the sensors
    //digitalWrite(A3, HIGH);
    //digitalWrite(A4, HIGH);
    
    //delay(15000);//necessary delay for RHT to pass unstable status (1 sec), plus warm up (+14 sec)
    
    int update = rht.update();//get temp and humidity readings from inside the van
    int humidity = rht.humidity();
    int tempF = rht.tempF();
    tempF = (tempF-4);//calibration adjustment

    tempOut = ((((((analogRead(pinOut) * (3.3/4095)) *1000.0) - 500)/10)*(9.0/5.0)) + 32.0);//calibrated
    
    tempFridge = ((((((analogRead(pinFridge) * (3.3/4095)) *1000.0) - 500)/10)*(9.0/5.0)) + (32.0-6.0));
    
    SoC = fuel.getSoC();
    
    //Create logic so only significant readings get uploaded to cloud
        tempFdelta = tempF-lasttempF;
        tempFdelta = abs (tempFdelta);
        if(tempFdelta>2){
            //Serial.printlnf("vanTemp %d\n", tempF);
            //Serial.printlnf("lasttempF %d\n", lasttempF);
            //Serial.printlnf("tempFdelta %d\n", tempFdelta);
            ubidots.add("t", tempF);
            lasttempF = tempF;
        }
  
        humiditydelta = humidity-lasthumidity;
        humiditydelta = abs (humiditydelta);
        if(humiditydelta>2){
            //Serial.printlnf("humidity %d\n", humidity);
            ubidots.add("h", humidity);
            lasthumidity = humidity;
        }
        
        tempOutdelta = tempOut-lasttempOut;
        tempOutdelta = abs (tempOutdelta);
        if(tempOutdelta>2){
            //Serial.printlnf("tempOut %d\n", tempOut);
            ubidots.add("o", tempOut);
            lasttempOut = tempOut;
        }
    
        tempFridgedelta = tempFridge-lasttempFridge;
        tempFridgedelta = abs (tempFridgedelta);
        if(tempFridgedelta>2){
            //Serial.printlnf("fridge %d\n", tempFridge);
            ubidots.add("f", tempFridge);
            lasttempFridge = tempFridge;
        }
        
        SoCdelta = SoC-lastSoC;
        SoCdelta = abs (SoCdelta);
        if(SoCdelta>2){
            //Serial.printlnf("SoC %d\n", SoC);
            ubidots.add("b", SoC);
            lastSoC = SoC;
        }

    ubidots.sendAll();
    
    //digitalWrite(3, LOW);//power down the sensors
    //digitalWrite(4, LOW);
    //digitalWrite(5, LOW);
    
    //System.sleep(BTN,FALLING,SLEEP_NETWORK_STANDBY,30);
    
    delay(1200000);//20 minute delay
}

That code also suffers from the same problematic variable re-declarations, data type and scoping problems. I’m not the C++ master so one of the elites might explain why this code would work in some situation and not in others. Looking at it, I don’t know how it was ever working properly. Perhaps since the data is sent to Ubidots, the Ubidots service can somehow interpret the floats even when sent as an integer.

2 Likes

Haha. I’m lucky? All I know is it’s been working and keeps my data usage down to around 2MB per month.

I started over using the temp/humidity sensor in the Grove Starter Kit for Particle Mesh. But when I try to compile I get an error message that says:

argongrovetemphum.ino:2:51: Grove_Temperature_And_Humidity_Sensor.h: No such file or directory

I started with example code linked from:

My current code (that won’t compile) is:

// This #include statement was automatically added by the Particle IDE.
#include <Grove_Temperature_And_Humidity_Sensor.h>

#define DHTPIN D3 //set pin

DHT dht(DHTPIN);

//Global variables to store messages.
char *message = "Room Environment";
char msg[128];

void setup()
{
    dht.begin(); //initialize the sensor
 
    // variable name max length is 12 characters long
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
}

void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) {
        float humidity = dht.getHumidity();
        float tempF = dht.getTempFarenheit();

        //Create your message to publish and load into the message buffer.
        snprintf(msg,arraySize(msg)-1,"Temp:%d;Humidity:%d",h,t);

        //Send your data.
        Particle.publish("Room Environment",msg);

        //Update your pub millis timer.
        lastPubMillis = millis();
    }
}

Change this:

To this:

#include <Seeed_DHT11.h>

You do not have to change the library, simply change the text at the top of the .ino file. For some reason, when you look at the Grove_temperature..._Sensor library, the filenames are "Seeed_DHT11.cpp" and Seeed_DHT11.h". But when you add the library to your project, it adds a totally different include statement. Looks like someone may have copied and pasted and forgot to edit some file names. @rickkas7 may be able to correct, maybe?!?

Probably unrelated, but, you keep moving your variable declarations for tempF and humidity inside of loop(). When you do that, the Particle.variable() functions declared in setup() don't have a valid variable to use. Either comment out the Particle.variables() or create global variables instead. I already demo'ed how to do that above. This is the variable scope problem I described above.

1 Like

Sorry about that, @ninjatill. I hurried the new program while being distracted on the side. I shouldn’t have posted until later, after I had time to digest what you were telling me and check everything. I didn’t mean to waste your time.

I actually left out a whole bunch of stuff. I changed the code per your recommendations, added in the stuff I left out, and it now compiles! But I’ll have to leave it tonight to hook up and test. As a side note, when compiling with floats it tells me I have to use double instead. So that is how my code now reads. I’ll report back tonight.

// This #include statement was automatically added by the Particle IDE.
#include <Seeed_DHT11.h>

#define DHTPIN D3 //set pin

DHT dht(DHTPIN);

double tempF = 0;
double humidity = 0;

unsigned long lastPubMillis = 0;
unsigned long pubInterval = 5000;

//Global variables to store messages.
char *message = "Room Environment";
char msg[128];

void setup()
{
    dht.begin(); //initialize the sensor
 
    // variable name max length is 12 characters long
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
}

void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) {
        humidity = dht.getHumidity();
        tempF = dht.getTempFarenheit();

        //Create your message to publish and load into the message buffer.
        snprintf(msg,arraySize(msg)-1,"Temp:%d;Humidity:%d",tempF,humidity);

        //Send your data.
        Particle.publish("Room Environment",msg);

        //Update your pub millis timer.
        lastPubMillis = millis();
    }
}

No worries, I figured you couldn’t get past the include error so you didn’t see all the other errors. After getting a blank project to compile with that library included, I added the rest of your code and there were a bunch of things missing. Keep on plugging!

1 Like

With your help I got it working, @ninjatill. Very much appreciated. I did end up switching to integers instead of floats or doubles. I still get an occasional wild reading but I’ll smooth those out later. I’m just happy to have my first functional project using a component from the Grove Starter Kit! Now that I have a base to work from I can start playing with the other components in the kit and then see if I can get the Xenons to play nicely. This is a great learning experience and couldn’t happen without people such as yourself.

So here’s my revised, functioning code using an Argon plus the Shield and Temp/Humidity Sensor from the Grove Starter Kit for Particle Mesh:

// This #include statement was automatically added by the Particle IDE.
#include <Seeed_DHT11.h>

#define DHTPIN D4 //set pin

DHT dht(DHTPIN);

int tempF = 0;
int humidity = 0;

unsigned long lastPubMillis = 0;
unsigned long pubInterval = 5000;

//Global variables to store messages.
char *message = "Room Environment";
char msg[128];

void setup()
{
    dht.begin(); //initialize the sensor
 
    // variable name max length is 12 characters long
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
}

void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) {
        humidity = dht.getHumidity();
        tempF = dht.getTempFarenheit();

        //Create your message to publish and load into the message buffer.
        snprintf(msg,arraySize(msg)-1,"Temp = %d;Humidity = %d",tempF,humidity);

        //Send your data.
        Particle.publish("Room Environment",msg);

        //Update your pub millis timer.
        lastPubMillis = millis();
    }
}
2 Likes

The DHT11 continues to work perfectly with my Argon. But because I need additional temperature/humidity sensors, and before I go buy more DHT11 sensors, I’m back to my original question: The RHT03 works fine with the Electron but does not seem to work with the Argon/Xenon (I always get 32 for T, 0 for H.) Is it possible it’s not working because the SparkFunRHT03 library has to be updated for the Argon/Xenon?

My current code for the RHT03:

// This #include statement was automatically added by the Particle IDE.
#include <SparkFunRHT03.h>

const int RHT03_DATA_PIN = D4;
RHT03 rht;

int tempF = 0;
int humidity = 0;

int lasttempF = 0;//I'll use these to get rid of spikes in the data
int tempFdelta;
int lasthumidity = 0;
int humiditydelta;

unsigned long lastPubMillis = 0;
unsigned long pubInterval = 5000;

//Global variables to store messages.
char *message = "Xenon1 Environment";
char msg[128];

void setup()
{
    rht.begin(RHT03_DATA_PIN);//initialize the RHT sensor
 
    // variable name max length is 12 characters long
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
}

void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) 
    {
        int update = rht.update();
        int humidity = rht.humidity();
        int tempF = rht.tempF();

        tempFdelta = tempF-lasttempF;
        tempFdelta = abs(tempFdelta);
        humiditydelta = humidity-lasthumidity;
        humiditydelta = abs(humiditydelta);
        
            if(tempFdelta <2 && humiditydelta <2)
            {
                            //Create your message to publish and load into the message buffer.
                    snprintf(msg,arraySize(msg)-1,"T = %d;H = %d",tempF,humidity);
            
                    //Send your data.
                    Particle.publish("Xenon1 Environment",msg);
            }

        //Update your pub millis timer.
        lastPubMillis = millis();
                            
        lasttempF = tempF;
        lasthumidity = humidity;
    }
}

Do you get the incorrect values via the Particle.variable() or the Particle.publish()? Check both and let us know.

Also, adding debugging output to the serial monitor is very helpful. Try running this slightly modified code which includes serial debugging info. (I did not change any of the variable declarations/re-declarations or anything so we can see where the issue lies… your code vs library.) You should attach the serial monitor after reboot and watch the serial output. You have 10 seconds to get the monitor up to catch the setup output… otherwise you might miss it and will just catch the loop output:

// This #include statement was automatically added by the Particle IDE.
#include <SparkFunRHT03.h>

const int RHT03_DATA_PIN = D4;
RHT03 rht;

int tempF = 0;
int humidity = 0;

int lasttempF = 0; //I'll use these to get rid of spikes in the data
int tempFdelta;
int lasthumidity = 0;
int humiditydelta;

unsigned long lastPubMillis = 0;
unsigned long pubInterval = 5000;

//Global variables to store messages.
char *message = "Xenon1 Environment";
char msg[128];

SerialLogHandler logHandler(LOG_LEVEL_TRACE);

void setup()
{
    //Start serial for console debugging.
    Serial.begin(9600);

    // variable name max length is 12 characters long
    // Declare Particle.variables as soon as possible.
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
    
    //Wait 10 seconds for the serial console to connect.
    waitFor(Serial.isConnected, 10000);
    
    //Initialize and update the sensor.
    rht.begin(RHT03_DATA_PIN);
    rht.update();
    
    //Add debugging output.
    snprintf(msg,arraySize(msg)-1,"Setup Readings:Ts = %d;Hs = %d",tempF,humidity);
    Log.trace(msg);
    
    Log.info("Setup complete.");
}

void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) 
    {
        int update = rht.update();
        int humidity = rht.humidity();
        int tempF = rht.tempF();
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Pre-Filter Readings:Tp = %d;Hp = %d",tempF,humidity);
        Log.trace(msg);

        tempFdelta = tempF-lasttempF;
        tempFdelta = abs(tempFdelta);
        humiditydelta = humidity-lasthumidity;
        humiditydelta = abs(humiditydelta);
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Delta Calcs:Td = %d;Hd = %d",tempFdelta,humiditydelta);
        Log.trace(msg);
        
        if(tempFdelta < 2 && humiditydelta < 2)
        {
            //Create your message to publish and load into the message buffer.
            snprintf(msg,arraySize(msg)-1,"T = %d;H = %d",tempF,humidity);
        
            //Send your data.
            Particle.publish("Xenon1 Environment",msg);
            
            //Add debugging output.
            strcat("Published Data:",msg);
            Log.trace(msg);
        } else {
            Log.error("Delta calcs out of spec... cannot publish.");
        }

        //Update your pub millis timer.
        lastPubMillis = millis();
                            
        lasttempF = tempF;
        lasthumidity = humidity;
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Last Readings Updated:Tl = %d;Hl = %d",lasttempF,lasthumidity);
        Log.trace(msg);
    }
}

Thanks, again, @ninjatill.

I was away for awhile but when I returned I looked at the data and it varied from (T/H) 32/0, 65/6, 3014/33, 227/3284, etc… So it’s all over the place.

The particle.variables both show 0.

I ran your modified code and this is what I get from the serial monitor. This is above my paygrade so I have no idea what any of this means:

0000003155 [app] TRACE: Setup Readings:Ts = 0;Hs = 0
0000003156 [app] INFO: Setup complete.
0000003342 [comm.protocol] INFO: Sending 'S' describe message
0000003346 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 4
0000003542 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 3
0000003543 [comm.protocol] INFO: rcv'd message type=1
0000003544 [comm.protocol] INFO: Sending 'A' describe message
0000003547 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 4
0000003548 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 3
0000003548 [comm.protocol] INFO: rcv'd message type=1
0000005107 [app] TRACE: Pre-Filter Readings:Tp = 32;Hp = 0
0000005107 [app] TRACE: Delta Calcs:Td = 32;Hd = 0
0000005108 [app] ERROR: Delta calcs out of spec... cannot publish.
0000005109 [app] TRACE: Last Readings Updated:Tl = 32;Hl = 0
0000010216 [app] TRACE: Pre-Filter Readings:Tp = 32;Hp = 0
0000010216 [app] TRACE: Delta Calcs:Td = 0;Hd = 0
0000010219 [app] TRACE: T = 32;H = 0
0000010219 [app] TRACE: Last Readings Updated:Tl = 32;Hl = 0
0000010489 [comm.protocol] TRACE: Reply recieved: type=2, code=0
0000010490 [comm.protocol] INFO: message id 5169 complete with code 0.00
0000010492 [comm.protocol] INFO: rcv'd message type=13
0000015343 [app] TRACE: Pre-Filter Readings:Tp = 32;Hp = 0
0000015344 [app] TRACE: Delta Calcs:Td = 0;Hd = 0
0000015347 [app] TRACE: T = 32;H = 0

To fix the scope problem these should just be:

humidity = rht.humidity();
tempF = rht.tempF();

Since they are already defined globally before setup().

Also:

arraySize(msg)-1

Should be:

sizeof(msg)

Also, it’s better practice to use a Software timer when possible, rather than a millis timer in loop.

https://docs.particle.io/reference/device-os/firmware/argon/#software-timers

1 Like

Above your paygrade... give yourself more credit. On the left-most of the log file, there is a millis timestamp which tells you when the corresponding message was written to the log. The [app] message are generated by the code I gave you. It works just like Serial.print() but by using the logging feature, we get nice timestamps. Each one of those [app] messages posts the variable contents at various points in the loop(). What I tried to do was post the variables at all the different times they are updated.

I think the problem is still the global vs local variable declarations. I didn't say it before because I wanted to see this log file. I read up on double variable declarations and the locally-scoped variable will take precedence over the global variable. So with the "last" variables you added, it may have worked. Instead, try flashing this code with properly scoped variables:

// This #include statement was automatically added by the Particle IDE.
#include <SparkFunRHT03.h>

const int RHT03_DATA_PIN = D4;
RHT03 rht;

int tempF = 0;
int humidity = 0;

int lasttempF = 0; //I'll use these to get rid of spikes in the data
int tempFdelta;
int lasthumidity = 0;
int humiditydelta;

unsigned long lastPubMillis = 0;
unsigned long pubInterval = 5000;

//Global variables to store messages.
const char pubEvent[] = "Xenon1 Environment";
char msg[128];
const char prePend[] = "Published Data:";

SerialLogHandler logHandler(LOG_LEVEL_TRACE);

void setup()
{
    //Start serial for console debugging.
    Serial.begin(9600);

    // variable name max length is 12 characters long
    // Declare Particle.variables as soon as possible.
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
    
    //Wait 10 seconds for the serial console to connect.
    waitFor(Serial.isConnected, 10000);
    
    //Initialize and update the sensor.
    rht.begin(RHT03_DATA_PIN);
    rht.update();
    
    //Add debugging output.
    snprintf(msg,arraySize(msg)-1,"Setup Readings:Ts = %d;Hs = %d",tempF,humidity);
    Log.trace(msg);
    
    Log.info("Setup complete.");
}

void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) 
    {
        int update = rht.update();
        humidity = rht.humidity();
        tempF = rht.tempF();
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Pre-Filter Readings:Tp = %d;Hp = %d",tempF,humidity);
        Log.trace(msg);

        tempFdelta = tempF-lasttempF;
        tempFdelta = abs(tempFdelta);
        humiditydelta = humidity-lasthumidity;
        humiditydelta = abs(humiditydelta);
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Delta Calcs:Td = %d;Hd = %d",tempFdelta,humiditydelta);
        Log.trace(msg);
        
        if(tempFdelta < 2 && humiditydelta < 2)
        {
            //Create your message to publish and load into the message buffer.
            snprintf(msg,arraySize(msg)-1,"T = %d;H = %d",tempF,humidity);
        
            //Send your data.
            Particle.publish(pubEvent,msg);
            
            //Add debugging output.
            strcat(prePend,msg);
            Log.trace(msg);
        } else {
            Log.error("Delta calcs out of spec... cannot publish.");
        }

        //Update your pub millis timer.
        lastPubMillis = millis();
                            
        lasttempF = tempF;
        lasthumidity = humidity;
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Last Readings Updated:Tl = %d;Hl = %d",lasttempF,lasthumidity);
        Log.trace(msg);
    }
}

I figured as much but wanted to confirm. Because you re-declare the variables inside loop, the global variable never gets updated... hence 0 and 0. However, the code I provided last post should have loaded the global variables so they would have most likely have been 32/0 as you see in the logs.

I would disagree. Software Timers and millis() counters have their place and are both good choices. Each has limitations. A well written non-blocking loop using an FSM approach (where it makes sense) will work just fine with millis() counters.

1 Like

True. When either method is implemented well it can perform properly.

1 Like

Okay, hopefully I did this right.

I ran the new code but first made the following changes (I'll post my current code below):

It didn't want to compile with that so I put the old line back to:

I used @nrobinson2000's suggestions:

and

Both the particle.publish and particle.variable are 32/0 (T/H).

My serial monitor output is:

0000002570 [app] TRACE: Setup Readings:Ts = 0;Hs = 0
0000002571 [app] INFO: Setup complete.
0000003169 [comm.protocol] INFO: Sending 'S' describe message
0000003173 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 4
0000003369 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 3
0000003370 [comm.protocol] INFO: rcv'd message type=1
0000003384 [comm.protocol] INFO: Sending 'A' describe message
0000003386 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 4
0000003388 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 3
0000003389 [comm.protocol] INFO: rcv'd message type=1
0000005001 [app] TRACE: Pre-Filter Readings:Tp = 32;Hp = 0
0000005001 [app] TRACE: Delta Calcs:Td = 32;Hd = 0
0000005002 [app] ERROR: Delta calcs out of spec... cannot publish.
0000005003 [app] TRACE: Last Readings Updated:Tl = 32;Hl = 0
0000010004 [app] TRACE: Pre-Filter Readings:Tp = 32;Hp = 0
0000010004 [app] TRACE: Delta Calcs:Td = 0;Hd = 0
0000010007 [app] TRACE: T = 32;H = 0
0000010008 [app] TRACE: Last Readings Updated:Tl = 32;Hl = 0
0000010136 [comm.protocol] TRACE: Reply recieved: type=2, code=0
0000010138 [comm.protocol] INFO: message id 5416 complete with code 0.00
0000010140 [comm.protocol] INFO: rcv'd message type=13

And my current code is:

// This #include statement was automatically added by the Particle IDE.
#include <SparkFunRHT03.h>

const int RHT03_DATA_PIN = D4;
RHT03 rht;

int tempF = 0;
int humidity = 0;

int lasttempF = 0; //I'll use these to get rid of spikes in the data
int tempFdelta;
int lasthumidity = 0;
int humiditydelta;

unsigned long lastPubMillis = 0;
unsigned long pubInterval = 5000;

//Global variables to store messages.
const char pubEvent[] = "Xenon1 Environment";
char msg[128];
const char prePend[] = "Published Data:";

SerialLogHandler logHandler(LOG_LEVEL_TRACE);

void setup()
{
    //Start serial for console debugging.
    Serial.begin(9600);

    // variable name max length is 12 characters long
    // Declare Particle.variables as soon as possible.
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
    
    //Wait 10 seconds for the serial console to connect.
    waitFor(Serial.isConnected, 10000);
    
    //Initialize and update the sensor.
    rht.begin(RHT03_DATA_PIN);
    rht.update();
    
    //Add debugging output.
    snprintf(msg,arraySize(msg)-1,"Setup Readings:Ts = %d;Hs = %d",tempF,humidity);
    Log.trace(msg);
    
    Log.info("Setup complete.");
}

void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) 
    {
        humidity = rht.humidity();
        tempF = rht.tempF();
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Pre-Filter Readings:Tp = %d;Hp = %d",tempF,humidity);
        Log.trace(msg);

        tempFdelta = tempF-lasttempF;
        tempFdelta = abs(tempFdelta);
        humiditydelta = humidity-lasthumidity;
        humiditydelta = abs(humiditydelta);
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Delta Calcs:Td = %d;Hd = %d",tempFdelta,humiditydelta);
        Log.trace(msg);
        
        if(tempFdelta < 2 && humiditydelta < 2)
        {
            //Create your message to publish and load into the message buffer.
            snprintf(msg,sizeof(msg),"T = %d;H = %d",tempF,humidity);
        
            //Send your data.
            Particle.publish(pubEvent,msg);
            
            //Add debugging output.
            strcat("Published Data:",msg);
            Log.trace(msg);
        } else {
            Log.error("Delta calcs out of spec... cannot publish.");
        }

        //Update your pub millis timer.
        lastPubMillis = millis();
                            
        lasttempF = tempF;
        lasthumidity = humidity;
        
        //Add debugging output.
        snprintf(msg,arraySize(msg)-1,"Last Readings Updated:Tl = %d;Hl = %d",lasttempF,lasthumidity);
        Log.trace(msg);
    }
}