ADVERTISEMENT
ThingSpeak網站是一個專業的物聯網平台,網址是https://thingspeak.com,讀者可以利用這個物聯網平台先行開發,該物聯網平台提供許多免費的資源。若讀者有不懂之處,可以參考筆者拙作:Arduino程式教學(無線通訊篇):Arduino Programming (Wireless Communication)(曹永忠, 許智誠, & 蔡英德, 2015f, 2015g)或網站上的文章等等。
前情提要:在進入這個部分之前,讀者可以先閱讀↓↓↓
建立帳號
讀者先到ThingSpeak網站建立帳號,網址是https://thingspeak.com
ADVERTISEMENT
▲ThingSpeak網站創建帳號完成後,會切換到這個畫面
帳號登入
ADVERTISEMENT
▲輸入你帳號正確資訊後,登入ThingSpeak網站。
查看Channel資料
▲讀者先登入ThingSpeak網站後,依下圖紅框處,先行查看目前的Channel。
創建新Channel
ADVERTISEMENT
▲如紅框區所示,點選New Channel選單來創建新的Channel。
▲這是創建新的Channel資訊的簡單介紹畫面。
▲讀者可以參考紅框區,將必要的資訊填入。
ADVERTISEMENT
▲讀者輸入資料後,將畫面捲軸拉至下方後,參考紅框處,選Save Channel的選單,將此Channel存檔。
▲如圖所示,完成Channel創建後,可以看到這個Channel的畫面。
取得Channel寫入金鑰
▲進入ThingSpeak網站,,建立一個新的Channel之後,先點選下圖紅框區,查看Channel的API Key的資料。
▲由紅框區處,可以看到本Channel寫入金鑰,本文範例是「UR42ZTYTE4PBQ8Y2 」。
手機控制電力開關
使用手機控制電力開關
我們打開LinkIt ONE開發板的開發工具:Sketch IDE整合開發軟體,編寫一段程式,如下表所示之手機控制插座開關測試程式,我們就可以使用Android手機,透過藍牙通訊來控制綠色能源之智慧插座,可以進行插座電力開啟與關閉,並且可以偵測插座電流。
手機控制插座開關測試程式(linkit_to_ThingSpeakV4_Bluetooth_Open)
#define SensorPin A1
#define RelayPin 13
#define turnon HIGH
#define turnoff LOW
#define MidValue 524
#define ReadMaxCount 200
char getdata ; // 儲存接收資料的變數
double Ampdata ; // 儲存接收資料的變數
void setup() {
pinMode(RelayPin , OUTPUT) ;
digitalWrite(RelayPin , turnon) ;
Serial.begin(9600);
Serial1.begin(9600) ;
// while(!Serial) ;
Serial.println("Program Start") ;
}
//String analogValue0 = String(lightMeter.readLightLevel(), DEC);
void loop()
{
getdata = '@';
// 若收到藍牙模組的資料,則送到「序列埠監控視窗」
if (Serial1.available()) {
getdata = Serial1.read();
Serial.print("(");
Serial.print(getdata, DEC);
Serial.print(")\n");
}
if (getdata == 67)
{
digitalWrite(RelayPin, turnoff) ;
}
if (getdata == 79)
{
digitalWrite(RelayPin, turnon) ;
}
if (getdata == 81)
{
Ampdata = ReadCurrentAverage() ;
Serial1.print("@");
Serial1.print(String(Ampdata,5) );
Serial.print("(") ;
Serial.print(Ampdata) ;
Serial.print("/") ;
Serial.print(String(Ampdata,5)) ;
Serial.print(")\n") ;
}
delay(200) ;
}
//===============
double ReadCurrent()
{
int Value = analogRead(SensorPin);
double Angv= (double)(Value - MidValue) ;
double Mv = Angv * 5000/1024 ;
double Amp = Mv /60 ;
double mAmp = Amp * 1000 ;
// Serial.print("Aout Value =( ");
Serial.print(Value);
Serial.print(" , ");
Serial.print(Angv);
Serial.print(" , ");
Serial.print(Mv);
Serial.print(" , ");
Serial.print(Amp) ;
Serial.print(" , ");
Serial.print(mAmp) ;
// Serial.print(")\n");
Serial.print("\n");
return Amp ;
}
double ReadCurrentAverage()
{
int Value;
double Angv;
double Mv;
double Amp = 0 ;
double mAmp ;
for(int i=0 ;i <ReadMaxCount; i++)
{
Value = analogRead(SensorPin);
Angv= ((double)(Value - MidValue) * 5000/1024) /60 ;
Amp = Amp + (Angv * Angv) ;
}
return sqrt(Amp/ReadMaxCount) ;
}
▲表3 手機控制插座開關測試程式
資料來源:(曹永忠, 許智誠, et al., 2015d, 2015e, 2015i, 2015j; 曹永忠, 蔡佳軒, et al., 2015a, 2015b)
原始碼下載網址:https://github.com/brucetsao/techbang/tree/master/201511/linkit_to_ThingSpeakV4_Bluetooth_Open
如圖所示,我們可以看到手機控制插座開關測試程式,在LinkIt ONE開發板上,當接受到”C”、”O”、”Q”等命令,就可以回覆手機正確的資訊,也可以執行下列動作:
- 命令O:開啟插座電力
- 命令C:關閉插座電力
- 命令Q:查詢插座使用電流,並用@電流值回傳到手機
控制電力手機程式設計
▲我們打開Chrome瀏覽器,進入的網站:,為了省卻讀者時間,可以到網址:https://github.com/brucetsao/techbang/tree/master/201511/IOT_APPs,下載:LK_Talk_ePower.aia檔,如上面所述,上傳APP Inventor2的原始碼到自己帳號的APP Inventors的保管箱。
▲我們可以切換到Block模式,進行程式編寫
▲完成之後,我們使用選單”Connect”的子選單”AI Comoanion”,會出現如下圖所示的QR Code畫面
▲我們在手機上執行AI Companion,然後掃描QR Code之後,進入程式畫面
手機控制插座畫面
▲進入程式之後,畫面如上
▲請按下「SelectBT」,選擇要通訊的藍牙模組(要事先跟手機配對完成才能被選到)
▲如圖所示,請選擇要通訊的藍牙模組(要事先跟手機配對完成才能被選到)
▲選完通訊的藍牙模組之後,進入系統主畫面
▲可以按下「插座」按鈕,在開啟狀態按下按鈕,就會關閉插座電力;在關閉狀態按下按鈕,就會開啟插座電力
▲可以按下「插座」按鈕,在開啟狀態按下按鈕,就會關閉插座電力;在關閉狀態按下按鈕,就會開啟插座電力
▲在開啟狀態下,可以按下「用電量」按鈕,則手機會透過藍牙通訊,與LinkIt ONE開發板通訊,要求進行電流偵測,在偵測之後,會回傳給手機,在顯示在手機上
▲除此之外,我們還可以按下「語音控制」按鈕,則手機會使用語音辨識模組
▲在手機上顯示語音辨識模組,請使用者輸入語音
- 語音中含有「開」:LinkIt ONE開發板會開啟插座電力
- 語音中含有「關」:LinkIt ONE開發板會關閉插座電力
- 語音中含有「查」:LinkIt ONE開發板會進行電流偵測,在偵測之後,會回傳給手機,在顯示在手機上目前使用電流(安培)。
▲到此,我們已經可以使用Android智慧型手機,透過我們開發的手機APPs,來操控「綠色能源之智慧插座」
物聯網之智慧電力開關
ThingSpeak雲端平台建立頻道
本文我們要將「綠色能源之智慧插座」送上雲端平台,本文使用「ThingSpeak雲端平台」,對於該平台,上面文章部分已有操作上的詳細介紹,所以不再詳述之。
首先,先進入「ThingSpeak雲端平台」,網址:https://thingspeak.com/,請先建立帳號後,登入該平台。
▲我們先查看目前已建立的頻道(Channel)
▲如圖紅框處所示,請讀者建立的一個頻道(Channel),並命名為「Current」的名字
▲請讀者在建立「Current」這個頻道時,如紅框處所示,請依本文內容一一鍵入
▲建立頻道之後,請點選「API Keys」,顯示「Current」頻道的讀寫金鑰。 讀者由紅框區處,可以看到「Current」頻道的寫入金鑰,本文範例是「7FQZ6JEDHQO6QF1H」。完成「Current」頻道建立後,請將寫入金鑰「7FQZ6JEDHQO6QF1H」記住,下列開發LinkIt ONE程式時,會用到。
物聯網之智慧插座程式設計
我們打開LinkIt ONE開發板的開發工具:Sketch IDE整合開發軟體,編寫一段程式,如下表所示之物聯網之智慧插座測試程式,我們就可以使用LinkIt ONE開發板的Wifi功能,連到無線基地台(Access Point:AP),透過網際網路,將綠色能源之智慧插座的所偵測到的插座電流,送到ThingSpeak雲端平台-我們建立的「Current」頻道內。
表4 物聯網之智慧插座測試程式
#include <LDateTime.h>
#include <LWiFi.h>
#include <LWiFiClient.h>
#define SITE_URL "184.106.153.149"
#define WIFI_AP "linkitone" //請輸入所要連的AP名稱
#define WIFI_PWD "" // 請輸入AP 密碼
LWiFiClient client;
// ThingSpeak Settings
String writeAPIKey = "7FQZ6JEDHQO6QF1H "; // Write API Key for a ThingSpeak Channel
const int updateInterval = 5000; // Time interval in milliseconds to update ThingSpeak// Variable Setup
long lastConnectionTime = 0;
boolean lastConnected = false;
int resetCounter = 0;
//=================
#define SensorPin A1
#define RelayPin 13
#define turnon HIGH
#define turnoff LOW
#define MidValue 524
#define ReadMaxCount 200
char getdata ; // 儲存接收資料的變數
double Ampdata ; // 儲存接收資料的變數
long mAmpdata ; // 儲存接收資料的變數
//===wifi var
//datatime data object
datetimeInfo t;void setup() {
pinMode(RelayPin , OUTPUT) ;
digitalWrite(RelayPin , turnon) ;
Serial.begin(9600);
Serial1.begin(9600) ;
// while(!Serial) ;
Serial.println("Program Start") ;
//wifi start here
LWiFi.begin();Serial.println();
Serial.print("Connecting to AP...");
// if(LWiFi.connectWEP(WIFI_AP, WIFI_PWD) < 0)
if(LWiFi.connect(WIFI_AP) < 0)
{
Serial.println("FAIL!");
return;
}
Serial.println("ok");
Serial.print("Connecting to site...");
if(!client.connect(SITE_URL, 80))
{
Serial.println("FAIL!");
return;
}
Serial.println("ok");
//client.close() ;
}
//String analogValue0 = String(lightMeter.readLightLevel(), DEC);
void loop()
{
// get date time
LDateTime.getTime(&t);
String analogdata = String(analogRead(SensorPin), DEC);
String tramformdata = String(analogRead(SensorPin), DEC);
String datedata = String(t.year, DEC)+"/"+String(t.mon, DEC)+"/"+String(t.day, DEC);
String timedata = String(t.hour, DEC)+":"+String(t.min, DEC)+":"+String(t.sec, DEC);
// get current data
Ampdata = ReadCurrentAverage() ;
mAmpdata = (long)(Ampdata * 1000) ;
delay(200) ;
Serial.print("Data is :(");
Serial.print(mAmpdata);
Serial.print("/");
Serial.print(Ampdata);
Serial.print(")\n");// Print Update Response to Serial Monitor
while (client.available())
{
char c = client.read();
Serial.print(c);
}
// updateThingSpeak("field4="+Ampdata);
// Serial.println("Update thingspeak is ok");
updateThingSpeak("field1="+datedata+"&field2="+timedata+"&field3="+Ampdata+"&field4="+mAmpdata);
Serial.println("Update thingspeak is ok");
delay(10000) ;
}
//===============
double ReadCurrent()
{
int Value = analogRead(SensorPin);
double Angv= (double)(Value - MidValue) ;
double Mv = Angv * 5000/1024 ;
double Amp = Mv /60 ;
double mAmp = Amp * 1000 ;
// Serial.print("Aout Value =( ");
Serial.print(Value);
Serial.print(" , ");
Serial.print(Angv);
Serial.print(" , ");
Serial.print(Mv);
Serial.print(" , ");
Serial.print(Amp) ;
Serial.print(" , ");
Serial.print(mAmp) ;
// Serial.print(")\n");
Serial.print("\n");
return Amp ;
}
double ReadCurrentAverage()
{
int Value;
double Angv;
double Mv;
double Amp = 0 ;
double mAmp ;
for(int i=0 ;i <ReadMaxCount; i++)
{
Value = analogRead(SensorPin);
Angv= ((double)(Value - MidValue) * 5000/1024) /60 ;
Amp = Amp + (Angv * Angv) ;
}
return sqrt(Amp/ReadMaxCount) ;
}
// ThingSpeak functions
//===============
void updateThingSpeak(String tsData)
{
if (client.connect(SITE_URL, 80))
{
Serial.println("Connected to ThingSpeak...");
Serial.println();
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(tsData.length());
client.print("\n\n");
client.print(tsData);
lastConnectionTime = millis();
resetCounter = 0;
}
else
{
Serial.println("Connection Failed.");
Serial.println();
resetCounter++;
if (resetCounter >=5 ) {resetEthernetShield();}
lastConnectionTime = millis();
}
}
void resetEthernetShield()
{
Serial.println("Resetting Ethernet Shield.");
Serial.println();
client.stop();
//delay(1000);
// Ethernet.begin(mac, ip, gateway, subnet);
delay(1000);
}
資料來源:(曹永忠, 許智誠, et al., 2015d, 2015e, 2015i, 2015j; 曹永忠, 蔡佳軒, et al., 2015a, 2015b)
原始碼下載網址:https://github.com/brucetsao/techbang/tree/master/201511/linkit_IOT_ThingSpeakV1
▲當上面程式寫好後,編譯完成後,請上傳到LinkIt ONE開發板,並開啟監控畫面就可以看到如圖所示之傳送資料到ThingSpeak雲端平台:
▲我們用瀏覽器,到ThingSpeak雲端平台,查看我們建立的「Current」頻道,就可以看到如圖所示的資料,讀者也可以做進一步分析,或從ThingSpeak雲端平台,將「Current」頻道的資料下載。
總結
本文到此,已經教導各位讀者使用強大無比的LinkIt ONE開發版,完成「綠色能源之智慧插座」的設計與開發,並可以使用手機操控,查詢電流,也可以將電流資料上傳到ThingSpeak雲端平台,整個開發的完整性,可以說非常豐富與完整,至於資料分析的範疇,本屬於巨量分析(Big Data)的領域,不再本文中詳述,後續筆者會再針對巨量分析(Big Data)的領域,發表相關的進階內容,請讀者拭目以待。
作者介紹:
曹永忠 (Yung-Chung Tsao):目前為自由作家、專研於軟體工程、軟體開發與設計、物件導向程式設計,商品攝影及人像攝影。長期投入資訊系統設計與開發、企業應用系統開發、軟體工程、新產品開發管理、商品及人像攝影等領域,並持續發表作品及相關專業著作。
Email:prgbruce@gmail.com
Line ID:dr.brucetsao
Arduino部落格:
範例原始碼網址:https://github.com/brucetsao/Arduino_FayaNUGGET
臉書社群(Arduino.Taiwan):https://www.facebook.com/groups/Arduino.Taiwan/Arduino
活動官網:
Youtube:https://www.youtube.com/channel/UCcYG2yY_u0m1aotcA4hrRgQ
ADVERTISEMENT