Arduino + SmartAirFilter 製作智能感應的 PM 空氣淨化器

先說 SmartAirFilters

知道 SmartAirFilters 源自微博上轉發的很火的那個帖子,和動輒七八千元的商用產品比,幾百元的 SmartAirFilters(以下簡稱電扇) 確實不貴。一次和朋友在清華科技園裏附近的咖啡館聊天,正好遇見他們在那裏做 DIY 體驗工坊,作爲 DIYer 愛好者,理所應當給個贊,就敗了個 1.0 試一試。

smartairfilters

空氣 PM 的監控

空氣過濾效果到底如何?作爲數據控,理所應當必須看數據說話。正好在玩 Arduino Yun,就起意搞個灰塵傳感器監控一下。

設備清單

要搞定空氣中的 PM 值檢測,網上已經有文章珠玉在前, 英文原文中文翻譯在此。我使用的設備也類似:

  • Arduino Yun
  • Shinyei 粉塵檢測傳感器 PPD42NS
  • Grove Base Shield(可選)
  • Micro USB 電源(輸出爲 5V 0.5A 左右即可)

Devices_1

這裏需要說明的是,目前類似 PPD42NS 的這類微型的空氣 PM 檢測傳感器都是利用光學特性,計算一段時間內觀測到的粉塵數量,從而推算出每立方米此類粉塵的數量。而嚴格意義上的 PM 1.0/2.5 是以每立方米此類粉塵的重量計量的。這兩個數據具有較大的相關性,對在日常生活中瞭解 PM 值的需要來說,PPD42NS 已經能夠滿足要求。

因爲有 Grove Base Shield,連接電路很簡單,將 Grove Base Shield 插到 Arduino 上,然後將 PPD42NS 的接口插到 D8 槽即可。PPD42NS 需豎直放置。

Devices_2

如果您沒有 Grove Base Shield,請按以下連接:

PPD42NS Arduino
Pin 1 (黑線) GND
Pin 3 (紅線) 5VDC
Pin 4 (黃線) D8

Arduino 代碼

完整代碼請參考 Git 上的 dust_check_simple 部分。

/*
# Smart Air Control #

Program by Iasc CHEN,April 2014

## Grove Dust Sensor ##

Use Shinyei Model PPD42NS Particle Sensor
http://www.sca-shinyei.com/pdf/PPD42NS.pdf

JST Pin 1 (Black Wire)  => Arduino GND
JST Pin 3 (Red wire)    => Arduino 5VDC
JST Pin 4 (Yellow wire) => Arduino Digital Pin 8
*/

#include <Bridge.h>

// dust check
int DUST_PIN = 8;

unsigned long DUST_SAMPLE_MS = 15000;//sampe 15s ;

unsigned long duration, starttime, now, lowpulseoccupancy = 0;
float ratio = 0, concentration = 0;

void setup() {
    Bridge.begin();
    Console.begin();
    // Serial.begin(9600);

    pinMode(DUST_PIN, INPUT);
    starttime = millis(); //get the current time;

    // while(!Console);
    Console.println(" Time , PM ");
}

void loop() {
    duration = pulseIn(DUST_PIN, LOW);
    lowpulseoccupancy = lowpulseoccupancy + duration;
    now = millis();

    if ((now - starttime) > DUST_SAMPLE_MS) {
        ratio = lowpulseoccupancy / (DUST_SAMPLE_MS * 10.0);  // Integer percentage 0=>100
        concentration = 1.1 * pow(ratio, 3) - 3.8 * pow(ratio, 2) + 520 * ratio + 0.62; // using spec sheet curve

        Console.print(now/1000);
        Console.print(",");
        Console.println(int(concentration/100));

        lowpulseoccupancy = 0;
        starttime = millis();
    }
}

從 Console 中得到未開電扇的一小時輸出數據如下,數據文件在此 pm_no_filter.csv

其數據圖形如下,經過一小時,PM 值緩慢的從平均約 80,降到約 40:

PM No Filter

能更 Smarter 一些嗎?

在封閉的室內,當空氣過濾達到一定水平之後,PM 值基本穩定。此時如果仍然開着淨化器,也只是白白耗電。我們可以設定一下閾值,例如,PM 指數高於 50,自動打開淨化器;低於 20,自動關閉淨化器,就比 Smart 更 Smarter 了 。

這個功能可以通過 Arduino 控制繼電器來實現。

設備清單

  • Arduino Yun
  • Shinyei 粉塵檢測傳感器 PPD42NS
  • Grove Base Shield(可選)
  • Micro USB 電源(輸出爲 5V 0.5A 左右即可)
  • 繼電器模塊,能夠控制 200V,10A 電路
  • 插座

Devices

繼電器的引腳連接說明如下:

Relay Arduino
Pin 1 (GND) GND
Pin 2 (VSS) 5VDC
Pin 3 (SIG) D4

插座的改造工作是用繼電器替換原有的控制開關。具體操作步驟是:

1 將原有的開關蓋子取出2 從開關的兩極焊接引出兩根線(感謝 @我是國寶 幫助焊接)3 將這兩根線接到繼電器上的控制引腳上

Plugin

在上圖中中間那個插座用於給 Arduino Yun 供電。左側的插座,在其開關位置連出的兩根線接到了繼電器上,下面的插頭是電扇用的。

Arduino 代碼

我在 Arduino 代碼中增加了對繼電器的控制,代碼修改如下,完整代碼請參考 Git 上的 dust_check 部分。:

/*
# Smart Air Control #

Program by Iasc CHEN,April 2014

## Grove Dust Sensor ##

Use Shinyei Model PPD42NS Particle Sensor
http://www.sca-shinyei.com/pdf/PPD42NS.pdf

JST Pin 1 (Black Wire)  => Arduino GND
JST Pin 3 (Red wire)    => Arduino 5VDC
JST Pin 4 (Yellow wire) => Arduino Digital Pin 8

## Relay ##

Relay Pin 1 (Black Wire)=> Arduino GND
Relay Pin 2 (Red wire)  => Arduino 5VDC
Relay Pin 3 (Green wire)=> Arduino Digital Pin 4
*/

#include <Bridge.h>

float RELAY_ON_VALUE  = 5000;
float RELAY_OFF_VALUE = 2000;

// dust check
int DUST_PIN = 8;

unsigned long DUST_SAMPLE_MS = 15000;//sampe 15s ;

unsigned long duration, starttime, lowpulseoccupancy = 0;
float ratio = 0, concentration = 0;

//relay control
int RELAY_PIN = 4;
unsigned long MAX_RELAY_RUNNING_MS = 1200000;// If after 1200s the air filter are still running, send a warning;

bool relay_on = false;
unsigned long now, relay_start_time, relay_running_time = 0;

void setup() {
    Bridge.begin();
    Console.begin();
    //Serial.begin(9600);

    pinMode(DUST_PIN,INPUT);
    starttime = millis(); //get the current time;

    pinMode(RELAY_PIN, OUTPUT);
    relay_start_time = millis();

    // while(!Console);
    Console.println("Time , PM , Status , Running");
}

void loop() {
    duration = pulseIn(DUST_PIN, LOW);
    lowpulseoccupancy = lowpulseoccupancy + duration;
    now = millis();

    if ((now - starttime) > DUST_SAMPLE_MS)//if the sampel time == 30s{

        ratio = lowpulseoccupancy / (DUST_SAMPLE_MS * 10.0);  // Integer percentage 0=>100
        concentration = 1.1 * pow(ratio,3) - 3.8 * pow(ratio,2) + 520 * ratio + 0.62; // using spec sheet curve

        Console.print(now/1000);
        Console.print(" , ");
        Console.print(int(concentration/100));
        Console.print(" , ");

        if (concentration < RELAY_OFF_VALUE){
            if(relay_on){
                digitalWrite(RELAY_PIN, LOW);
                relay_on = false;
            }
        } else if (concentration > RELAY_ON_VALUE){
            if(! relay_on){
                digitalWrite(RELAY_PIN, HIGH);
                relay_on = true;

                relay_start_time = millis();
            }
        }

        if(relay_on){
            relay_running_time = now - relay_start_time ;

            Console.print(" ON , ");
            Console.println( relay_running_time / 1000 );

            // if (relay_running_time > MAX_RELAY_RUNNING_MS){
            //      Console.println(" => Make sure your doors and windows are closed, or Change Filter!");
            // }
        }
        else{
            Console.print(" OFF , ");
            Console.println( 0 );
        }

        lowpulseoccupancy = 0;
        starttime = millis();
    }
}

將 PM 數值記錄愛 Log 文件中

前面的 PM 記錄都是輸出在 Console 中的,讓我們增加上 log 記錄,這樣就可以長時間記錄家裏的空氣 PM 值了。

下面的代碼實驗的性質較大,不僅僅是爲了寫 log 文件,還驗證了 Arduino 調用 Shell 命令的過程。這樣的方法便於將 Arduino Sketch 變成一個能 “推Push“ 的數據源使用,可以將更多地工作放到 Python 或 Shell 中去,提升開發效率。

設備清單

設備同上。

Arduino 代碼

以下內容是部分相關的代碼,完整代碼請參考 Git 上的 dust_check_log 部分。

首先,增加了用於創建所需的 Shell 腳本的部分,在使用時,請根據您的環境修改文件目錄和名字:

#include <FileIO.h>

void uploadScript() {
    File script = FileSystem.open("/mnt/sda1/workspaces/dust_check/dust_log.sh", FILE_WRITE);
    script.print("#!/bin/sh\n");
    script.print("echo $(date +'%Y-%m-%d %H:%M:%S') , $1 >> /mnt/sda1/workspaces/dust_check/logs/dust.log");
    script.close();

    Process chmod;
    chmod.begin("chmod");      // chmod: change mode
    chmod.addParameter("+x");  // x stays for executable
    chmod.addParameter("/mnt/sda1/workspaces/dust_check/dust_log.sh");
    chmod.run();
}

其次編寫了用於執行這個腳本的部分:

void runLogScript(String msg){
    Process logscript;
    logscript.begin("/mnt/sda1/workspaces/dust_check/dust_log.sh");
    logscript.addParameter(msg);
    logscript.run();
}

這些代碼在 Sketch 中的調用情況如下示意:

void setup() {
    ...

    FileSystem.begin();
    uploadScript() ;
    // runLogScript("Time , PM , Status , Running");

    Console.begin();
}

void loop() {
    duration = pulseIn(DUST_PIN, LOW);
    lowpulseoccupancy = lowpulseoccupancy + duration;
    now = millis();

    if ((now - starttime) > DUST_SAMPLE_MS){    //if the sampel time == 30s

        ...

        String output = String(int(concentration/100), DEC)
            + " , " + String(relay_on)
            + " , " + String(relay_running_time / 1000, DEC);
        Console.println(output);
        runLogScript(output);

        ...
    }
}

查看輸出 Log

SSH 登陸上 Linino,進入相關路徑,能夠查看 Log 文件的輸出。

$ cd /mnt/sda1/workspaces/dust_check
$ ls
dust_log.sh  logs
$ tail -f logs/dust.log
2014-05-12 19:50:06 , 27 , 1 , 421
2014-05-12 19:50:21 , 40 , 1 , 437
2014-05-12 19:50:37 , 31 , 1 , 452
2014-05-12 19:50:52 , 43 , 1 , 468
2014-05-12 19:51:08 , 41 , 1 , 484
2014-05-12 19:51:24 , 46 , 1 , 500
2014-05-12 19:51:40 , 46 , 1 , 516
2014-05-12 19:51:55 , 43 , 1 , 531
2014-05-12 19:52:11 , 43 , 1 , 547
2014-05-12 19:52:26 , 51 , 1 , 562
2014-05-12 19:52:42 , 43 , 1 , 578

獲得的日誌數據如下,dust_log.csv:此數據因爲有調試對 Arduino 和數據收集時間等原因,有部分數據缺失,開關閾值爲 50 開, 20 關。其數據圖形如下(畫圖代碼參見 draw_log.R )。通過數據圖形展示了這個智能感應的 PM 空氣淨化器的運行情況和效果。粉塵吸附情況和房間大小、以及是否關窗有關。紅色區間主要是家裏做飯的時候,還有就是俺家廚房煙道有露煙,:(

Log 數據展現 0511Log 數據展現 0522

總之,現在俺的 Smart Air Filter 能夠自動開關,效果能夠通過數據觀測驗證,看起來還蠻不錯,不是嗎?

全部成本

剛又去淘寶上查了一下相關設備,有點小貴(主要是買 Arduino 板子和傳感器的時候,以興趣居多,沒考慮價格,當然,也不是隻幹這個用),供各位參考。

  • Arduino Yun ¥480
  • Shinyei PPD42NS ¥95
  • Grove Base Shield ¥59
  • 繼電器模塊 ¥20
  • 插座,超市中買的 ¥20
  • Smart Air Filter 1.0 ¥200

估計用更廉價的 Arduino 兼容板和較便宜的器件,能夠將總成本控制在 ¥400 元以內。


代碼地址

https://github.com/iascchen/smarter_air_filter/


玩的開心!


轉載請註明出處

Author : iascchen(at)gmail(dot)com

Date : 2014-5-12

Github : https://github.com/iascchen

新浪微博 : @問天鼓

CSDN : http://blog.csdn.net/iascchen

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章