Linkit Smart 7688 Duo上使用PMS3003 (G3) 空汙感測器

Home AllLinkit Smart 7688 Duo上使用PMS3003 (G3) 空汙感測器
57721adbe03b3948839f97f732c6981d.image_.530×397

Linkit Smart 7688 Duo上使用PMS3003 (G3) 空汙感測器

No Comments

作者:

Behind the project…

我是最近一段時間才開始摸索 IoT 生態的,是興趣;但相對我過去的工作經驗,應該是算是業餘的嘗鮮族。然後,發現雖然不是電子背景出身要動動手當個【創客】好像不是件太困難的事。於是,我跟在智慧家電領域的同學 Harvey 聊了這個想法,他毫不考慮了丟了個 Arduino 套件讓我嘗試。這真是有趣的世界,我好像可以去做一些事,一些以前不認為可以獨力幹的事。這也開始了我的創客生活。

回到我那個搞智慧家電的同學 Harvey,在玩弄他丟給我的 Arduino 一段間後,有一天他又問我說能不能搞個空氣品質觀測的應用,因為… 有這個需求。聽起來很有趣,於是有了這個 project 的想法。

他說就很簡單,弄個空氣品質感測器,然後把測得的數據顯示出來,然後…
最好可以把數據資料給保存起來 (Database/Cloud?)
最好可以把數據資料整理再呈現 (Analysis and vistualization?)
最好可以透過不同的介面被呈現 (LCD/TFT/Web/App?)
最好可以盡可能地把體積小型化 (7688/Duo?)
最好可以把整體費用壓到最便宜 (Arduino+Wifi or 7688/Duo?)
最好可以… 明天醒來這一切都實現了。

Arduino 讓很多創客可以輕易的踏出第一步,而且獲得成就感。

但是隨著想法和功能越趨複雜,就發現 Arduino 開發板好像要疊的積木更多,要寫的 sketch code 更長,然後 Flash Rom 的 size 好像也開始不夠用了。於是,我開始尋找具備相當整合性的開發板:我想至少幫我把網路(Ethernet 或 Wifi 都好)整合在開發板吧,或至少讓我除了有 Arduino C 以外,還具備更有伸展性的開發環境吧(可以來點跟互聯網相關的嗎)!

我在想把這類裝置和互聯網連接上是一件有趣的事(我在講什麼!IoT 不就是為了這檔事嗎?),事實上我很喜歡這樣的結果。

於是我幾番考慮後決定使用【LinkIt Smart 7688 Duo】。當然,其他開發板也做得到,而且功能也更強大,只是我比較背骨偏偏選擇這個新上市的薄薄的一片來玩。

事實上,因為 7688/Duo 才上市(2015.12.25)不久,網路上的資源有限,摸索 MCU 和 MPU 的互動過程中也讓我吃了不少閉門羹,畢竟我只是幾個月的創客生手,這摸索的路是必經的過程就不再多做文章了。

有感這一路學習的資源都是透過互聯網來的,很多觀念和程式技巧的養成都是分享自許多前人的貢獻,我真的很感激(鞠躬+讚嘆)。那天跟 LASS 的哈爸在臉書訊息上聊了一下,發現除了 7688/Duo 資源的短缺著實讓很多人學習過程受挫外,開源共享的模式也還未遍地開花結果,很多成功的經驗自然無法繼續被擴充和延續。有鑑於此,既然自己是喝互聯網的奶水長大的,就也分享自己的奶水(呵)給大家吧,我決定把自己這走這一遭的經驗全部給紀錄並公開給大家參考,希望可以幫助更多初心者一路好走,ㄟ 是起步的順利一點。

Ready? Let’s Go!

有了之前一些嘗試的經驗,這次我決定要以簡潔和滿足最低功能需求的前提下去實作這個 project。

一開場就梭哈了,以下是這次硬體上我所用上的元件:

  • Planter PMS3003(G3)/PMS5003(G5)PMS3003
  • LinkIt Smart 7688 DuoLinkit Smart 7688 Duo
  • Grove Breakout for LinkIt Smart 7688 DuoGrove Breakout for LinkIt Smart 7688 Duo
  • Hitachi HD44780U 1602 LCD (I2C)Hitachi HD44780U 1602 LCD
  • DS1307 RTC(I2C)DS1307_RTC

選擇 PMS3003(或是叫 G3)的原因是有以下特點:

  • 數據準確:鐳射檢測,穩定、一致性好
  • 回應速度快速:使用環境變更時回應時間小於 10 秒
  • 獨立運作:使用標準的通訊埠輸出量測資料
  • 不須外加元件:自備風扇,不須外加。
  • 分析能力高:分辨顆粒最小直徑達 0.3 微米

為了降低實作過程中硬體配置的接線複雜度(另一方面是偷懶),我選擇搭配了 Grove Breakout for LinkIt Smart 7688 Duo 這塊擴充版來串接另外兩個 I2C 設備(用在 1602 LCD 和 RTC);當然這不是必要的,你也可以有另外兩個替代方案:

  • 如果想降低成本或是先做開發測試,可以使用麵包板(breadboard)用杜邦線來處理配線。
  • 如果想簡化整個硬體的體積,可以考慮剪裁一張適當的PCB來焊接處理配線。

接下來的步驟就像玩樂高積木一樣,請把它們組合起來。

  • 7688/Duo 開發板直接對準腳位插上 Grove Breakout就可以。
  • 另外 LCD 和 RTC 因為都是選用 grove I2C 規格,也直接插上去 Grove Breakout 就可以。
  • 加工(1),因為 PMS3003 的排線是 Molex 1.25mm 8P 的規格,為了方便和開發板那端接,我自己裁了一小塊PCB然後把這8條線焊上標準的 2.54mm 排插(參考附圖)。
  • 加工(2),非必要,請視實際情況參考,因為我選用LCD元件供電是5v,另外 PMS3003 的供電也是 5v,但是開發板上的 5v 只有一個插槽,我就直接利用加工(1)裁的那塊PCB焊上一條5v共腳的單排插,把所有要用到5v的供電的元件都一起接過來,然後再接一條線過去開發板上的5v。
  • 非必要,請視實際情況參考,把LCD元件的 VCC/5v 改接到PCB 剛剛焊的 5v 共腳排插。
  • 參考 PMS3003 的 datasheet 把: PIN(1) VCC/5v 接到 PCB 剛剛焊的 5v 共腳排插。
  • 參考 PMS3003 的 datasheet 把: PIN(2) GND 接到開發板的 GND 端。
  • 參考 PMS3003 的 datasheet 把: PIN(4) RXD 接到開發板的 D10 端。
  • 參考 PMS3003 的 datasheet 把: PIN(5) TXD 接到開發板的 D09 端。

PMS3003 PIN out

pms3003_pinout

PMS3003 G3 PM2.5 粉塵感測器接腳圖。資料出處:https://www.dfrobot.com/wiki/index.php?title=PM2.5_laser_dust_sensor_SKU:SEN0177

8 Pin 接腳和 5v共腳排插加工PCB

PCB for 8 PIN

整體實物佈線配置(由於我還沒有整理線路,所以圖片凌亂的線路傷眼睛請不要怪我)
另外圖中配線有一大把接到 LCD 的原因是那塊 LCD 和 I2C 控制晶片模組是我分開買自己再用杜邦排線焊接的,直接選購帶I2C控制晶片模組的 1602 LCD 省事多了,又免掉一堆線路。
The System
=================================================

Plan for the software architecture

接下來我們可以開始來聊聊程式架構和佈局了。

但是,在此之前我想先借用 Linkit Smart 7688 Duo Developers’ Guide 上面的一張圖片來引導7688/Duo程式架構可能的方式有哪些,以及我選擇用什麼模式來開發。

development model of Linkit Smart 7688 Duo

如果你選擇了 Linkit Smart 7688 Duo 這個開發板,你應該(或許)知道這個板子上面比 Linkit Smart 7688 多了一顆 ATMega32u4 MCU 晶片。這意味著兩件事,(1)你可以在 7688/Duo 上面實現大部分 Arduino(UNO) 可以做的事。(2)你的軟體開發模式可以有更多元的模式,如上圖(右)揭露的三種方式。

我的開發模式選擇第二種模型,也就是預設的方法,因為在這裡我不需要 MPU 下任何溝通指導給 MCU,單單僅要用它丟過來的資料即可:
SerialPort Model

我的想法是,既然開發板同時有 MPU(MT7688) 和 MCU(ATMega32u4),那麼就讓兩顆晶片分工做他們擅長的事吧;也就是對sensors 讀取資料的事完全交給 MCU 做,讀到的資料透過內部 Serial Port 協定傳給 MPU,然後所有邏輯處理和聯網作業就交給 MPU。以上理由是我自己掰的,不管有沒有道理聽聽就好,重點他真的可以跑得動(初心者,我好感動!)。

接下就是整體的架構規劃了,我把整個實作又再切成兩大塊,第一部分是純粹發生在 Linkit Smart 7688 Duo 身上的程式,這也是我會多著墨的地方,以及第二部分是在網頁呈現的部分這部分就偏離 7688/Duo 的探討範圍,我會僅就 UI 的呈現說明,不細究程式的撰寫。

在 Linkit Smart 7688 Duo 上面運行的程式分 MCU 端以及 MPU 端的工作,我們可以用兩隻獨立的程式來滿足不同的功能需求:

  • MCU 主要的工作有3件事,(1)讀取 sensors 資料,(2)把讀取到的 sensors 資料顯示在 LCD,(3)打包 sensors 資料給 MPU
  • MPU 的工作有就只有一件事,把收到來自 MCU 的 sensors 資料寫入資料庫。

在資料保存和網頁呈現端有兩種可以選擇,就端看你熟悉怎樣的程式技巧了。如果熟 PHP 可以考慮用第一種,如果非常懂Node.js 可以走第二種方法。我比較偷懶,用第一種架構(PHP)來實作資料保存。
Development Model 1
Development Model 2

MCU(ATMega32u4) side programming
MCU 程式下載 (.ino)

我要說好在 7688/Duo 用的 MCU 是和 Arduino(UNO) 相同的 ATMega32u4 晶片,所以我們可以把 Arduino IDE 開發的那套經驗,完全套用在這裡甚至不用修改程式碼(我試過了,移植性是 100%)。有關 Arduino IDE 的環境操作就請自己練習了,我唯一要提醒的是:請務必記得依照 Linkit Smart 7688 Duo Developer’s Guide 把 Arduino IDE 的開發板環境設定成 7688/Duo 啊~ 不然你的紅色錯誤訊息會一直出現…

我們直接切入主題,上面說我們規劃的時候,就只打算讓 MCU 負責以下3件事:

  • (1)讀取 sensors 資料
  • (2)把讀取到的 sensors 資料顯示在 LCD
  • (3)打包 sensors 資料給 MPU

(1)讀取 sensors 資料

RTC時間的讀取 和 LCD 資料的顯示應該算超簡單的練習,相信直接看 sketch code 就可以懂,這裡就不贅述了。我們直接來看 PMS3003 (G3) 這顆 sensor 的參數特性:

首先,它可以採樣測定的空氣懸浮微粒有三種規格 0.3-1.0um/1.0-2.5um/2.5-10um,也就是說我們可以拿到 PM1.0/PM2.5/PM10 的測定資料(ug/m3)。而且PMS3003 的 datasheet 寫到他有兩套檢定空氣品質濃度的方法,分別是可以獲得「大氣環境下」和「標準顆粒物」兩組資料值,所以程式裡面每一次從 sensor 那邊得到的資料就會有2組,6個測定值。(這裡我會在意的是「大氣環境下」測得的這組)

這裡我要補充說明的是,範例裡面使用程式去讀取 PMS3003 資料那段邏輯在網路上有多種不同的實作(讀到的資料值都相同啦),我是參考一個程式寫的很簡潔的網友的(雖然他的方法也偷懶少做了checksum),如果看不懂建議您直接看一下 PMS3003 的 datasheet。或是參考下面這另一個出處的邏輯:https://www.dfrobot.com/wiki/index.php?title=PM2.5_laser_dust_sensor_SKU:SEN0177

再來,它的資料介面使用標準序列阜(Serial port baudrate: 9600; Parity: None; Stop Bits: 1; packet length is fixed at 24 bytes.)讀取,從PIN(4)和PIN(5)接腳可以和他溝通 (RX/TX)。這裡有個注意的地方,如果我們直接以 Arduino 的 Serial1 類別去讀取 RX/TX 將會有問題。原因是 7688 把預設的第一組 UART(D0/D1) 保留給 MCU 和 MPU 的溝通使用,所以把 PMS3003的 RX/TX 插上 7688/Duo 的 D0/D1 是讀不到資料的,請記得預設情況下在 7688/Duo 裡面,Serial1是MCU丟資料給MPU的通道口。

我使用另一個替代方法即用 SoftwareSerial() 類別去實作 serialport 和他溝通,這個方法可以選用 7688/Duo 上面有限定可用的數位腳位去指定(RX/TX)。所以記得程式一開始必須把SoftwareSerial.h 這句宣告(#include)包含進來。

(2)打包 sensors 讀取的資料

在這裡我選用 JSON 資料格式來打包 PMS3003 讀取到的資料和 DS1307 RTC 得到的日期和時間。所以在程式裡面一開始就會看到關於 ArduinoJson.h 宣告(#include)就是這個原因。

這裡我舉一個採集到的資料,他被包成 JSON 格式後的範例給大家參考:

{
"sensor": "PMS3003",
"date": "2016-03-13",
"time": "05:34:11",
"pm010_TSI": "07",
"pm010_ATM": "07",
"pm025_TSI": "10",
"pm025_ATM": "10",
"pm100_TSI": "16",
"pm100_ATM": "16"
}

資料名稱 _ATM 指的就是「大氣環境下」方法測得的數據。
資料名稱 _TSI 指的就是「標準顆粒物」方法測得的數據。

接下來打包完的 JSON 資料,就是要把資料往 MPU 送。


之前寫個這一段,後來我重新看過程式,發現 FIRMATA protocol 只被我宣告,但是在我的 code 裡面宣告後一直沒有使用(因為我發現那個是我移植另一個測試用的),所以下面粉紅色這塊注釋裡面,我把之前 sketch code 裡面這兩行給直接刪除掉(程式已經更新了)。

Firmata.h 的宣告那行(#include)
Firmata.begin(Serial1);

設定MCU/MPU溝通(Serial Port) 的 Baud Rate Rate = 57600,然後把打包的 JSON 資料物件(這裡的範例是 Jasonroot)直接寫進去 Serial1即可:


Serial1.begin(57600);
Jasonroot.printTo(Serial1);

最後我們把範例程式 compiler 完 upload 到 7688/Duo 板子後,打開 Arduino IDE 的 Serial Monitor 觀看執行結果,應該會如同下圖所示。
SerialPort_Monitor

LCD 端的顯示應該如下圖:
LCD 1602 Display

補充說明,程式中設定每隔 10 秒 (10,000 ms) 去讀取 sensors 資料一次。

MPU(MT7688AN) side programming
MPU 程式下載 (.js)

我們複習一下,在這個設定好的故事裡面 MPU 的工作有就只有一件事,把揭開來自 MCU 的 sensors 資料寫入資料庫。

當我們把 MCU 的 sketch 給 upload 後,sensor 所讀到的值經包裝成 JSON 後將會源源不絕的被送到 Serial1。既然我們知道源頭的水進入 Serial1 這條水管後,我就可以在另一頭接水使用了,MPU 的工作就從接水開始。

MPU 端的程式我選擇用 Node.js 來實作,好處就是他已經是出廠就安裝好的開發環境,不用自己去煩心安裝主程式和相關套件的問題。

在 Node.js 中先宣告一個序列阜 serialport 的物件 ==> var com = require(“serialport”);
把這個序列阜物件設定以 Baud Rate = 57600 的速度連到 /dev/ttyS0 這個 port 串口, /dev/ttyS0 就是接水口,水源就是剛剛在 MCU 持續每隔10秒鐘寫入的 JSON 資料。

既然我們在 MCU 端包裝資料就是以 JSON 格式包裝,這裡我們就可以用 Node.js 的內建 JSON 函數把它解(parse)出來。這裡我非常簡單的檢查收到的資料是不是有無效的資料( if (jobj.xxxxx==”undefined”)),如果有這一包資料我就不要了,直接忽略他。 當然你應用更嚴僅的方法去過濾垃圾資料,我這裡只是偷個懶,千萬別學我,不然程式執行過程是會有機會被無緣無故的垃圾操作給中斷的。

寫到這裡,當千辛萬苦的資料都到手了,現在要殺要刮就輕而易舉了,是不?(耶!下課了)在這個階段可以做的事太多了,但是以我的規劃,當MPU把資料拿到手後的下一步是寫進去資料庫存起來,我選用的辦法是,用 HTTP Client 去發動一個 PHP 程式帶必要的資料過去,然後由 PHP 處理資料建檔。

會喜歡 Node.js 的原因是,他剛好有內建 HTTP Server/Client 的服務,我只要把資料以合乎URL規範的格式編輯好再交付給 HTTP Client 去觸發執行即可。

比方說,我們用下的例子當範例:

MPU 當下收到的資料解開如下


[sensor]= PMS3003
[date]= 2016-03-13
[time]= 09:10:07
[pm010_TSI]= 10
[pm025_TSI]= 15
[pm100_TSI]= 18
[pm010_ATM]= 10
[pm025_ATM]= 15
[pm100_ATM]= 18

那我就會利用一隻位在 pm25.com 這部 web server 上面一隻已經編程好的 PHP 程式 cgi_insert_sensor_data.php 幫我做建檔資料,最簡單的 URL 字串可以寫成如下:(資料的傳遞是以 key=value 的方式用一個 & 符號串起組成)


http://pm25.com/cgi_insert_sensor_data.php?input_SID=PMS3003&input_datetime=2016-03-13T09:10:07&pm010_TSI=10&pm025_TSI=15&pm100_TSI=18&pm010_ATM=10&pm025_ATM=15&pm100_ATM=18

而當位在 pm25.com 這部 web server 上的 cgi_insert_sensor_data.php 收到後,我會把資料轉成如下 SQL 語言,然後呼叫資料庫函數寫入資料庫:


SQL Command String =INSERT INTO Resort.Weather(Sensor_Id, Sensor_Datetime, pm010_TSI, pm025_TSI, pm100_TSI, pm010_ATM, pm025_ATM, pm100_ATM) VALUES (‘PMS3003’, ‘2016-03-13T09:10:07’, 10, 15, 18, 10, 15, 18 )

這樣一來,資料建檔就可以被存放在任何有接通資料庫的互聯網主機上了。當然,如果資料庫是在近端的網域內,你可以直接考慮以 Node.js 直接寫入資料庫,而不用再維護一支遠端主機上的 cgi 程式。

實際操作方面,我假設你已經會用 SSH 遠端登錄到你的 7688/Duo ,並且會一些很基本的 Linux 指令,這是因為 7688/Duo 的 OS 是採用 Linux 近親 OpenWrt的緣故,如果你一點都不懂的話會很吃力,先找幾帖 Linux 大補帖惡補一下吧。

待 login root 後,請建立一個目錄例如:
root@mylinkit:~#mkdir app

切換到該目錄:
root@mylinkit:~#cd app

用任何拿手的 text editor 編輯一個新的文字檔如:
root@mylinkit:~/app#vi PM25_7688Duo.js

把範例程式碼貼上去,存檔後離開。
接下來我們要讓這個程式碼發生作用,必須用 node 啟動執行它:
root@mylinkit:~/app#node PM25_7688Duo.js

等個幾秒後,畫面應該就會 prompt 出一些資料,這是我把執行過程中的資料片段丟到畫面來觀測的緣故,當然這個階段程式會佔據你的控制權,您沒辦法做其他的事,事實上您也不需要在這時間做任何事,因為 node 程式正很忠實地幫你一分一秒做你要他做的事,那到底他做了什麼?我們上面的說明已經解釋過了(要終止這隻程式的獨佔模式而回到命令列可以同時按下 [control]+[c] 兩個按鍵,程式就會立即中止了)。

下面是啟動 node 程式執行的畫面截圖,可以供參考。
MPU_screenshot

Data Visualisation

網頁端的資料呈現不是這個題目的範圍,我等有空在講個概念吧!
這裡我就先分享一個我初步弄出來的樣子供大家參考,各位可以構思自己的視覺呈現。

數據視覺化輸出展示

以上簡單的說明,希望對 Linkit Smart 7688 Duo 抱有期待又沒辦法突破的你有所幫助。

發佈留言