Need help finding example code for sending mesh data from xenon to argon

Okay, I cleaned that up on the Xenon. I got rid of the JSON generator and the Xenon still works correctly.

#include <Seeed_DHT11.h>

#define DHTPIN D4//set pin for DHT

DHT dht(DHTPIN);

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";
char msg[128];

void setup()

{
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
    
    dht.begin(); //initialize the sensor
    
    Serial.begin(9600);
}
void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) 
    {
        humidity = dht.getHumidity();
        tempF = dht.getTempFarenheit();
        tempFdelta = tempF-lasttempF;
        tempFdelta = abs(tempFdelta);
        humiditydelta = humidity-lasthumidity;
        humiditydelta = abs(humiditydelta);

            if(tempFdelta <2 && humiditydelta <2)
            {

                snprintf(msg, sizeof(msg), "{\"tempF\":\"%.d\",\"humidity\":\"%.d\"}",tempF,humidity);
                Serial.println(msg);

	        	//Send the data.
                Mesh.publish("Xenon1",msg);
                
             }

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

I'm sorry, @ScruffR, but I'm not following. I added the line (I'm including the entire myHandler to show where I put it):

 // this will be called whenever an event arrives we subscribed to
void myHandler(const char *event, const char *data){
  Serial.println(data);       // print out the data as it comes in for debugging
  strncpy(msg, data, sizeof(msg)-1); // copy the incoming data to the global variable msg (with boundary limit)

  jsonParser.clear();         // make sure the parser buffer is fresh and empty
  jsonParser.addString(data); // copy the received data into the parser buffer for it to work with
  if (jsonParser.parse()) {   // let the parser do its job and split up the data internally
    // first ask the parser for the value connected with the key 'tempF' 
    // if this is successful pop that value into the provided variable tempF
    // if not, the function will return false which - in turn - triggers the error output
    if (jsonParser.getOuterValueByKey("tempF", tempF) == false) {
      Serial.println("failed to get Temperature");
    }
    // do the same for 'humidity'
    // if(!someBoolean) is short hand for if(someBoolean == false) 
    if (!jsonParser.getOuterValueByKey("humidity", humidity)) {
      Serial.println("failed to get Humidity");
    }
  }
}

But my results are still the same. i guess I just assumed that since the data was printing correctly in the console then that meant that it was actually set in the subscription handler. I don't know how to check that.

Can you post the serial output of your Argon?
And also repost your Argon code?

You can also add this line before your Particle.publish() line (and reqirte that as shown too)

                //Send your data.
                Serial.printlnf("RoomEnv: '%s'", msg);
                Particle.publish("Room Environment", msg, PRIVATE);

And I think I found your issue

You only ever enter the if() block (which would do the updating) once on startup, since you keep "resetting" the delay timer every iteration of loop().
That lastPubMillis line needs to be inside that if() block.

For debugging you should have Serial.print() statements in each block you want to check whether they are actually doing anything and if they are also doing what you expect.

2 Likes

WAHOOOOOOOOO! Everything works! I must have moved the delay outside the loop when I was doing all the cutting and pasting.

My current (final?) Argon code:

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

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

#define CLK D2//pins definitions for TM1637
#define DIO D3

TM1637 tm1637(CLK,DIO);

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

int tempF;
int humidity;

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

void printJson(JsonParser &jp);

// Create a parser to handle 2K of data and 100 tokens
JsonParserStatic<2048, 100> jsonParser;

// this will be called whenever an event arrives we subscribed to
void myHandler(const char *event, const char *data){
  Serial.println(data);       // print out the data as it comes in for debugging
  strncpy(msg, data, sizeof(msg)-1); // copy the incoming data to the global variable msg (with boundary limit)

  jsonParser.clear();         // make sure the parser buffer is fresh and empty
  jsonParser.addString(data); // copy the received data into the parser buffer for it to work with
  if (jsonParser.parse()) {   // let the parser do its job and split up the data internally
    // first ask the parser for the value connected with the key 'tempF' 
    // if this is successful pop that value into the provided variable tempF
    // if not, the function will return false which - in turn - triggers the error output
    if (jsonParser.getOuterValueByKey("tempF", tempF) == false) {
      Serial.println("failed to get Temperature");
    }
    // do the same for 'humidity'
    // if(!someBoolean) is short hand for if(someBoolean == false) 
    if (!jsonParser.getOuterValueByKey("humidity", humidity)) {
      Serial.println("failed to get Humidity");
    }
  }
}

void setup()
{
  tm1637.init();
  tm1637.set(BRIGHT_TYPICAL);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;
  tm1637.point(POINT_ON);
  
  Serial.begin(9600);

  delay(1500);
  
  Mesh.subscribe("Xenon1",myHandler);
}

void loop()
{
        //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) 
            {
                //Send your data.
                Serial.printlnf("RoomEnv: '%s'", msg);
                Particle.publish("Room Environment", msg, PRIVATE);
                
                int digit1 = tempF/10;
                int digit2 = tempF % 10;
                int digit3 = humidity/10;
                int digit4 = humidity % 10;
                tm1637.display(0,digit1);
                tm1637.display(1,digit2);
                tm1637.display(2,digit3);
                tm1637.display(3,digit4);
                
                //Update your pub millis timer.
                lastPubMillis = millis();
            }
}

My current (final) Xenon code:

#include <Seeed_DHT11.h>

#define DHTPIN D4//set pin for DHT

DHT dht(DHTPIN);

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";
char msg[128];

void setup()

{
    Particle.variable("tempF", tempF);
    Particle.variable("humidity", humidity);
    
    dht.begin(); //initialize the sensor
    
    Serial.begin(9600);
}
void loop()
{
    //Use a millis timer for non-blocking code design.
    if (millis() - lastPubMillis > pubInterval) 
    {
        humidity = dht.getHumidity();
        tempF = dht.getTempFarenheit();
        tempFdelta = tempF-lasttempF;
        tempFdelta = abs(tempFdelta);
        humiditydelta = humidity-lasthumidity;
        humiditydelta = abs(humiditydelta);

            if(tempFdelta <2 && humiditydelta <2)
            {

                snprintf(msg, sizeof(msg), "{\"tempF\":\"%.d\",\"humidity\":\"%.d\"}",tempF,humidity);
                Serial.println(msg);

	        	//Send the data.
                Mesh.publish("Xenon1",msg);
                
             }

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

My serial output. I switched partway from the serial port for the Xenon to the serial port for the Argon:

{"tempF":"75","humidity":"17"}
{"tempF":"75","humidity":"17"}
{"tempF":"75","humidity":"18"}
{"tempF":"75","humidity":"18"}
RoomEnv: '{"tempF":"75","humidity":"18"}'
{"tempF":"75","humidity":"18"}
RoomEnv: '{"tempF":"75","humidity":"18"}'
{"tempF":"75","humidity":"18"}
RoomEnv: '{"tempF":"75","humidity":"18"}'
{"tempF":"75","humidity":"18"}

Both the console output and the 4-digit display are now working properly.

@ScruffR - First a big thanks for all your time! Second, it seems to me maybe I should post the final code in a separate, fresh post. While I don't want to cross-post, it just seems that putting this code in a standalone post would be nice for people that are just starting to play with their mesh networks and the Grove Starter Kits or similar. If you agree, it might makes sense to have you do one more runthrough on my code so I don't post a "dirty" code.

Regardless, thanks again.

3 Likes

I’d have some minor changes, like replacing #define PIN_X Dx with const int PIN_X = Dx; to reduce defines which may interfere with other (hidden) defines without throwing an error.
Remove superfluous comments like // This #include statement was automatically added by the Particle IDE.
And maybe clean up your indentations.

BTW, you may want to rename lastPubMillis in your Xenon code to lastSensorRead since you aren’t really timing for the publish - which only happens when your readings have changed enough - but limiting the frequency with what you read your sensors.
If you were timing for the publish, the line lastPubMillis = millis(); should live in the same block as the actual publish command.

4 Likes

Sorry to bother you again, @ScruffR, but I came to realize that if I disconnect the Xenon the Argon continues to publish the last T/H data to the Console. Same for the serial monitor. Any suggestions on where I might have gone wrong? Thanks!

You can keep track of the last update and only publish when that timestamp changes or you just set a global flag (e.g. needPublish = true;) in the event handler, change your condition to (needPublish && millis() - lastPubMillis > pubInterval) and once you have published the data reset that flag to false.

1 Like

It took me a bit to figure out where & how to do it but I figured it out and also modified my example code in the example on the forum:

[Example Code: Xenon collects temp/humidity data & sends to Argon which then outputs to 4-digit display and Particle Console]

I also made it so my display would show all 0s if the Xenon quit sending data.

Thanks again, @ScruffR