Dan Tudose
Published © GPL3+

WiFi Air Quality Station

Yes, yet another weather station. But this one is special! It connects to your WiFi and it can run for more than a year on 2 AA batteries!

IntermediateFull instructions provided4 hours3,227
WiFi Air Quality Station

Things used in this project

Hardware components

SparkFun ESP8266 Thing - Dev Board
SparkFun ESP8266 Thing - Dev Board
×1
Adafruit BME680
×1
CJMCU MAX44009
×1

Story

Read more

Code

Arduino project sketch

C/C++
//#define JSON
#define CBOR

//#define DEBUG

#define SEALEVELPRESSURE_HPA (1013.25)

#define WIFI_SSID ""
#define WIFI_PWD ""

#define DEVICE_ID ""
#define DEVICE_TOKEN ""

// Define http and mqtt endpoints
#define HTTP_URL "api.allthingstalk.io"  // API endpoint
#define MQTT_URL "api.allthingstalk.io"  // MQTT broker

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <ATT_IOT.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include "MAX44009.h"

// I2C sensors
Adafruit_BME680 bme; 
MAX44009 light;

void callback(char* topic, byte* payload, unsigned int length);
WiFiClient espClient;
PubSubClient pubSub(MQTT_URL, 1883, callback, espClient);

ATTDevice device(DEVICE_ID, DEVICE_TOKEN);

#ifdef CBOR
  #include <CborBuilder.h>
  CborBuilder payload(device);
#endif

float lux = 0.0;
float temperature, pressure, humidity, voc;

// timer variable
unsigned long elapsed_msec;

int BME680init()
{

  if (!bme.begin())
    return 0;
  
  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms

  return 1;
}

int setupWiFi(const char* ssid, const char* password)
{
  unsigned char tries = 0;
  
  delay(10);
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    tries++;
    delay(50);
    Serial.print(".");
    if(tries == 50) return 0;
  }
  
  return 1;
}

void setup()
{
  #ifdef DEBUG
  elapsed_msec = millis();
  #endif

  
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);  // Turn the onboard LED off

  Serial.begin(9600);  // Init serial link for debugging
  
  Wire.begin();

  if(light.begin())
  {
    Serial.println("Could not find a valid MAX44009 sensor, check wiring!");
    ESP.deepSleep(10000000, WAKE_RF_DEFAULT); // go to sleep for 10s to force a reset 
  }
  
  if(!BME680init())
  {
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    ESP.deepSleep(10000000, WAKE_RF_DEFAULT); // go to sleep for 10s to force a reset 
  }
  
  // Enter your WiFi credentials here!
  if(!setupWiFi(WIFI_SSID, WIFI_PWD))
  {
    Serial.println("Could not connect to wifi.");
    ESP.deepSleep(10000000, WAKE_RF_DEFAULT); // go to sleep for 10s to force a reset
  }
  else 
    Serial.println("connected!");
  
  /* //Call this only once, or manually create all Assets in the AllThingsTalk web interface
  while(!device.connect(&espClient, HTTP_URL))  // Connect to AllThingsTalk
    Serial.println("retrying");

  // Create device assets
  device.addAsset("light", "light", "light intensity", "sensor", "{\"type\": \"number\"}");
  device.addAsset("temperature", "temperature", "ambient temperature", "sensor", "{\"type\": \"number\"}");
  device.addAsset("humidity", "humidity", "ambient humidity", "sensor", "{\"type\": \"number\"}");
  device.addAsset("pressure", "pressure", "ambient pressure", "sensor", "{\"type\": \"number\"}");
  device.addAsset("VOC", "VOC", "ambient VOC", "sensor", "{\"type\": \"number\"}");
  */
  //device.addAsset("toggle", "toggle", "toggle", "actuator", "{\"type\": \"boolean\"}");
  
  while(!device.subscribe(pubSub))  // Subscribe to mqtt
    Serial.println("retrying"); 

  lux = light.get_lux();
  #ifdef DEBUG
  Serial.print(lux);
  Serial.println(" lux");
  #endif

  if (!bme.performReading()) 
  {
    Serial.println("Failed to perform reading :(");
    return;
  }
  if (!bme.performReading()) 
  {
    Serial.println("Failed to perform reading :(");
    return;
  }

  temperature = bme.temperature;
  pressure = bme.pressure / 100.0;
  humidity = bme.humidity;
  voc = bme.gas_resistance / 1000.0;

  #ifdef DEBUG  
  Serial.print("Temperature = ");
  Serial.print(temperature);
  Serial.println(" *C");
  
  Serial.print("Pressure = ");
  Serial.print(pressure);
  Serial.println(" hPa");
  
  Serial.print("Humidity = ");
  Serial.print(humidity);
  Serial.println(" %");
  
  Serial.print("Gas = ");
  Serial.print(voc);
  Serial.println(" KOhms");
  #endif

       
  #ifdef JSON
  device.send(String(lux), "light");
  #endif
    
  #ifdef CBOR  // Send data using Cbor
  payload.reset();
  payload.map(5); //send a total of 5 values for the declared assets
  payload.addNumber(lux, "light");
  payload.addNumber(temperature, "temperature");
  payload.addNumber(humidity, "humidity");
  payload.addNumber(pressure, "pressure");
  payload.addNumber(voc, "VOC");
  payload.send();
  #endif
    
  //device.process();  // Check for incoming messages

  #ifdef DEBUG
  Serial.print("Millis elapsed: ");
  Serial.println(millis() - elapsed_msec);
  #endif
  
  ESP.deepSleep(900e6, WAKE_RF_DEFAULT); //sleep for 900 seconds
}

void loop()
{
    
}

MAX44009 Arduino Library

Credits

Dan Tudose

Dan Tudose

6 projects • 34 followers

Comments