I am a programming novice but have been fascinated with Particle devices for the last couple years. When Particle announced they were creating Mesh devices I put in my order as soon as possible. I also ordered the Grove Starter Kit for Particle Mesh.
When my package arrived I was excited to get started. Unfortunately (or fortunately!) I found this wasn't a plug-and-play environment. I searched for example codes or tutorials on using the Starter Kit with Mesh devices and discovered nothing much was out there. And while there was good information available to make the various sensors in the Starter Kit work in a standalone environment...
...I wasn't able to find anything that was of much help for people at my level of programming experience to collect sensor data from one Mesh device and then send it directly to another Mesh device for processing. This seems to me to be the essence of using Mesh!
I decided to see if I could figure how to:
- Collect temperature and humidity data using the DHT11 sensor included in the Starter Kit connected to a Xenon, and then:
- Send the data to an Argon and have the Argon output the sensor data to the 4-digit display included in the Starter Kit as well as publish the data to the Particle Console.
I floundered around for awhile and was ready to give up when, through the help of @ScruffR and others on this forum, I was able to get everything working. To make things easier for those of you looking for examples to use when playing around with the Starter Kit, I figured it would make sense to post the code in this forum. Good luck and have fun!
Xenon Code (collects data from a DHT11 temp/humidity sensor and sends the data to an Argon)(NOTE: Edited 19 Jan 2018 to stop publishing and make display show all 0's if Xenon stops sending data):
//This code allows a Particle Xenon to collect temperature and humidity data and then send it to a Particle Argon
//for processing. The Argon then outputs the data to a 4-digit display and, concurrently, to the Particle Console.
//Matching code is available for the Argon to make all this work.
//Special thanks to @ScruffR and others on the Particle Forum. If any code doesn't seem right, that's on me.
//For any code that works especially well, that's because of @ScruffR.
#include <Seeed_DHT11.h>
const int 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 lastSensorRead = 0;
unsigned long sensorInterval = 5000;//I choose to read the sensor every 5 seconds
//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() - lastSensorRead > sensorInterval)
{
humidity = dht.getHumidity();
tempF = dht.getTempFarenheit();
tempFdelta = tempF - lasttempF;
tempFdelta = abs(tempFdelta);
humiditydelta = humidity - lasthumidity;
humiditydelta = abs(humiditydelta);
if (tempFdelta < 2 && humiditydelta < 2)//if temp difference is more than 1 degree F in 5 seconds
//it's probably a spike in the data
{
snprintf(msg, sizeof(msg), "{\"tempF\":\"%.d\",\"humidity\":\"%.d\"}", tempF, humidity);
Serial.println(msg);//for debugging
//Send the data.
Mesh.publish("Xenon1", msg);
}
//Update the sensor read millis timer.
lastSensorRead = millis();
lasttempF = tempF;
lasthumidity = humidity;
}
}
Argon code (receives temp/humidity data from Xenon and then outputs the data to a 4-digit display and publishes the data to the Particle Console):
//This code allows a Particle Argon to receive temperature and humidity data from a Particle Xenon
//and then output the data to a 4-digit display connected to the Argon and, concurrently, to the Particle Console.
//Matching code is available for the Xenon to make all this work.
//Special thanks to @ScruffR and others on the Particle Forum. If any code doesn't seem right, that's on me.
//For any code that works especially well, that's because of @ScruffR.
#include <JsonParserGeneratorRK.h>
#include "TM1637.h""
//pins definitions for TM1637
const int CLK = D2;
const int 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 = "Xenon1 T / H";//A temp/humidity sensor is attached to Xenon1
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);//I am collecting data from Xenon1
}
void loop()
{
//Using a millis timer for non-blocking code design.
if (millis() - lastPubMillis > pubInterval)
{
//Send your data.
Serial.printlnf("RoomEnv: '%s'", msg);//for debugging
Particle.publish("Xenon1 T / H", 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();
}
}
To see the process and reasoning behind the individual steps that posed some obstacles in the development of this code, go here: