空氣盒子感測器資料上傳至MSCLITE&ThingSpeak雲服務

前言

本文延續【LinkIt™ 7697空氣品質偵測並上傳Google表單(空氣盒子2.0)】,本文要進一步把空氣盒子的監測數值分別上傳到MCSLite和ThingSpeak中,並會比較IFTTT、MCSLite和ThingSpeak的優缺點。

本範例程式碼下載請點我

撰寫/攝影 許鈺莨
前情提要
時間 1小時 材料表 空氣品質監測基本材料包
(使用LinkIt™ 7697、Grove 擴充板)
連結: https://robotkingdom.com.tw/product/airbox-kit-linkit-7697-2/

Grove -VOC與eCO2 氣體感測器(選配)
連結:
https://robotkingdom.com.tw/product/grove-voc-and-eco2-gas-sensor-sgp30/

成本 難度  **** (最高10顆星)

 


我們將三套空氣盒子放置在機器人王國的 B1、一樓店面及三樓辦公室,並將空氣盒子的監測數值上傳到雲端。

B1

一樓店面

三樓

之前是將數值透過IFTTT上傳至Google表單,如果讀者有興趣請看【LinkIt™ 7697空氣品質偵測並上傳Google表單(空氣盒子2.0)】。本文則是要進一步把空氣盒子的感測器數值上傳到 MCSLite 和 ThingSpeak 兩個不同的雲服務中,。為將空氣盒子數值傳上ThingSpeak是新的嘗試,所以會著重ThingSpeak的說明,而因為程式碼比較龐大,所以會重點解釋程式碼,以下本文開始。


筆者針對目前使用過的雲端平台做一些心得感想:

1. 透過IFTTT上傳至Google表單

使用IFTTT的好處就是方便串接兩種不同的服務,而這樣的組合可說是變化多端。設定好之後可以做一套自動化的執行程序(Applets)。例如:當空氣盒子偵測到溫度過高可以傳訊息到LINE中通知。

對於偵測數值有變化進而可以控制裝置,或傳通知訊息的專案,可以使用這個方案,但缺點就是在2020年10月7號後,就會需要付費成專業版,可不受限制可以建立多個個人化的執行程序,若使用免費方案的話,最多只能有 3 個 applet,超過的話就必須刪除,以下就是當時收到建議付費成專業版的郵件內容。

再來是上傳數值的種類,最多只能選擇三種,例如:溫度、濕度、CO2數值,除此之外,筆者還發現,上傳到Google的表單的數值,最多只能顯示2000列,如下圖所示。

2. MCSLite

由聯發科技物聯網雲端平台 MediaTek Cloud Sandbox(MCS)的核心功能改寫而成的輕量化程式,雖然MCS在 2021年4月16日停止了服務,但是MCSLite還是有繼承MCS的部分功能,而且 MCSLite 還可以直接運行於 Windows、Linux、Mac OS 等作業系統,方便不聯外網的區域網路使用。

使用MCSLite優點是可以在網頁中可以創建控制通道和顯示通道,可以透過控制頁面來控制裝置,而在創建產品原型時可以無限制建立,而每個產品原型也可以無限制創建出測試裝置。

其缺點是只能將上傳的資料點存在雲端中,而無法下載成CSV檔或JSON檔等格式,儲存到電腦中。

3. ThingSpeak

ThingSpeak 是由知名MATLAB公司所提供的免費空間,每個註冊帳號可以免費有四個頻道(channel),而每個頻道可有八個自訂欄位(field),這意味著可以上傳八種不同的數值,可以提供很直觀圖表製作的功能,也可以下載CSV檔到電腦中,手機端也有專用 app 來檢視資料。但缺點就是無法像 IFTTT 一樣,可以設定超過一定數值就會推播訊息到裝置中,或像MCSLite可以有控制頁面直接控制裝置。


再來要說明如何將空氣盒子的資料點上傳到MCSLite和ThingSpeak的平台,首先以下說明建立這兩個的平台的註冊流程及通道建立。

上傳資料到 MCSLite

MCSLite從下載解壓縮檔案到註冊流程及通道建立,請由此網頁【5-4 MCS Lite介紹及MCS Lite環境建置】來查閱。

上傳資料到 ThingSpeak

以下為建立ThingSpeak平台通道的詳細步驟:

第一步:註冊 ThingSpeak 帳號

先到 ThingSpeak 網站註冊一個免費帳號

填寫Email信箱、所在地區…等基本資料,再按下Continue

第二步:建立頻道

註冊成功後,到上方頁面的Channels🡪My Channels

按下 New Channel 即可新增頻道

第三步:新增頻道

寫上頻道名稱,一個頻道可以建立最多8個欄位,代表空氣盒子可以上傳8種不同的數值。填完欄位名稱後,點選最下面的 Save Channel 代表頻道新增完畢。

筆者分別在公司的地下一樓、一樓店面及三樓辦公室個放了一個空氣盒子作環境監測,以下是三個樓層的頻道。

第四步:查詢API Key

由於 ThingSpeak 在此用於接收來自空氣盒子的感測器數值 (被寫入),所以這裡請複製Write API Key,後續程式會用到。

程式說明

本專案的程式是由BlocklyDuino附屬的Arduino IDE 1.8.5開啟,程式下載解壓縮後,請開啟CAVEDU_AirBox_V3_IFTTT_DHT20_1F.ino檔案。開啟時,其他的檔案都會匯入進來,以下為重要程式說明。

重要程式說明

[pastacode lang=”c” manual=”%2F**************************************************%2F%0A%2F*%20%20Copyright%20%C2%A9%202021%20CAVEDU.%20All%20rights%20reserved.%0A%0A%20%20The%20AirBox%20program%20is%20suitable%20for%20sensors%3A%0A%0A%20%20Grove-DHT20%3A%0A%20%20https%3A%2F%2Frobotkingdom.com.tw%2Fproduct%2Fgrove-%25e6%25ba%25ab%25e6%25ba%25bc%25e5%25ba%25a6%25e6%2584%259f%25e6%25b8%25ac%25e5%2599%25a8temperature-humidity-sensor-v2-0-dht20-upgraded-dht11-i2c-port%2F%0A%0A%20%20SPG30%3A%0A%20%20https%3A%2F%2Frobotkingdom.com.tw%2Fproduct%2Fgrove-voc-and-eco2-gas-sensor-sgp30%2F%0A%0A%20%20OLED%20Display%200.96%3A%0A%20%20https%3A%2F%2Frobotkingdom.com.tw%2Fproduct%2Fgrove-oled-display-0-96%2F%0A%20%20(Also%20suitable%20for%20Grove-OLED%20Display%200.96%E2%80%9D%3Ahttps%3A%2F%2Frobotkingdom.com.tw%2Fproduct%2Foled-display-0-96%2F)%0A%0A%20%20Education%20Kit%20001%20Button%20%3A%0A%20%20https%3A%2F%2Frobotkingdom.com.tw%2Fproduct%2Frk-education-kit-001%2F%0A%0A%20%20You%20can%20see%20the%20AirBox%20Technical%20article%3A%0A%20%20https%3A%2F%2Fblog.cavedu.com%2F2021%2F01%2F20%2Flinkit-7697-airbox%2F%0A%0A%20%20https%3A%2F%2Fblog.cavedu.com%2F2021%2F11%2F25%2Flinkit-7697-airbox-2%2F%0A%0A*%2F%0A%2F***************************************************%2F%0A%0A%23include%20%22PMS.h%22%0A%23include%20%20%3CSoftwareSerial.h%3E%0A%23include%20%22U8g2lib.h%22%0A%23include%20%3CDHT.h%3E%0A%23include%20%22sensirion_common.h%22%0A%23include%20%22sgp30.h%22%0A%23include%20%3CLRTC.h%3E%0A%23include%20%3CWiFiUdp.h%3E%0A%23include%20%3Cctime%3E%0A%23include%20%22Wire.h%22%0A%23include%20%22MCS.h%22%0A%0A%0A%0A%2F*%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3DPins%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D*%2F%0A%23define%20buttonPin%204%0A%23define%20PMSTx%20%20%20%20%202%0A%23define%20PMSRx%20%20%20%20%203%0A%2F%2F%23define%20DHT11Pin%2010%0A%23define%20DHTTYPE%20DHT20%20%20%20%2F%2F%20DHT%2020%0A%2F*%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D*%2F%0A%0A%2F%2FEnter%20WIFI%20SSID%20%26%20Password%0A%23include%20%3CLWiFi.h%3E%0Achar%20_lwifi_ssid%5B%5D%20%3D%20%22_lwifi_ssid%22%3B%0Achar%20_lwifi_pass%5B%5D%20%3D%20%22_lwifi_pass%22%3B%0A%0A%2F%2FEnter%20IFTTT_key%20%26%20Event_name%0Achar%20IFTTT_key%5B%5D%20%3D%20%22IFTTT_KEY%22%3B%0Achar%20Event_name%5B%5D%20%3D%20%22Event_Name%22%3B%0A%0Aunsigned%20long%20current_time%20%3D%200%3B%2F%2Frecord%20current%20time%0Aunsigned%20long%20previous_IFTTT_time%20%3D%200%3B%2F%2FRecord%20the%20last%20time%20of%20IFTTT%0Aint%20IFTTT_upload_time%20%3D%202000%3B%2F%2FIFTTT%20intervals%20of%20time%0A%0Aint%20frame%20%3D%200%3B%0A%0A%2F*ThingSpeak%20value*%2F%0Aunsigned%20long%20previous_ThingSpeak_time%20%3D%200%3B%2F%2Frecord%20current%20time%0Aint%20ThingSpeak_upload_time%20%3D%201000*60*10%3B%2F%2FThingSpeak%20intervals%20of%20time%20%0A%0AString%20Write_API_key%3D%20%22Write_API_key%22%3B%2F%2F%E8%BC%B8%E5%85%A5ThingSpeak%E7%9A%84%20Write_API_Key%0A%0A%2F*MCSLITE%20value*%2F%0Aunsigned%20long%20previous_mcslite_time%20%3D%200%3B%2F%2Frecord%20current%20time%0Aint%20mcslite_upload_time%20%3D%201000*60*10%3B%2F%2FMCSLITE%20intervals%20of%20time%20%0A%0A%23define%20_your_MCSLite_DeviceId%20%20%20%22_your_MCSLite_DeviceId%22%20%20%2F%2F%E8%BC%B8%E5%85%A5MCSLite%E7%9A%84DeviceId%0A%23define%20_your_MCSLite_DeviceKey%20%20%22_your_MCSLite_DeviceKey%22%20%2F%2F%E8%BC%B8%E5%85%A5MCSLite%E7%9A%84Devicekey%0A%23define%20_your_MCSLite_IP%20%20%20%20%20%20%20%20%20%22_your_MCSLite_IP%22%20%2F%2F%E8%BC%B8%E5%85%A5MCSLite%E7%9A%84IP%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0AMCSLiteDevice%20mcs(_your_MCSLite_DeviceId%20%2C%20_your_MCSLite_DeviceKey%2C%20_your_MCSLite_IP%2C%203000)%3B%0A%0AMCSDisplayInteger%20_1F_CO2(%22_1F_CO2%22)%3B%0AMCSDisplayInteger%20_1F_TVOC(%22_1F_TVOC%22)%3B%0AMCSDisplayInteger%20_1F_PM10(%22_1F_PM10%22)%3B%0AMCSDisplayInteger%20_1F_PM1_0(%22_1F_PM1_0%22)%3B%0AMCSDisplayInteger%20_1F_PM2_5(%22_1F_PM2_5%22)%3B%0AMCSDisplayInteger%20_1F_TEMP(%22_1F_TEMP%22)%3B%0AMCSDisplayInteger%20_1F_HUMI(%22_1F_HUMI%22)%3B%0A%0ASoftwareSerial%20PMSSerial(PMSTx%2C%20PMSRx)%3B%0APMS%20pms(PMSSerial)%3B%0APMS%3A%3ADATA%20data%3B%0AU8G2_SSD1306_128X64_NONAME_1_HW_I2C%20u8g2(U8G2_R0%2C%20%2F*%20reset%3D*%2F%20U8X8_PIN_NONE)%3B%0A%2F*Monitor%20rotate%20angle%0A%20%20%20U8G2_R0%20%20%20%20%200%20%20%20degrees%0A%20%20%20U8G2_R1%20%20%20%20%2090%20%20degrees%0A%20%20%20U8G2_R2%20%20%20%20%20180%20degrees%0A%20%20%20U8G2_R3%20%20%20%20%20270%20degrees%0A%20%20%20U8G2_MIRROR%20mirror%0A*%2F%0A%23define%20imgWidth%20128%0A%23define%20imgHeight%2048%0A%0Aint%20pms1_0%2C%20pms2_5%2C%20pms10_0%3B%0Aint%20temp%3B%0Aint%20humi%3B%0Aint%20button_state%3B%0A%0As16%20err%20%3D%200%3B%0Au16%20tvoc_ppb%2C%20co2_eq_ppm%3B%0A%0A%0A%2F%2FDHT%20dht11_p10(DHT11Pin%2C%20DHT11)%3B%20%20%2F%2Fdefine%20dht11%20PIN%0ADHT%20dht(DHTTYPE)%3B%0A%0A%23if%20defined(ARDUINO_ARCH_AVR)%0A%23define%20debug%20%20Serial%0A%0A%23elif%20defined(ARDUINO_ARCH_SAMD)%20%7C%7C%20%20defined(ARDUINO_ARCH_SAM)%0A%23define%20debug%20%20SerialUSB%0A%23else%0A%23define%20debug%20%20Serial%0A%23endif%0A%0A%0Afloat%20temp_hum_val%5B2%5D%3B%0A%0Avoid%20setup()%0A%7B%0A%20%20Serial.begin(115200)%3B%0A%20%20while%20(!Serial)%20%7B%0A%20%20%20%20%3B%20%2F%2F%20wait%20for%20serial%20port%20to%20connect.%20Needed%20for%20native%20USB%20port%20only%0A%20%20%7D%0A%20%20debug.println(%22DHT20%20test!%22)%3B%0A%20%20Wire.begin()%3B%0A%20%20dht.begin()%3B%0A%20%20%2F%2Fdht11_p10.begin()%3B%0A%0A%20%20PMSSerial.begin(9600)%3B%0A%20%20LRTC.begin()%3B%0A%20%20SGP30_int()%3B%0A%20%20oled_int()%3B%0A%20%20msclite_channel_int()%3B%0A%20%20pinMode(buttonPin%2C%20INPUT)%3B%0A%0A%7D%0A%0Avoid%20loop()%0A%7B%0A%20%20float%20temp_hum_val%5B2%5D%20%3D%20%7B0%7D%3B%0A%20%20button_state%20%3D%20digitalRead(buttonPin)%3B%0A%20%20%2F%2Ftemp%20%3D%20dht11_p10.readTemperature()%3B%0A%20%20%2F%2Fhumi%20%3D%20dht11_p10.readHumidity()%3B%0A%0A%0A%20%20while%20(!pms.read(data))%20%7B%7D%20%20%20%20%20%20%2F%2FPM2.5%20read%20Data%0A%20%20pms1_0%20%3D%20data.PM_AE_UG_1_0%3B%0A%20%20pms2_5%20%3D%20data.PM_AE_UG_2_5%3B%0A%20%20pms10_0%20%3D%20data.PM_AE_UG_10_0%3B%0A%0A%20%20err%20%3D%20sgp_measure_iaq_blocking_read(%26tvoc_ppb%2C%20%26co2_eq_ppm)%3B%0A%20%20if%20(err%20%3D%3D%20STATUS_OK)%20%7B%0A%20%20%20%20Serial.print(%22tVOC%20%20Concentration%3A%22)%3B%0A%20%20%20%20Serial.print(tvoc_ppb)%3B%0A%20%20%20%20Serial.println(%22ppb%22)%3B%0A%0A%20%20%20%20Serial.print(%22CO2eq%20Concentration%3A%22)%3B%0A%20%20%20%20Serial.print(co2_eq_ppm)%3B%0A%20%20%20%20Serial.println(%22ppm%22)%3B%0A%20%20%7D%20else%20%7B%0A%20%20%20%20Serial.println(%22error%20reading%20IAQ%20values%5Cn%22)%3B%0A%20%20%7D%0A%0A%0A%0A%20%20sensor_oled_task()%3B%20%2F%2FOLED%20show%20sensor%20value%0A%20%20button_oled_show_time()%3B%2F%2FPress%20Button%20to%20show%20time%0A%20%20%2F%2FIFTTT_pm25_temp_humi_task()%3B%2F%2FUpload%20sensor%20value%20to%20IFTTT%0A%20%20upload_to_msclite_task()%3B%2F%2FUpload%20sensor%20value%20to%20msclite%0A%20%20upload_to_ThingSpeak()%3B%2F%2FUpload%20sensor%20value%20to%20ThingSpeak%0A%7D” message=”51,52,55,56,60,66,68,72,74-76,79-85,173-177″ highlight=”” provider=”manual”/]
  • 51~52 第51行,輸入WIFI的SSID。
    第52行,輸入WIFI的密碼。
    55~56 第55行,輸入IFTTT的金鑰。
    第56行,輸入IFTTT的任務名稱。
    請看【LinkIt™ 7697空氣品質偵測並上傳Google表單(空氣盒子2.0)】[註1]文章。
    60 輸入上傳感測器到IFTTT的間隔時間(單位為毫秒)。
    66 輸入上傳感測器到ThingSpeak的間隔時間(單位為毫秒)。
    68 輸入ThingSpeak的Write_API_Key。
  • 72 輸入上傳感測器到MCSLite的間隔時間(單位為毫秒)。
  • 第74行,輸入MCSLite的DeviceId。
  • 第75行,輸入MCSLite的DeviceKey。
  • 第76行,輸入MCSLite的IP。請看【5-4 MCS Lite介紹及MCS Lite環境建置】[註2]。
  • 79~85 第79~85行,在MCSLite建立的資料通道。
  • 173 顯示感測器數值在OLED。
  • 174 按下按鈕會顯示時間在OLED。
  • 175 因IFTTT只能上傳三種數值,故選了PM2.5、溫度和濕度的數值。而程式前面有雙斜線則是註解,不會跑那一段程式。
  • 176 上傳感測器數值到MCSLite。
  • 177 上傳感測器數值到ThingSpeak 。

B1程式和一樓與三樓程式幾乎都一樣,所以就以一樓的空氣盒子程式來說明即可。更改完成後,就可以將程式燒錄到LinkIt™ 7697中,由於程式已整合成可同時把感測器數值上傳到IFTTT、MCSLite和ThingSpeak,若讀者想要上傳到IFTTT,請修改175行的註解。

以下為上傳到MCSLite和ThingSpeak成功的例子。

MCSLite

MCSLite屬於區域網路,無法公開網址,故分享感測器上傳成功的畫面。

ThingSpeak

ThingSpeak 可以公開頻道,在此分享網址給大家看看:

FB影片說明

https://www.facebook.com/watch/?v=453900302908283&ref=sharing

那麼以上就是空氣盒子2.0的使用教學,下次見!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *