Air quality/weather station

details

This is a good starting project for people who are interested in Internet of Things devices and wishing to start with something both simple and fun.

An air quality or weather station that pushes the data on the Internet is a low complexity fun project to explore the Internet of Things revolution and understand the main concepts and protocols used.

For the device, Arduino Ethernet was opted because of the strong community support and large base of supported sensors. The device measures the CO2 concentration in the air, the temperature and noise level and compare it between two locations. So, the author had two of this devices with the same components and only sending the data to different endpoints. Speaking of endpoints, for the cloud solution, DeviceHub.net  is used to offer both data in and data out in the form of gathering data from sensors and remote control devices by defining actuators on the platform first and then linking them to the hardware by using the API.

arduino Ethernet

Here is a snapshot from both locations of the sensors and their current data.

device_hub

 

Code

 /*
Air Quality/Weather station
  |--> device that monitors the temperature, 
       noise and carbon dioxide levels via devicehub.net
 
 Hardware parts:
   1. Microcontroller board     
       ---> Arduino Ethernet
        |-> http://arduino.cc/en/Main/arduinoBoardEthernet
   
   2. Sound sensor              
       ---> Grove - Sound Sensor w/ LM358 amplifier and an electret microphone  
        |-> http://www.seeedstudio.com/wiki/index.php?title=Twig_-_Sound_Sensor
   
   3. Temperature sensor        
       ---> One Wire Temperature Sensor waterproof DS18B20   
       |-> http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf     
 
   4. CO2 sensor               
       ---> Grove - CO2 Sensor
        |-> http://www.seeedstudio.com/wiki/images/c/ca/MH-Z16_CO2_datasheet_EN.pdf
   
   5. Additional parts          
       ---> 4.7K resistor
 
 Connections:
   1. Sound sensor              
       ---> Arduino Analog A0
   
   2. Temperature sensor        
      ----> Arduino Digital 2
       |--> 4.7K resistor between signal and the power pin
   
   3. CO2 sensor               
       ---> Arduino Digital 3 ( TX )
        |-> Arduino Digital 4 ( RX )
 
 Libraries:
   1. OneWire
       ---> http://code.bildr.org/download/997.zip
   
   2. MQTT PubSubClient         
       ---> https://github.com/knolleary/pubsubclient/archive/v1.9.1.zip
   
   3. Dallas Temperature       
       ---> http://www.hacktronics.com/code/DallasTemperature.zip
     
 Web platform:    
   DeviceHUB.net                
       
 23.06.2015                         
 Author: Alexandru Gheorghe
*/


#include <SPI.h>  
#include <OneWire.h>  
#include <Ethernet.h>                            
#include <PubSubClient.h>
#include <SoftwareSerial.h>
#include <DallasTemperature.h>

// MAC Address of Arduino Ethernet (Sheild)
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

#define API_KEY           "paste_apikey_here"
#define PROJECT_ID        "paste_projectid_here"
#define TEMPERATURE_NAME  "paste_temp_sensor_name_here"
#define NOISE_NAME        "paste_noise_sensor_name_here"
#define CO2_NAME          "paste_co2_sensor_name_here"
#define DEVICE_UUID       "paste_device_uuid_name_here"

#define sec               1000

char clientId[]        = "write_a_client_name_without_spaces"; // e.g. char clientId[] = "my_arduino"
char TempTopic[]       = "/a/"API_KEY"/p/"PROJECT_ID"/d/"DEVICE_UUID"/sensor/"TEMPERATURE_NAME"/data";
char NoiseTopic[]      = "/a/"API_KEY"/p/"PROJECT_ID"/d/"DEVICE_UUID"/sensor/"NOISE_NAME"/data";
char CO2Topic[]        = "/a/"API_KEY"/p/"PROJECT_ID"/d/"DEVICE_UUID"/sensor/"CO2_NAME"/data";
// server mqtt.devicehub.net ip
char server[]         = "104.155.7.31";
char message_buffer1[20];
char message_buffer2[20];
char message_buffer3[20];

EthernetClient apiClient;

void callback(char* topic, byte* payload, unsigned int length)
{
  // handle message arrived
}

PubSubClient client(server, 1883, callback, apiClient);

boolean conn = false;
unsigned long time;

#define DS18S20_Pin  2        // DS18S20 Signal pin on digital 2
OneWire ds(DS18S20_Pin);      // on digital pin 2
DallasTemperature sensors(&ds);

int counter = 0;

// CO2 sensor
#define pinTx  3
#define pinRx  4
SoftwareSerial sensorCo2(pinTx,pinRx);
const unsigned char cmd_get_sensor[] = {
0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
const unsigned char cmd_c_sensor[] = {
0xff, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78};

// Noise variables
#define noise_pin        A0   // Microphone is connected to Analog 0
const int sampleWindow = 50;  // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;
// variables for smoothing the microphone values
const int numReadings = 10;
int readings[numReadings];      
int index = 0;                  
int total = 0;                  
int average = 0;  

void setup(void)  
{
  // init serial for debugging
  Serial.begin(9600);
  initPins();

  if (Ethernet.begin(mac) == 0)  
  {
    Serial.println(F("Failed to configure Ethernet using DHCP"));
    Ethernet.begin(mac);
  }

  Serial.println(F("\nStarting connection to server..."));
  
  if(client.connect(clientId))  
  {
    conn = true;
    Serial.println(F("Successfuly connected and running!"));
  }
  else  
  {
    Serial.println(F("Connection problem"));
  }

  Serial.println(F("Starting..."));
  Serial.println(F("3 minutes warm-up CO2 sensor..."));
  // warm-up time for co2 sensor
  while(counter < 2)  {
    Serial.println(counter);
    delay(sec);
    counter++;
  }

  Serial.print('\n');
  Serial.println(F("Warm-up completed"));
  Serial.print('\n');

  // start a serial communication with the CO2 sensor
  sensorCo2.begin(9600);
  
  // cablibrate the zero point for CO2 sensor  
  Serial.println(F("Calibrating CO2 sensor..."));
    for(int i = 0; i < sizeof(cmd_c_sensor); i++)  {
    sensorCo2.write(cmd_c_sensor[i]);
  }

  delay(3*sec);  
  
  Serial.println(F("Calibration completed"));

}

void loop(void)  
{
  //if client it's not connected or disconnects here we try to reconnect
  if (!client.connected())
  { 
    Serial.println(F("reconnecting ..."));
    client.connect(clientId);
    delay(3*sec); 
    sendData();  
  }

  sendData();
}

void sendData(void) 
{
  float ThermometerTemperature = getTemp();
  float Noise = getNoise();
  int gas;
  int tempCo2;

  // get co2 value from function getCarbonDioxide
  if(getCarbonDioxide(&gas, &tempCo2))  {
    gas;
  }
  
  if(conn) 
  {
    //publishing new value every 5 seconds
    if (millis() > (time + 5*sec)) 
    {
      time = millis();
      
      String pubString1 = "{\"value\": " + String(ThermometerTemperature) + "}";
      String pubString2 = "{\"value\": " + String(Noise) + "}";
      String pubString3 = "{\"value\": " + String(gas) + "}";

      pubString1.toCharArray(message_buffer1, pubString1.length()+1);
      pubString2.toCharArray(message_buffer2, pubString2.length()+1);
      pubString3.toCharArray(message_buffer3, pubString3.length()+1);
    
      Serial.println(F("Publishing new value: "));
      Serial.println(ThermometerTemperature);
      Serial.println(Noise);
      Serial.println(gas);
      
      client.publish(TempTopic,  message_buffer1);
      client.publish(NoiseTopic, message_buffer2);
      client.publish(CO2Topic,   message_buffer3);
    }
    // MQTT client loop processing
    client.loop();
  }

}

void initPins()  
{
  pinMode(noise_pin, INPUT); 
}


// returns the temperature from DS18S20 in DEG Celsius
float getTemp(void)
{
  sensors.requestTemperatures();
  float currentTemp;
  currentTemp = sensors.getTempCByIndex(0);
  
  return currentTemp;
}

void sendcommand(uint8_t *pcommand)  
{
    uint8_t i;
   
    for (i=0;i<9;i++)  
    {
      sensorCo2.write(pcommand[i]);
    }   
}


// returns the gas strength from the CO2 sensor
bool getCarbonDioxide(int *gas_strength, int *temperatureGas)  
{
  for(int i = 0; i < sizeof(cmd_get_sensor); i++)  
  {
    sensorCo2.write(cmd_get_sensor[i]);
  }
  
  long cnt_timeout = 0;
  while(!sensorCo2.available())  
  {
    delay(1);
    cnt_timeout++;    
    if(cnt_timeout > 1000)
      return 0;
  }
  
  int len = 0;
  unsigned char dta[20];
  
  while(sensorCo2.available())  
  {
    dta[len++] = sensorCo2.read();
  }
  
  if((9 == len) && (0xff == dta[0]) && (0x86 == dta[1]))
  {
    *gas_strength = 256*dta[2]+dta[3];
    *temperatureGas = dta[4] - 40;
    delay(5*sec);
    return 1;
  }

  return 0;  

}

// returns the decibels from sound sensor
float getNoise()  
{
  unsigned long startMillis= millis();
  unsigned int peakToPeak = 0;

  unsigned int signalMax = 0;
  unsigned int signalMin = 750;

  while (millis() - startMillis < sampleWindow)  
  {
    sample = analogRead(noise_pin);
    if (sample < 1024)  
    {
      if (sample > signalMax)  
      {
        signalMax = sample;
      }
      else if (sample < signalMin)  
      {
         signalMin = sample;
      }
    }
  }

  peakToPeak = signalMax - signalMin;  
  
  // transform voltage to decibels 
  double dB = 3.1 * 20.0  * log10 (peakToPeak  +1.);
  
  // smoothing the values from sensor
  total= total - readings[index];         
  readings[index] = dB; 
  total= total + readings[index];       
  index = index + 1;                    
  
  if (index >= numReadings) 
    index = 0;               
    
  average = total / numReadings;         
  
  int realdB = map(average, 100, 190, 40,100);
  delay(30);
  // not send false values
  if(realdB > 4)  
  {
    delay(6*sec);
    return realdB;
  }

}

For more detail, please visit below link.

https://www.hackster.io/devicehub-net/air-quality-weather-station

 

This is a good starting project for people who are interested in Internet of Things devices and wishing to start with something both simple and fun.

An air quality or weather station that pushes the data on the Internet is a low complexity fun project to explore the Internet of Things revolution and understand the main concepts and protocols used.

For the device, Arduino Ethernet was opted because of the strong community support and large base of supported sensors. The device measures the CO2 concentration in the air, the temperature and noise level and compare it between two locations. So, the author had two of this devices with the same components and only sending the data to different endpoints. Speaking of endpoints, for the cloud solution, DeviceHub.net  is used to offer both data in and data out in the form of gathering data from sensors and remote control devices by defining actuators on the platform first and then linking them to the hardware by using the API.

arduino Ethernet

Here is a snapshot from both locations of the sensors and their current data.

device_hub

 

Code

 /*
Air Quality/Weather station
  |--> device that monitors the temperature, 
       noise and carbon dioxide levels via devicehub.net
 
 Hardware parts:
   1. Microcontroller board     
       ---> Arduino Ethernet
        |-> http://arduino.cc/en/Main/arduinoBoardEthernet
   
   2. Sound sensor              
       ---> Grove - Sound Sensor w/ LM358 amplifier and an electret microphone  
        |-> http://www.seeedstudio.com/wiki/index.php?title=Twig_-_Sound_Sensor
   
   3. Temperature sensor        
       ---> One Wire Temperature Sensor waterproof DS18B20   
       |-> http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf     
 
   4. CO2 sensor               
       ---> Grove - CO2 Sensor
        |-> http://www.seeedstudio.com/wiki/images/c/ca/MH-Z16_CO2_datasheet_EN.pdf
   
   5. Additional parts          
       ---> 4.7K resistor
 
 Connections:
   1. Sound sensor              
       ---> Arduino Analog A0
   
   2. Temperature sensor        
      ----> Arduino Digital 2
       |--> 4.7K resistor between signal and the power pin
   
   3. CO2 sensor               
       ---> Arduino Digital 3 ( TX )
        |-> Arduino Digital 4 ( RX )
 
 Libraries:
   1. OneWire
       ---> http://code.bildr.org/download/997.zip
   
   2. MQTT PubSubClient         
       ---> https://github.com/knolleary/pubsubclient/archive/v1.9.1.zip
   
   3. Dallas Temperature       
       ---> http://www.hacktronics.com/code/DallasTemperature.zip
     
 Web platform:    
   DeviceHUB.net                
       
 23.06.2015                         
 Author: Alexandru Gheorghe
*/


#include <SPI.h>  
#include <OneWire.h>  
#include <Ethernet.h>                            
#include <PubSubClient.h>
#include <SoftwareSerial.h>
#include <DallasTemperature.h>

// MAC Address of Arduino Ethernet (Sheild)
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

#define API_KEY           "paste_apikey_here"
#define PROJECT_ID        "paste_projectid_here"
#define TEMPERATURE_NAME  "paste_temp_sensor_name_here"
#define NOISE_NAME        "paste_noise_sensor_name_here"
#define CO2_NAME          "paste_co2_sensor_name_here"
#define DEVICE_UUID       "paste_device_uuid_name_here"

#define sec               1000

char clientId[]        = "write_a_client_name_without_spaces"; // e.g. char clientId[] = "my_arduino"
char TempTopic[]       = "/a/"API_KEY"/p/"PROJECT_ID"/d/"DEVICE_UUID"/sensor/"TEMPERATURE_NAME"/data";
char NoiseTopic[]      = "/a/"API_KEY"/p/"PROJECT_ID"/d/"DEVICE_UUID"/sensor/"NOISE_NAME"/data";
char CO2Topic[]        = "/a/"API_KEY"/p/"PROJECT_ID"/d/"DEVICE_UUID"/sensor/"CO2_NAME"/data";
// server mqtt.devicehub.net ip
char server[]         = "104.155.7.31";
char message_buffer1[20];
char message_buffer2[20];
char message_buffer3[20];

EthernetClient apiClient;

void callback(char* topic, byte* payload, unsigned int length)
{
  // handle message arrived
}

PubSubClient client(server, 1883, callback, apiClient);

boolean conn = false;
unsigned long time;

#define DS18S20_Pin  2        // DS18S20 Signal pin on digital 2
OneWire ds(DS18S20_Pin);      // on digital pin 2
DallasTemperature sensors(&ds);

int counter = 0;

// CO2 sensor
#define pinTx  3
#define pinRx  4
SoftwareSerial sensorCo2(pinTx,pinRx);
const unsigned char cmd_get_sensor[] = {
0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
const unsigned char cmd_c_sensor[] = {
0xff, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78};

// Noise variables
#define noise_pin        A0   // Microphone is connected to Analog 0
const int sampleWindow = 50;  // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;
// variables for smoothing the microphone values
const int numReadings = 10;
int readings[numReadings];      
int index = 0;                  
int total = 0;                  
int average = 0;  

void setup(void)  
{
  // init serial for debugging
  Serial.begin(9600);
  initPins();

  if (Ethernet.begin(mac) == 0)  
  {
    Serial.println(F("Failed to configure Ethernet using DHCP"));
    Ethernet.begin(mac);
  }

  Serial.println(F("\nStarting connection to server..."));
  
  if(client.connect(clientId))  
  {
    conn = true;
    Serial.println(F("Successfuly connected and running!"));
  }
  else  
  {
    Serial.println(F("Connection problem"));
  }

  Serial.println(F("Starting..."));
  Serial.println(F("3 minutes warm-up CO2 sensor..."));
  // warm-up time for co2 sensor
  while(counter < 2)  {
    Serial.println(counter);
    delay(sec);
    counter++;
  }

  Serial.print('\n');
  Serial.println(F("Warm-up completed"));
  Serial.print('\n');

  // start a serial communication with the CO2 sensor
  sensorCo2.begin(9600);
  
  // cablibrate the zero point for CO2 sensor  
  Serial.println(F("Calibrating CO2 sensor..."));
    for(int i = 0; i < sizeof(cmd_c_sensor); i++)  {
    sensorCo2.write(cmd_c_sensor[i]);
  }

  delay(3*sec);  
  
  Serial.println(F("Calibration completed"));

}

void loop(void)  
{
  //if client it's not connected or disconnects here we try to reconnect
  if (!client.connected())
  { 
    Serial.println(F("reconnecting ..."));
    client.connect(clientId);
    delay(3*sec); 
    sendData();  
  }

  sendData();
}

void sendData(void) 
{
  float ThermometerTemperature = getTemp();
  float Noise = getNoise();
  int gas;
  int tempCo2;

  // get co2 value from function getCarbonDioxide
  if(getCarbonDioxide(&gas, &tempCo2))  {
    gas;
  }
  
  if(conn) 
  {
    //publishing new value every 5 seconds
    if (millis() > (time + 5*sec)) 
    {
      time = millis();
      
      String pubString1 = "{\"value\": " + String(ThermometerTemperature) + "}";
      String pubString2 = "{\"value\": " + String(Noise) + "}";
      String pubString3 = "{\"value\": " + String(gas) + "}";

      pubString1.toCharArray(message_buffer1, pubString1.length()+1);
      pubString2.toCharArray(message_buffer2, pubString2.length()+1);
      pubString3.toCharArray(message_buffer3, pubString3.length()+1);
    
      Serial.println(F("Publishing new value: "));
      Serial.println(ThermometerTemperature);
      Serial.println(Noise);
      Serial.println(gas);
      
      client.publish(TempTopic,  message_buffer1);
      client.publish(NoiseTopic, message_buffer2);
      client.publish(CO2Topic,   message_buffer3);
    }
    // MQTT client loop processing
    client.loop();
  }

}

void initPins()  
{
  pinMode(noise_pin, INPUT); 
}


// returns the temperature from DS18S20 in DEG Celsius
float getTemp(void)
{
  sensors.requestTemperatures();
  float currentTemp;
  currentTemp = sensors.getTempCByIndex(0);
  
  return currentTemp;
}

void sendcommand(uint8_t *pcommand)  
{
    uint8_t i;
   
    for (i=0;i<9;i++)  
    {
      sensorCo2.write(pcommand[i]);
    }   
}


// returns the gas strength from the CO2 sensor
bool getCarbonDioxide(int *gas_strength, int *temperatureGas)  
{
  for(int i = 0; i < sizeof(cmd_get_sensor); i++)  
  {
    sensorCo2.write(cmd_get_sensor[i]);
  }
  
  long cnt_timeout = 0;
  while(!sensorCo2.available())  
  {
    delay(1);
    cnt_timeout++;    
    if(cnt_timeout > 1000)
      return 0;
  }
  
  int len = 0;
  unsigned char dta[20];
  
  while(sensorCo2.available())  
  {
    dta[len++] = sensorCo2.read();
  }
  
  if((9 == len) && (0xff == dta[0]) && (0x86 == dta[1]))
  {
    *gas_strength = 256*dta[2]+dta[3];
    *temperatureGas = dta[4] - 40;
    delay(5*sec);
    return 1;
  }

  return 0;  

}

// returns the decibels from sound sensor
float getNoise()  
{
  unsigned long startMillis= millis();
  unsigned int peakToPeak = 0;

  unsigned int signalMax = 0;
  unsigned int signalMin = 750;

  while (millis() - startMillis < sampleWindow)  
  {
    sample = analogRead(noise_pin);
    if (sample < 1024)  
    {
      if (sample > signalMax)  
      {
        signalMax = sample;
      }
      else if (sample < signalMin)  
      {
         signalMin = sample;
      }
    }
  }

  peakToPeak = signalMax - signalMin;  
  
  // transform voltage to decibels 
  double dB = 3.1 * 20.0  * log10 (peakToPeak  +1.);
  
  // smoothing the values from sensor
  total= total - readings[index];         
  readings[index] = dB; 
  total= total + readings[index];       
  index = index + 1;                    
  
  if (index >= numReadings) 
    index = 0;               
    
  average = total / numReadings;         
  
  int realdB = map(average, 100, 190, 40,100);
  delay(30);
  // not send false values
  if(realdB > 4)  
  {
    delay(6*sec);
    return realdB;
  }

}

For more detail, please visit below link.

https://www.hackster.io/devicehub-net/air-quality-weather-station

 

COMMENTS

Please Login to comment
  Subscribe  
Notify of