Okay, let’s try it :). This is the code running on the Argon. Hardware-wise it’s just a normal 0.96" 128x64 OLED connected via I2C. It displays 3 lines, the word “Temperatur”, the temperature in celsius reported by the Xenon, and the Argon’s uptime as " h:mm:ss".
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
SYSTEM_THREAD(ENABLED);
char szInfo[64];
double celsius;
long sampleTime;
#define OLED_RESET D4
Adafruit_SSD1306 display(OLED_RESET);
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
void setup() {
pinMode(D7, OUTPUT);
digitalWrite(D7, HIGH);
Mesh.subscribe("dsTmp", processTemp);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
display.clearDisplay();
}
void loop() {
display.clearDisplay();
display.setCursor(0,0); // print title on line 1
display.setTextSize(2);
display.setTextColor(WHITE);
display.println("Temperatur");
display.setCursor(0,20); // print temperature on line 2
display.setTextSize(3);
sprintf(szInfo, "%2.1f C", celsius);
display.println(szInfo);
display.drawCircle(79, 23, 3, WHITE);
display.drawCircle(79, 23, 4, WHITE);
display.setTextSize(2); // print uptime on line 3
sprintf(szInfo, "%2d:%02d:%02d", millis()/3600000, (millis()/60000)%60, (millis()/1000)%60);
display.println(szInfo);
display.display();
if (millis() - sampleTime > 20000) digitalWrite(D7, LOW); // if we didn't receive an update for the temperature for at least 20 seconds, turn off LED.
}
void processTemp(const char *name, const char *data) {
celsius = atof(data);
digitalWrite(D7, HIGH);
sampleTime = millis();
}
and this is the code running on the Xenon. The hardware is a DS1820 temperature sensor on pin D2. It reads the temperature every 2.5 seconds and Mesh.publishes it for the Argon. If the temperature is over a threshold, it does a Particle.publish to create an event that will be monitored to sound an alarm. And every 30 seconds it Particle.publishes the temperature for datalogging purposes.
#include <DS18B20.h>
const int MAXRETRY = 4;
const uint32_t msSAMPLE_INTERVAL = 2500;
const uint32_t msMETRIC_PUBLISH = 30000;
DS18B20 ds18b20(D2, true); //Sets Pin D2 for Water Temp Sensor and
// this is the only sensor on bus
char szInfo[64];
double celsius;
double fahrenheit;
uint32_t msLastMetric;
uint32_t msLastSample;
long lastAlarmTime;
int alarmSetPoint = 29;
void setup() {
Serial.begin(115200);
pinMode(D7, OUTPUT);
}
void loop() {
if (millis() - msLastSample >= msSAMPLE_INTERVAL){ // take a measurement every interval, just publish within Mesh network
getTemp();
}
if (millis() - msLastSample < 100) { // pulse the D7 LED every time a measurement is taken, act as a heartbeat
digitalWrite(D7, HIGH);
}
if (millis() - msLastSample > 300) {
digitalWrite(D7, LOW);
}
if (millis() - msLastMetric >= msMETRIC_PUBLISH){ // take a sample every intervale, this time publish to cloud
publishData();
}
}
void publishData() {
sprintf(szInfo, "%2.1f", celsius);
Particle.publish("dsTmp", szInfo, PRIVATE);
msLastMetric = millis();
}
void getTemp(){
float _temp;
int i = 0;
do {
_temp = ds18b20.getTemperature();
} while (!ds18b20.crcCheck() && MAXRETRY > i++);
if (i < MAXRETRY) {
celsius = _temp;
fahrenheit = ds18b20.convertToFahrenheit(_temp);
Serial.println(fahrenheit);
}
else {
celsius = fahrenheit = NAN;
Serial.println("Invalid reading");
}
sprintf(szInfo, "%2.1f", celsius);
Mesh.publish("dsTmp", szInfo);
if ((celsius > alarmSetPoint) && ((lastAlarmTime + 600000) < millis())) // if the temperature is too high, publish a cloud event as an alarm.
if (celsius > alarmSetPoint) // throttled to once every 10 minutes, not within first 10 minutes of powerup
{
Particle.publish("tempAlarm", "overTemp");
lastAlarmTime = millis();
}
msLastSample = millis();
}
It’s pretty much quick and dirty code heavily based on examples. I haven’t done much to clean it up and get it ready for prime-time. So be kind with how messy it is, but if you’ve got some feedback on how I’m actually doing things, I’d be happy to hear it