Updated 31 Jan 2014
My Arduino micro-controller board measures indoor light intensity, temperature, humidity, air quality and has human movement detection. It sends the measured data to Xively.com that creates beautiful graphs for me. Additionally you can control the brightness of a red and a green LED from the Xiveley website. This indoor sensor logger helps me understand the indoor climate and air quality over time. In the future it may help to control the indoor climate. First I used a Arduino Uno and a ethernet shield, but later I used a Arduino Nano and a Electric Imp as Wifi gateway. The MQ-135 air quality sensor output is compensated for dependency on temperature and humidity.
This project is very similar to energy usage meter that I build using a Mbed microcontroller board.
The hardware:
First I used a Arduino Uno and a ethernet shield
, but later I used a Arduino Nano and a Electric Imp as Wifi gateway.
These are the beautifull graphs
Here is the Arduino code
/*
Name: Jasper's Arduino Logger
Author: Jasper Sikken
Date : 31 jan 2014
This system measures all kinds of sensors using an Arduino microcontroller board
and sends the measured data to the internet either through a ethernet shield or the electric imp.
The original code comes from https://xively.com/dev/tutorials/arduino_wi-fi/ and
is adapted to use a Wiznet 5100 Ethernetshield in stead if a Wi-Fi shield.
It make uses of the Xively Arduino library. https://github.com/xively/xively_arduino/archive/master.zip
The MQ-135 air quality sensor output is compensated for dependency on temperature and humidity.
Circuit:
* Arduino UNO or Nano
* Wiznet Ethernet shield attached to pins 10, 11, 12, 13 (only on UNO)
* Electric Imp is used as a Wifi gateway
* Temperature and humidity sensor (DHT11) on pin2
* Infra red movement detector (HC-SR501)connected to pin3
* red LED on pin5 (analog/PWM out)
* softserial RX pin 6 to Electric Imp
* softwerial TX pin 7 to Electric Imp
* green LED on pin9 (analog/PWM out)
* Light intensity sensor (LDR) on analog pin0 and 100k to GND
* Air quality sensor (MQ-135) on analog pin1
*/
boolean useEthernet = 0; // Indicates if ethernet is used or not
int interval = 10000; // delay between calls to xively in ms
#include <SPI.h> // SPI library
#include <Ethernet.h> // Ethernet library
#include <HttpClient.h> // Http client library
#include <Xively.h> // Xively Arduino Library
#include <dht11.h> // Temperature and humidity sensor
#include <SoftwareSerial.h> // the serial interface to the imp
dht11 DHT11;
#define APIKEY "<API key>" // your API key
#define FEEDID <feed ID> // your xively feed ID
char lightID[] = "light"; // datastreams
char airqID[] = "air"; // datastreams
char RedLEDID[] = "RedLED"; // datastreams
char dht11tempID[] = "dht11temp";// datastreams
char dht11humID[] = "dht11hum"; // datastreams
char pirID[] = "PIR"; // datastreams
char GreenLEDID[] = "GreenLED"; // datastreams
volatile boolean pir; // variables used in an ISR must be volatile
float RoRs; // to compensate the MQ-135 Air Quality sensor for Temp and RH
#define LDRPin A0 // the pin connected to the LDR
#define airqPin A1 // the pin connected to air quality sensor
#define GreenLEDPin 9 // the pin connected to the Green LED
#define RedLEDPin 5 // the pin connected to the Red LED
#define DHT11PIN 2 // the pin connected to the temperature and humidity sensor
// pirPin 3 // this is a interrupt pin and does not have to be declared
SoftwareSerial mySerial(6, 7); // RX, TX
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
EthernetClient client;
IPAddress server(216,52,233,121); // numeric IP for api.xively.com
XivelyClient xivelyclient(client);
XivelyDatastream datastreams[] = { // Define the strings for our datastream IDs
XivelyDatastream(lightID ,strlen(lightID) ,DATASTREAM_FLOAT), // light
XivelyDatastream(airqID ,strlen(airqID) ,DATASTREAM_FLOAT), // air quality
XivelyDatastream(RedLEDID ,strlen(RedLEDID) ,DATASTREAM_FLOAT), // red LED
XivelyDatastream(dht11tempID,strlen(dht11tempID),DATASTREAM_FLOAT), // temp
XivelyDatastream(dht11humID ,strlen(dht11humID) ,DATASTREAM_FLOAT), // humidity
XivelyDatastream(pirID ,strlen(pirID) ,DATASTREAM_FLOAT), // PIR
XivelyDatastream(GreenLEDID ,strlen(GreenLEDID) ,DATASTREAM_FLOAT),};// green LED
// Finally, wrap the datastreams into a feed
XivelyFeed feed(FEEDID, datastreams, 7); /* number of datastreams */
void setup() {
Serial.begin(9600); // initialize the serial port
mySerial.begin(19200); // initialize the software serial port
Serial.println("Start"); // print to the serial port
if(useEthernet==0){
Serial.println("Ethernet is turned OFF");
}
else {
Serial.println("Ethernet is turned ON");
}
Serial.print("DHT11 LIBRARY VERSION: ");
Serial.println(DHT11LIB_VERSION);
pinMode(LDRPin, INPUT); // set the pin as input
pinMode(airqPin, INPUT); // set the pin as input
pinMode(RedLEDPin, OUTPUT);// set the pin as output
pinMode(GreenLEDPin,OUTPUT);// set the pin as output
delay(1000); // give the ethernet module time to boot up:
if(useEthernet==1){
Serial.println("Obtaining DHCP IP address"); // print to the serial port
if (Ethernet.begin(mac) == 1) { // start the Ethernet connection:
Serial.print("IP address: "); // print your local IP address:
Serial.println(Ethernet.localIP());
} //end of ethernet begin
}
attachInterrupt(1, PirActive, RISING); // interrupt 0 is on pin 2, and interrupt 1 is on pin 3, triggered on rising edge
} //end of void setup()
// this function is executed when PIR activity is detected
void PirActive(){
pir=1;
} // set a flag that movement was detected
void loop() {
analogWrite(GreenLEDPin, 0); // turn off the Green LED
analogWrite(RedLEDPin, 0); // turn off the Red LED
int level, value;
// Here we get all values in the feed from Xively
if(useEthernet==1){
Serial.println("Getting feed from Xively"); // print to the serial port
int getReturn = xivelyclient.get(feed, APIKEY);// get all values in the feed from Xively
if(getReturn > 0){Serial.println(feed[2]);} // if getting the feed was successful print the value to serial
if(getReturn > 0){Serial.println(feed[6]);} // if getting the feed was successful print the value to serial
else Serial.println("HTTP Error"); // else print to serial that it was unsuccesfull
// Here we write the level to the Red LED
level = feed[2].getFloat(); // convert float to integer
if(level < 0 )level = 0; // values below 0 are are capped to 0
if(level > 255)level = 255; // values above 255 are capped to 255
analogWrite(RedLEDPin, level); // here I actually write the value to the red LED
// Here we write the level to the Green LED
value = feed[6].getFloat(); // convert float to integer
if(value < 0 )value = 0; // values below 0 are are capped to 0
if(value > 255)value = 255; // values above 255 are capped to 255
analogWrite(GreenLEDPin, value);// here I actually write the value to the red LED
}
int sensorValue = analogRead(LDRPin); // read brightness from LDR
datastreams[0].setFloat(sensorValue); // set the LDR value in the feed
Serial.print("LDR value "); // print the LDR value
Serial.println(datastreams[0].getFloat());// print the LDR value
datastreams[2].setFloat(level); // set the Red LED value in the feed
Serial.print("Red LED value "); // print the LED value
Serial.println(datastreams[2].getFloat());// print the LED value
int chk = DHT11.read(DHT11PIN); // read the temperature and humidity
switch (chk)
{
case DHTLIB_OK:
break;
case DHTLIB_ERROR_CHECKSUM:
Serial.println("DHT11 Checksum error");
break;
case DHTLIB_ERROR_TIMEOUT:
Serial.println("DHT11 Time out error");
break;
default:
Serial.println("DHT11 Unknown error");
break;
}
datastreams[3].setFloat(DHT11.temperature);// set the temperature value in the feed
Serial.print("DHT11 Temp "); // print the temperature value
Serial.println(datastreams[3].getFloat()); // print the temperature value
datastreams[4].setFloat(DHT11.humidity); // set the humidity value in the feed
Serial.print("DHT11 Humidity "); // print humidity value
Serial.println(datastreams[4].getFloat()); // print humidity value
int airqValue = analogRead(airqPin); // read air quality sensor
if(DHT11.temperature >=20.0&&DHT11.temperature<=50.0){//adjust for dependency on temperature
RoRs = -0.0034 * DHT11.temperature + 1.067;
}
else if(DHT11.temperature>=-10.0&&DHT11.temperature<=5.0){//adjust for dependency on temperature
RoRs = -0.0300 * DHT11.temperature + 1.4;
}
else if (DHT11.temperature >= 5.0 && DHT11.temperature <= 20.0){//adjust for dependency on temperature
RoRs = -0.0167 * DHT11.temperature + 1.333;
}
else {
RoRs = 1;
}
RoRs= RoRs * (-0.001923 * DHT11.humidity + 1.0634); //adjust for dependency on humidity
int adjAirQValue = airqValue * RoRs;
datastreams[1].setFloat(adjAirQValue); // set the AirQ value in the feed
Serial.print("Adj AirQ value "); // print the AirQ value
Serial.println(datastreams[1].getFloat());// print the AirQ value
datastreams[5].setFloat(pir); // set the pir value in the feed
Serial.print("PIR activity: "); // print PIR activity
Serial.println(pir); // print 1 or 0
datastreams[6].setFloat(value); // set the Red LED value in the feed
Serial.print("Green LED value "); // print the LED value
Serial.println(datastreams[6].getFloat()); // print the LED value
// First print to software serial port
Serial.println("Putting feed to Soft Serial Port");
mySerial.print("|");
mySerial.print("LDR,");
mySerial.println(sensorValue);
mySerial.print("Air,");
mySerial.println(adjAirQValue);
mySerial.print("Temp,");
mySerial.println(DHT11.temperature);
mySerial.print("Hum,");
mySerial.println(DHT11.humidity);
mySerial.print("PIR,");
mySerial.print(pir);
mySerial.println("~");
Serial.println("End of putting feed to soft serial port"); // print to the serial port
if(useEthernet==1){
Serial.println("Putting feed to Xively"); // print to the serial port
int ret = xivelyclient.put(feed, APIKEY); // put the feed to xively
Serial.print("Put to xivelyclient returned ");//return message
Serial.println(ret); // if 200, all is fine!
}
Serial.println(""); // print empy line
pir=0; // set back to 0 to able able to detect activity until
delay(interval); // delay before restarting the loop
}