Eric yuan
Published © GPL3+

Air Quality Measure and Digital Control System

A project which can monitor the environment temperature and humidity, PM2.5 and control something remotely through Photon Particle.

IntermediateProtip4 hours998
Air Quality Measure and Digital Control System

Things used in this project

Hardware components

Photon
Particle Photon
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

schematic for control board

picture for WEB IDE

put those pictures into the same folder as html file

Code

source code for photon

C/C++
Put it into WEB IDF for photon and add the related library into that .ino file and compile it.
// This #include statement was automatically added by the Particle IDE.
#include "idDHT22/idDHT22.h"

// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_SSD1306/Adafruit_SSD1306.h"

// This #include statement was automatically added by the Particle IDE.
#include "ThingSpeak/ThingSpeak.h"

#include"application.h"
#include"stdlib.h"

#define LENG 24

// use hardware SPI,so only need to config DataCommand, ChipSelect, Reset Pins
//#define OLED_MOSI A5  //DI
//#define OLED0_MISO A4
//#define OLED_SCK  A3  //DO
#define OLED_CS A0
#define OLED_DC A1
#define OLED_RESET A2

#define ITEM_NONE 0
#define ITEM_LAMP 1
#define ITEM_PUMP 2
#define ITEM_FAN  3 


#define PIN_FAN D0
#define PIN_PUMP D1
#define PIN_LAMP D2


Adafruit_SSD1306 oled(OLED_DC, OLED_RESET, OLED_CS);


int idDHT22pin = D3; //Digital pin for comunications
void dht22_wrapper(); // must be declared before the lib initialization
// DHT instantiate
idDHT22 DHT22(idDHT22pin, dht22_wrapper);



unsigned char buf[LENG];
 
int PM01Value=0;          //define PM1.0 value of the air detector module
int PM2_5Value=0;         //define PM2.5 value of the air detector module
int PM10Value=0;         //define PM10 value of the air detector module

#define SENSOR PMS3003      //have another type of sensor
 
 

unsigned char ledFlip=0;



void dht22_wrapper() {
	DHT22.isrCallback();
}

int handlepara(String value);
void setup()
{
    Serial.begin(9600); 
    Serial1.begin(9600);
    pinMode(D7,OUTPUT);
 //   digitalWrite(D7,LOW);
    analogWrite(A4,1);
    
 ///   ThingSpeak.begin(client);                   
    Particle.function("handlepara",handlepara);         // handles all parameters.
    
    oled.begin(SSD1306_SWITCHCAPVCC);   //init the oled
    oled.display();
    oled.clearDisplay();
    oled.setTextSize(1);
    oled.setTextColor(WHITE);

    DHT22.acquire();
	while (DHT22.acquiring())
		;
	int result = DHT22.getStatus();
	switch (result)
	{
		case IDDHTLIB_OK:
			Serial.println("OK");
			break;
		case IDDHTLIB_ERROR_CHECKSUM:
			Serial.println("Error\n\r\tChecksum error");
			break;
		case IDDHTLIB_ERROR_ISR_TIMEOUT:
			Serial.println("Error\n\r\tISR Time out error");
			break;
		case IDDHTLIB_ERROR_RESPONSE_TIMEOUT:
			Serial.println("Error\n\r\tResponse time out error");
			break;
		case IDDHTLIB_ERROR_DATA_TIMEOUT:
			Serial.println("Error\n\r\tData time out error");
			break;
		case IDDHTLIB_ERROR_ACQUIRING:
			Serial.println("Error\n\r\tAcquiring");
			break;
		case IDDHTLIB_ERROR_DELTA:
			Serial.println("Error\n\r\tDelta time to small");
			break;
		case IDDHTLIB_ERROR_NOTSTARTED:
			Serial.println("Error\n\r\tNot started");
			break;
		default:
			Serial.println("Unknown error");
			break;
	}
}

int handlepara(String value)
{
    static unsigned char counter=0;
    static uint8_t item_update = ITEM_NONE; //no item will be udpated at first.
    unsigned char adjust_value = 0;
    if((value=="FanON")||(value=="FanOFF"))
        item_update = ITEM_FAN;
    else
    if((value=="LampON")||(value=="LampOFF"))
        item_update = ITEM_LAMP;
    else
    if((value=="PumpON")||(value=="PumpOFF"))
        item_update = ITEM_PUMP;
    
    if(value=="FanON")
        digitalWrite(D7,HIGH);
    else
    if(value=="FanOFF")
        digitalWrite(D7,LOW);
    else
    if(value=="LampON")
        digitalWrite(D7,HIGH);
    else
    if(value=="LampOFF")
        digitalWrite(D7,LOW);
    else
    if(value=="PumpON")
        digitalWrite(D7,HIGH);
    else
    if(value=="PumpOFF")
        digitalWrite(D7,LOW);
    else
    adjust_value= atoi(value);     //must be a value from adjust panel
    {
        if(adjust_value==5)
            digitalWrite(D7,HIGH);
        else
        if(adjust_value==6)
            digitalWrite(D7,LOW);
        if((adjust_value>=0)&&(adjust_value<=10))   //make sure it's the right value
        {
            uint16_t pwm = (uint16_t)(adjust_value/10.0)*4095;
            if(item_update==ITEM_FAN)
                analogWrite(PIN_FAN,pwm);
            else
            if(item_update==ITEM_LAMP)
                analogWrite(PIN_LAMP,pwm);
            else
            if(item_update==ITEM_PUMP)
                analogWrite(PIN_PUMP,pwm);    
        }
    }

    return 0;
}

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

// SYSTEM_MODE(SEMI_AUTOMATIC);
#ifdef SENSOR       //we use the sensor from plantower 

float Tempp=0.0;
float Humii=0.0;
float PM2_5=0;
void loop()
{
    unsigned char flag=0;
    char pubstring[64];
    bool success;
    static unsigned char update=0;
    
    if(Serial1.available())
    {
        buf[0]=Serial1.read();
        if(buf[0]==0x42)
        while(!Serial1.available());
        buf[1]=Serial1.read();
        if(buf[1]==0x4d)
        {
            Serial.print("PMS3003\r\n");
            for(unsigned char i=2;i<24;i++)
            {
                while(!Serial1.available());
                buf[i]= Serial1.read();
            }   
            flag=1;
        }
    }
    if(flag==1)     //upate the data every time when sensor udpated 
    {
        flag=0;
        if(checkValue(buf,LENG))
        {
            PM01Value=transmitPM01(buf); //count PM1.0 value of the air detector module
            PM2_5Value=transmitPM2_5(buf);//count PM2.5 value of the air detector module
            PM2_5=PM2_5Value;
            PM10Value=transmitPM10(buf); //count PM10 value of the air detector module 
        } 
        update++;
        if(update==3)     //only update all the value five times later.
        {
            update=0;
            DHT22.acquire();
	        while (DHT22.acquiring());
	        oled.clearDisplay();
            oled.setCursor(0,0);
            
            oled.print("Temperature:");     //the first line
            Tempp=DHT22.getCelsius();
            oled.print(Tempp, 2);
            oled.println("C");  
            
            
            oled.println("");       //do nothing here,just to leave one space line
            
            oled.print("Humidity:");            //the second line
            Humii=DHT22.getHumidity();
            oled.print(Humii, 2);
            oled.println("%");
            
            oled.println("");       //do nothing here,just to leave one space line
            
            oled.print("PM2.5:");      //the third line
            oled.print(PM2_5Value,DEC);
            oled.println("ug/m3");    
            
            oled.println("");       //do nothing here,just to leave one space line
            
            oled.print("PM10:");      //the fourth line
            oled.print(PM10Value,DEC);
            oled.print("ug/m3"); 
            oled.display();
            
            sprintf(pubstring,"{\"t\":%0.2lf,\"h\":%0.2lf,\"p\":%0.1lf}", Tempp, Humii,PM2_5);  
            success=Particle.publish("temp", pubstring);
            if(!success)
                Serial.println("Failed to publish this event");
            else
                Serial.println("Event had published successfully");
        }
        
        // Update the 2 ThingSpeak fields with the new data
         /*this is only used if i want to publish all the value to website
        ThingSpeak.setField(1, (int)PM01Value);
        ThingSpeak.setField(2, (int)PM2_5Value);
        ThingSpeak.setField(3, (int)PM10Value);
        // Write the fields that you've set all at once.
        ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
        */
      
    }
}
char checkValue(unsigned char *thebuf, char leng)
{  
  char receiveflag=0;
  int receiveSum=0;
  char i=0;
 
  for(i=0;i<leng;i++)
  {
  receiveSum=receiveSum+thebuf[i];
  }
    
  if(receiveSum==((thebuf[leng-2]<<8)+thebuf[leng-1]+thebuf[leng-2]+thebuf[leng-1]))  //check the serial data 
  {
    receiveSum=0;
    receiveflag=1;
  }
  return receiveflag;
}
 
int transmitPM01(unsigned char *thebuf)
{
  int PM01Val;
  PM01Val=((thebuf[4]<<8) + thebuf[5]); //count PM1.0 value of the air detector module
  return PM01Val;
}
 
//transmit PM Value to PC
int transmitPM2_5(unsigned char *thebuf)
{
  int PM2_5Val;
  PM2_5Val=((thebuf[6]<<8) + thebuf[7]);//count PM2.5 value of the air detector module
  return PM2_5Val;
  }
 
//transmit PM Value to PC
int transmitPM10(unsigned char *thebuf)
{
  int PM10Val;
  PM10Val=((thebuf[8]<<8) + thebuf[9]); //count PM10 value of the air detector module  
  return PM10Val;
}

#else       //sendsor for liudu

void loop()
{
    unsigned char i=0;
    unsigned char flag=0;
    if(Serial1.available())
    {
        buf[0]=Serial1.read();
        if(buf[0]==0xAA)    //get the start frame
        {
            for(i=1;i<7;i++)
            {
                while(!Serial1.available());
                buf[i]= Serial1.read();
            }   
            if(buf[6]==0xff)        //get the end frame
            {
                flag=1;
                Serial.print("LMLPM05K\r\n");
            }
            else
                flag=0;
        }
    }
    if(flag==1)
    {
        flag=0;
        if(checkValue(buf,7))
        {
            PM2_5Value=transmitPM2_5(buf);//count PM2.5 value of the air detector module
            PM10Value=transmitPM10(buf); //count PM10 value of the air detector module 
        }   
        Serial.print("PM2.5: ");  //send PM1.0 data to bluetooth
        PM2_5Value/=10;
        Serial.print(PM2_5Value);
        Serial.println("  ug/m3");     
        
        Serial.print("PM10:  ");  //send PM1.0 data to bluetooth
        PM10Value/=10;
        Serial.print(PM10Value);
        Serial.println("  ug/m3");   
        if(ledFlip==0)
        {
           ledFlip=1;
           digitalWrite(D7,LOW);
        }
        else
        {
           ledFlip = 0;
           digitalWrite(D7,HIGH);
        }
    }
    
}
char checkValue(unsigned char *thebuf, char leng)
{  
  char receiveflag=0;
  unsigned char receiveSum=0;
  char i=0;
 
  for(i=1;i<5;i++)
  {
    receiveSum=receiveSum+thebuf[i];
  }
    
  if(receiveSum==thebuf[5])  //check the serial data 
  {
    receiveSum=0;
    receiveflag=1;
  }
  return receiveflag;
}
//transmit PM Value to PC
int transmitPM2_5(unsigned char *thebuf)
{
  int PM2_5Val;
  PM2_5Val=((thebuf[1]<<8) + thebuf[2]);//count PM2.5 value of the air detector module
  return PM2_5Val;
  }
 
//transmit PM Value to PC
int transmitPM10(unsigned char *thebuf)
{
  int PM10Val;
  PM10Val=((thebuf[3]<<8) + thebuf[4]); //count PM10 value of the air detector module  
  return PM10Val;
}
#endif

webpage file

HTML
change your token and device id for your own photon.
<!DOCTYPE html>
<html>
    <head>
        <title>MyFirstApp</title>
        <script type="text/javascript" src="http://cdn.jsdelivr.net/particle-api-js/5/particle.min.js"></script>
        <style>
            button#button1{color:black;padding:5px}
            button#button1:hover{background-color: blue}
            button#button1:active{background-color: antiquewhite}
            button#button2{color:black;padding:5px}
            button#button3{color:black;padding:5px}
            
            legend{text-align:center}
            
            fieldset{border: block}
            
            img#buttonPanelImage{width:100px; height:100px;float:right;}
        </style>
    </head>
    <body>
        
        <!---------------------For the Button Coltorl Panel------->
        <div>
            <br>
            <fieldset>        
                <legend>Button Control Panel</legend>
            <!--<button id="button1" onclick="function_fan()" onmouseover="style.backgroundColor='blue'" 
                onmouseout="style.backgroundColor='grey'" onmousedown="style.backgroundColor='green'" >Turn ON Fan</button> <br> -->
            <img id="buttonPanelImage"  src="fanOff.gif">
        <!-- <img id="fanImage" src="fanOff.gif" style="wdith:50px;height:90px;float:right"> -->
        <!--<img id="myImage"  src="LampOff.gif" width="50" height=90 float:right>   -->
            <button id="button1" onclick="function_fan()" >Turn ON Fan</button> <br>
            <button id="button2" onclick="function_lamp()">Turn ON Lamp</button> <br>
            <button id="button3" onclick="function_pump()">Turn ON Pump</button><br>
            
            </fieldset>
        </div>
        
        <!--------------For the Value Tune Panel------------------->
        <div>
            <fieldset>
                <legend>Adjust Panel</legend>
                <p id="tuneTitle">Set Fan Speed</p>    <!--Why the layout will change if i didnot use <p> -->
                <input id="Range" type="range" style="width:200px;height:30px" min="0" max="10" value="5" onclick="Function_Adjust()">  <!--set the default value as 5-->
            </fieldset>
        </div>
        
        <!--For read out value-->
        <div>
            <fieldset>
                <legend>Sensor</legend>
                <p id="Temp">Temperature:</p>
                <p id="Humidity">Humidity:</p>
                <p id="PM2.5">PM2.5:</p>
                <p id="Time">Time:</p>
            </fieldset>
        </div>
        
        <p id="debug"></p>          <!--THIS syntax is just for debug---------->
        
        <!-----------------Java script section-------------------->
        <script>
            
            var image=document.getElementById("buttonPanelImage");  //define the image for the button panel image
            
            var FanStatus = 0,
                LampStatus = 0,
                PumpStatus = 0,
                DeviceId = "xxxxchagne it with your own deviceID for photonxxx",
                token="xxxxxxxxchange it with your own tokenxxxxxxxxxxxxx";
            
            
            var particle = new Particle();
            
            particle.login({username: '------your user name for web IED-----', password: '---your password for IED--------'}).then(
              function(data){
                console.log('API call completed on promise resolve: ', data.body.access_token);
                token = data.body.access_token;
              },
              function(err) {
                console.log('API call completed on promise fail: ', err);
              }
            );
            
            function function_cloud(FunctionName, FunctionVar){
              var fnPr = particle.callFunction({ deviceId: DeviceId, name: FunctionName, argument: FunctionVar, auth: token });
            
              fnPr.then(
                function(data) {
                  console.log('Function called succesfully:', data);
                }, 
                function(err) {
                  console.log('An error occurred:', err);
                }
              );           
            
            }
            
            var tune_fan  =5;
            var tune_pump = 5;
            var tune_lamp = 5;
            var tune_current = 0;       //define the current tune status-->the last time that the user pused the turn on button
            
            //Get test event for specific device
            particle.getEventStream({ deviceId:DeviceId, name: 'temp', auth:token  }).then(function(stream) {
              stream.on('event', function(data) {
                console.log("Event: ", data);
                var ParseData=JSON.parse(data.data);
                console.log("temperature: " + ParseData.t + " degrees C, Humidity: " + ParseData.h + "%");
                document.getElementById("Temp").innerHTML="Temperature: "+ParseData.t+"C";
                document.getElementById("Humidity").innerHTML="Humidity: "+ParseData.h+"%";
                document.getElementById("PM2.5").innerHTML="PM2.5: "+ParseData.p +"mg/m3";
              });
            });
            /**********************************************************************************/ 
            function function_fan()
            {
                var x=0; 
                var State;
                x=document.getElementById("button1").innerHTML;
                x=(x=="Turn OFF Fan")? "Turn ON Fan":"Turn OFF Fan";
                document.getElementById("button1").innerHTML=x;
                if(x=="Turn OFF Fan")
                {
                    image.src="FanOn.gif";
                    document.getElementById("tuneTitle").innerHTML="Set Fan Speed";
                    //document.getElementById("Range").value = tune_fan;
                    State="FanON";
                    tune_current=State;     //which means the last time the user pused the turn on button is turn Fan on
                }
                   
                else
                if(x=="Turn ON Fan")
                {
                    image.src="FanOff.gif";   
                    State="FanOFF";
                }
                function_cloud("handlepara",State);   
                document.getElementById("Range").value = tune_fan;
            }
            function function_lamp()
            {
                var x=0;
                var State;
                x=document.getElementById("button2").innerHTML;
                x=(x=="Turn OFF Lamp")? "Turn ON Lamp":"Turn OFF Lamp";
                document.getElementById("button2").innerHTML=x;
                if(x=="Turn OFF Lamp")
                {
                    image.src="LampOn.gif";
                    document.getElementById("tuneTitle").innerHTML="Set Lamp brightness";
                    //document.getElementById("Range").value = tune_lamp;
                    State="LampON";
                    tune_current=State;
                }
                    
                else
                if(x=="Turn ON Lamp")
                {
                    image.src="LampOff.gif";
                    State="LampOFF";
                }
                function_cloud("handlepara",State);    
                document.getElementById("Range").value = tune_lamp;
            }
            function function_pump()
            {
                var x=0;
                var State;
                x=document.getElementById("button3").innerHTML;
                x=(x=="Turn OFF Pump")? "Turn ON Pump":"Turn OFF Pump";
                document.getElementById("button3").innerHTML=x;
                if(x=="Turn OFF Pump")
                {
                    image.src="PumpOn.gif";
                    document.getElementById("tuneTitle").innerHTML="Set Pump Volume";
                 //   document.getElementById("Range").value = tune_pump;
                    State="PumpON";
                    tune_current=State;
                } 
                else
                if(x=="Turn ON Pump")
                {
                    image.src="PumpOff.gif"; 
                    State="PumpOFF";
                }   
                function_cloud("handlepara",State);  
                document.getElementById("Range").value = tune_pump;
            }
            function Function_Adjust()
            {
                var x;
                if(tune_current=="FanON")
                    tune_fan = document.getElementById("Range").value;              
                else
                if(tune_current=="LampON")
                    tune_lamp = document.getElementById("Range").value;    
                else
                if(tune_current=="PumpON")
                    tune_pump = document.getElementById("Range").value;    
                
                x=document.getElementById("Range").value; 
                document.getElementById("debug").innerHTML=x;
                function_cloud("handlepara",x);
                
            }
            
            (function(){
                function checkTime(i)
                {
                    return (i<10)?"0"+i:i;
                }

                function function_time()
                {
                    var Time = new Date();
                    var h=checkTime(Time.getHours());
                    var m=checkTime(Time.getMinutes());
                    var s=checkTime(Time.getSeconds());
                  //  var temp=document.getElementById(Time).innerHTML;
                    document.getElementById("Time").innerHTML="Time:"+h+":"+m+":"+s;
                    setTimeout(function(){function_time()},500);
                }
                function_time(); 
            })();
            
        </script>
    </body>
</html>

Credits

Eric yuan

Eric yuan

4 projects • 1 follower

Comments