空氣盒子感測器資料上傳至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檔案。開啟時,其他的檔案都會匯入進來,以下為重要程式說明。

重要程式說明

51,52,55,56,60,66,68,72,74-76,79-85,173-177
/**************************************************/
/* Copyright © 2021 CAVEDU. All rights reserved.

The AirBox program is suitable for sensors:

Grove-DHT20:
https://robotkingdom.com.tw/product/grove-%e6%ba%ab%e6%ba%bc%e5%ba%a6%e6%84%9f%e6%b8%ac%e5%99%a8temperature-humidity-sensor-v2-0-dht20-upgraded-dht11-i2c-port/

SPG30:
https://robotkingdom.com.tw/product/grove-voc-and-eco2-gas-sensor-sgp30/

OLED Display 0.96:
https://robotkingdom.com.tw/product/grove-oled-display-0-96/
(Also suitable for Grove-OLED Display 0.96”:https://robotkingdom.com.tw/product/oled-display-0-96/)

Education Kit 001 Button :
https://robotkingdom.com.tw/product/rk-education-kit-001/

You can see the AirBox Technical article:
https://blog.cavedu.com/2021/01/20/linkit-7697-airbox/

https://blog.cavedu.com/2021/11/25/linkit-7697-airbox-2/

*/
/***************************************************/

#include "PMS.h"
#include <SoftwareSerial.h>
#include "U8g2lib.h"
#include <DHT.h>
#include "sensirion_common.h"
#include "sgp30.h"
#include <LRTC.h>
#include <WiFiUdp.h>
#include <ctime>
#include "Wire.h"
#include "MCS.h"



/*============Pins==================*/
#define buttonPin 4
#define PMSTx 2
#define PMSRx 3
//#define DHT11Pin 10
#define DHTTYPE DHT20 // DHT 20
/*====================================*/

//Enter WIFI SSID & Password
#include <LWiFi.h>
char _lwifi_ssid[] = "_lwifi_ssid";
char _lwifi_pass[] = "_lwifi_pass";

//Enter IFTTT_key & Event_name
char IFTTT_key[] = "IFTTT_KEY";
char Event_name[] = "Event_Name";

unsigned long current_time = 0;//record current time
unsigned long previous_IFTTT_time = 0;//Record the last time of IFTTT
int IFTTT_upload_time = 2000;//IFTTT intervals of time

int frame = 0;

/*ThingSpeak value*/
unsigned long previous_ThingSpeak_time = 0;//record current time
int ThingSpeak_upload_time = 1000*60*10;//ThingSpeak intervals of time

String Write_API_key= "Write_API_key";//輸入ThingSpeak的 Write_API_Key

/*MCSLITE value*/
unsigned long previous_mcslite_time = 0;//record current time
int mcslite_upload_time = 1000*60*10;//MCSLITE intervals of time

#define _your_MCSLite_DeviceId "_your_MCSLite_DeviceId" //輸入MCSLite的DeviceId
#define _your_MCSLite_DeviceKey "_your_MCSLite_DeviceKey" //輸入MCSLite的Devicekey
#define _your_MCSLite_IP "_your_MCSLite_IP" //輸入MCSLite的IP
MCSLiteDevice mcs(_your_MCSLite_DeviceId , _your_MCSLite_DeviceKey, _your_MCSLite_IP, 3000);

MCSDisplayInteger _1F_CO2("_1F_CO2");
MCSDisplayInteger _1F_TVOC("_1F_TVOC");
MCSDisplayInteger _1F_PM10("_1F_PM10");
MCSDisplayInteger _1F_PM1_0("_1F_PM1_0");
MCSDisplayInteger _1F_PM2_5("_1F_PM2_5");
MCSDisplayInteger _1F_TEMP("_1F_TEMP");
MCSDisplayInteger _1F_HUMI("_1F_HUMI");

SoftwareSerial PMSSerial(PMSTx, PMSRx);
PMS pms(PMSSerial);
PMS::DATA data;
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
/*Monitor rotate angle
U8G2_R0 0 degrees
U8G2_R1 90 degrees
U8G2_R2 180 degrees
U8G2_R3 270 degrees
U8G2_MIRROR mirror
*/
#define imgWidth 128
#define imgHeight 48

int pms1_0, pms2_5, pms10_0;
int temp;
int humi;
int button_state;

s16 err = 0;
u16 tvoc_ppb, co2_eq_ppm;


//DHT dht11_p10(DHT11Pin, DHT11); //define dht11 PIN
DHT dht(DHTTYPE);

#if defined(ARDUINO_ARCH_AVR)
#define debug Serial

#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
#define debug SerialUSB
#else
#define debug Serial
#endif


float temp_hum_val[2];

void setup()
{
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
debug.println("DHT20 test!");
Wire.begin();
dht.begin();
//dht11_p10.begin();

PMSSerial.begin(9600);
LRTC.begin();
SGP30_int();
oled_int();
msclite_channel_int();
pinMode(buttonPin, INPUT);

}

void loop()
{
float temp_hum_val[2] = {0};
button_state = digitalRead(buttonPin);
//temp = dht11_p10.readTemperature();
//humi = dht11_p10.readHumidity();


while (!pms.read(data)) {} //PM2.5 read Data
pms1_0 = data.PM_AE_UG_1_0;
pms2_5 = data.PM_AE_UG_2_5;
pms10_0 = data.PM_AE_UG_10_0;

err = sgp_measure_iaq_blocking_read(&tvoc_ppb, &co2_eq_ppm);
if (err == STATUS_OK) {
Serial.print("tVOC Concentration:");
Serial.print(tvoc_ppb);
Serial.println("ppb");

Serial.print("CO2eq Concentration:");
Serial.print(co2_eq_ppm);
Serial.println("ppm");
} else {
Serial.println("error reading IAQ values\n");
}



sensor_oled_task(); //OLED show sensor value
button_oled_show_time();//Press Button to show time
//IFTTT_pm25_temp_humi_task();//Upload sensor value to IFTTT
upload_to_msclite_task();//Upload sensor value to msclite
upload_to_ThingSpeak();//Upload sensor value to ThingSpeak
}
  • 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的使用教學,下次見!

發佈留言

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