Temperature and Humidity Monitor


#1

Hi All,

As a beginner in these filed of Particle photon I start project which is useful for my work. The requirement is monitoring the temp + humidity in store and export the data saved in server for monthly report.
I used web-hook (www.thingspeak.com ) to log and export data to/from the web.

components used
1 X Particle Photon
1 X BME280 Pressure, Temp and Humidity breakout.
1X PCB board.

Optional:
1 X micro OLED 3.3V for display

Also I used the in code alarm trigger if exceeding the set point.
here below the code for particle.
your comments will be appreciated to improve the project.

I note there is a delay in disply the temp in OLED display when the internet disconnected. I am still working on this to improve. if anyone can help on this will be helpful.

References:
https://thingspeak.com/
Example of publish data to ThingSpeak
Hookup Guide for Temp Sensor BME280

Hookup OLED
Code:

#include <SparkFunBME280.h>



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





////////////////////
//Webhook
///////////////////

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




char mqttUserName[] = "TSPhotonMQTTDemo";    // Can be any name.
char mqttPass[] = "IXCXXXCYC8XXXXW3I";        // Change this to your MQTT API Key from Account > MyProfile.
char writeAPIKey[] = "2Q2ZWB8AXXXXXH";     // Change this to your channel Write API Key.
long channelID = 521114;                    // Change this to your channel number.
char server[] = "mqtt.thingspeak.com";       // Define the ThingSpeak MQTT broker
int led =D7;


static const char alphanum[] ="0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";  // This variable is used for random generation of client ID.


// Define a callback function to initialize the MQTT client.
void callback(char* topic, byte* payload, unsigned int length) {
}

MQTT client(server, 1883, callback);       // Initialize the MQTT client.

unsigned long lastConnectionTime = 0;
const unsigned long postingInterval = 300L * 1000L; // Post data every 300 seconds.





 MicroOLED oled;
 


//* This sketch uses the MicroOLED library to draw a 3-D projected
 //* cube, and rotate it along all three axes.
 //* 
 //* Development environment specifics:
 //*  Arduino 1.0.5
 //*  Arduino Pro 3.3V
 //*  Micro OLED Breakout v1.0
 //* 
 //* This code is beerware; if you see me (or any other SparkFun employee) at the
 //* local, and you've found our code helpful, please buy us a round!
 //* 
 //* Distributed as-is; no warranty is given.
 //***************************************************************/

#include <SPI.h>  // Include SPI if you're using SPI


//////////////////////////
// MicroOLED Definition //
//////////////////////////
#define PIN_RESET D7   // Connect RST to pin D7 (SPI & I2C)
#define PIN_DC    D6  // Connect DC to pin A4 (SPI only)
#define PIN_CS    A2 // Connect CS to pin D3 (SPI only)

BME280 MySensor1;


// connect SCK to pin A3
// Connect SDL to pin A5



//////////////////////////////////
// MicroOLED Object Declaration //
//////////////////////////////////
//MicroOLED oled(PIN_RESET, PIN_DC, PIN_CS);  // SPI Example




void setup()
{
  oled.begin();     // Initialize the OLED
  oled.clear(PAGE);// Clear the display's internal memory
  oled.clear(ALL);  // Clear the library's display buffer
  
  oled.setCursor(0, 0);
  oled.setFontType(1); // Set the text to medium (6 columns, 3 rows worth of characters).
  oled.print("Welcome ");
  oled.print("Temp Monitor");
  oled.display();   // Display what's in the buffer (splashscreen)

  delay(5000);
  oled.clear(PAGE);// Clear the display's internal memory
  oled.clear(ALL);  // Clear the library's display buffer
  

  oled.setCursor(0, 0);
  oled.setFontType(1); // Set the text to medium (6 columns, 3 rows worth of characters).
  oled.print("Tempmonitor ");
  oled.display();   // Display what's in the buffer (splashscreen)

  delay(5000);
  oled.clear(PAGE);// Clear the display's internal memory
  oled.clear(ALL);  // Clear the library's display buffer
  
 
  
  // Setup the BME Sensor
  
  //***Driver settings********************************
 
    //commInterface can be I2C_MODE or SPI_MODE
    //specify chipSelectPin using arduino pin names
    //specify I2C address.  Can be 0x77(default) or 0x76
    
  MySensor1.settings.commInterface = I2C_MODE;
  MySensor1.settings.I2CAddress = 0x77;
  
  

//***Operation settings*****************************//

    //runMode can be:
    //  0, Sleep mode
    //  1 or 2, Forced mode
    //  3, Normal mode
    MySensor1.settings.runMode = 3; //Normal Mode


    //tStandby can be:
    //  0, 0.5ms
    //  1, 62.5ms
    //  2, 125ms
    //  3, 250ms
    //  4, 500ms
    //  5, 1000ms
    //  6, 10ms
    //  7, 20ms
    MySensor1.settings.tStandby = 0;


    //filter can be off or number of FIR coefficients to use:
    //  0, filter off
    //  1, coefficients = 2
    //  2, coefficients = 4
    //  3, coefficients = 8
    //  4, coefficients = 16
    MySensor1.settings.filter = 0;// before 0


    //tempOverSample can be:
    //  0, skipped
    //  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
    MySensor1.settings.tempOverSample = 1;//before 1


    //pressOverSample can be:
    //  0, skipped
    //  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
    MySensor1.settings.pressOverSample = 0;// before 1

    //humidOverSample can be:
    //  0, skipped
    //  1 through 5, oversampling *1, *2, *4, *8, *16 respectively
    MySensor1.settings.humidOverSample = 1;

    delay(10);  //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up.         
MySensor1.begin();
delay(8);
/////////////////////////////////

// Varulables 
////////////////////////////////



}

float Tin=0; //Tempruture 
float Tcal=0.7;
float H=0; // Humidity
int TD=5000; // Time Delay


int AltS=26.2; //Alert Setpoint.
int Alt= 0; //Alert output
int AD= 36000;   //Alert Delay 10hrs
int iA=0;


void loop()
{


///////////////////////
//      Webhook    ///
//////////////////////


 // If MQTT client is not connected then reconnect.
    if (!client.isConnected())
    {
        TempRead();
        Serial.println("Connection lost...");// 
      reconnect();
      
    }
    
    client.loop();  // Call the loop continuously to establish connection to the server.
    
    if (millis() - lastConnectionTime > postingInterval)
    {
        TempRead();
        Alert();
        mqttpublish();
    }
}  // end loop



//////////////////////////////
////   Reconnection to MQTT ///
//////////////////////////////


void reconnect(){
    
     char clientID[9];
     

     // Generate ClientID
     for (int i = 0; i < 8; i++) {
         clientID[i] = alphanum[random(51)];
     }
     clientID[8]='\0';
     
        
     // Connect to the ThingSpeak MQTT broker.
     if (client.connect(clientID,mqttUserName,mqttPass))  {
         Particle.publish("Conn:"+ String(server) + " cl: " + String(clientID)+ " Uname:" + String(mqttUserName));
     } else
     {
         Particle.publish("Failed to connect, Trying to reconnect in 5 seconds");
      
         TempRead();
         delay(1000);
     } 
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////
////   Publish MQTT  ///////
///////////////////////////


void mqttpublish() {
    
    String Temp = String(Tin);
    String HT = String(H);
    String ALERT= String(Alt);
  
    
    
    // Create data string to send data to ThingSpeak.
    // Use these lines to publish to a channel feed,
    // which allows multiple fields to be updates simultaneously.
    // Comment these lines and use the next two to publish to a single channel field directly.
    String data = String("field1=" + String(Temp) + "&field2=" + String(HT)+"&field3=" + String(ALERT));
    String topic = String("channels/"+String(channelID)+ "/publish/"+String(writeAPIKey));
    
    //String data=String(t);
    //String topic = String("channels/"+String(channelID)+ "/publish/fields/field1/"+String(writeAPIKey));
    
    client.publish(topic,data);
    
    lastConnectionTime = millis();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////
///   Alert Delay and output    ///
//////////////////////////////////

void Alert(){
if (Tin >=AltS && iA>=0)
{
    iA++;
    Alt=0;
    delay(1000);
}

if (Tin>=AltS && iA==3)

{
Alt=1;
}

if (Tin>=AltS && iA>AD)
{
    iA=0;
}

}//end Alert
////////////////////////////////////////////////////////////////////////////////////////////////////



///////////////////////////////////////
///   Take Reading and Display   /////
//////////////////////////////////////


void TempRead(){

Tin = MySensor1.readTempC()-Tcal;
H=MySensor1.readFloatHumidity();


// OLED Display
/////////////////////
 // oled.pixel(LCDWIDTH/2, LCDHEIGHT/2); // Add a pixel to the display buffer.


oled.clear(PAGE);
//delay(3000);
oled.setCursor(0, 0);  // Set the text cursor to the upper-left of the screen.
oled.setFontType(2);
oled.print(Tin,1);
oled.setFontType(1);
oled.println(" C");

oled.setFontType(2);
oled.print(H,1);
oled.setFontType(1);
oled.println(" %");


oled.display(); // Draw to the screen


}// end TempRead


#2

@Lahmdi, try using SYSTEM_THREAD(ENABLED) at the top of your file.


#3

This info might be helpful to you.


#4

That is a nice board but that CCS 811 sensor is garbage .

This is a stable and reliable VOC sensor after many months of testing.


#5

@WoobaGooba, is this your project?
Do you get stable gas readings from the CCS811?
I’ve tried multiple boards with that sensor and none of them ever gave me consistent readings. The drift was 400% over a few hours.


#6

The OP described he needs temperature and pressure. That board is offered w/ or w/o the VOC sensor. The vendor might be open to a re-spin if you can make the case for a better VOC sensor.


#7

Many thanks
I shall try it