當我們要做一個遠端控制的專題時,最好的方式是讓該裝置連上網路,如果能跨網路且不侷限在區域網路內才能控制時,就需要有一個雲端伺服器。雲端伺服器可以自己架設,也可以找尋免費提供的伺服器。免費提供的伺服器最大的優點就是方便及免費,但缺點就是不穩定且安全性較差。
我們選擇一個輕量的通訊協定(MQTT) 來做控制,test.mosquitto.org、mqtt.eclipseprojects.io 提供免費的 MQTT 雲端伺服器(broker),不需要申請就能直接使用,因此不需要使用者帳號與密碼,也因為不需要使用者帳號與密碼,安全性堪慮,如果是重要的控制,最好還是使用需要申請的 MQTT broker比較安全,如果只是實習用,就上述2個伺服器選擇1個來用就行。
MQTT broker(經紀人) 接受用戶端(Client)發佈(publisher)主題(Topic)與內容,其它有訂閱(subscriber)此主題的用戶端,都能收到MQTT broker(經紀人)轉送來的內容。用戶端之間有 broker 伺服器當作中繼站,所以用戶端之間並不需要知道彼此的IP位址,可以跨網域控制。
設備與材料
個人電腦 × 1
ESP12F × 1
麵包板 × 1
智慧手機 × 1
PB按鈕 × 1
繼電器模組 × 1
連接線 若干
實體接線圖
手機設定
因為用手機控制我們的專題,手機部份必需有支援 MQTT 的程式才行,手機這部份的程式已有現成的程式,我的手機是 Android ,因此打開 Play 商店,輸入mqtt 篩選(如下左圖),目前覺得 Lapetov 推出的 MQTT dashboard 符合我的使用要求,只要下載來設定一下就能控制。安裝後(如下中圖)執行會出現如下右圖,他有2個範例控制面板提供你參考,按 + 可以新增控制面板,輸入 Name(名稱) 及 Description(描述) 按左上方 ✓ 就可以新增我們的控制面板,左上功能選單可以進入MQTT connections 連線設定。
按 MQTT connections 進入 連線設定,他有3個連線範例,都是連到 test.mosquitto.org ,如果你用其它MQTT 伺服器,可以新增連線,或是直接修改都可以。
我們新增一個 “BLOCK IOT” 控制面板,點進去如下左圖畫面,按 + 就可以新增控制元件了(如下中圖),選擇 “Toggle” 形式的控制元件,輸入 Name 並開啟 MQTT enable。
選擇要連線到之前設定的那個伺服器,在 “Topic for publish” 輸入你在 ESP12F 程式內訂閱的主題,Retain 是保留選項,不需要勾選,”Qos for publish” 傳送品質用內定的 0 就可以。 “Toggle” 形式的控制元件會有2種狀態 State(ON)、State(OFF),先設定 State(ON) ,Payload 是 State(ON)時發佈主題的內容;Text 是 State(ON)時顯示在手機的文字,也可以選擇不顯示;ICON 是 State(ON)時顯示的圖示,圖示可以改,顏色也可以改,大小也可以變換。
State(OFF)設定方式與State(ON)相同,只是區別ON、OFF ,顏色不同, State(OFF)時發佈主題的內容不同,Uptime 是發佈的時間,可以選擇要不要顯示,控制元件的 Name 可以選擇要不要顯示,如果都設定好按左上方 ✓ 就可以新增控制元件了。
控制元件可以變更大小與位置,按左上 + 圖示旁的 方框圖示,可以進入大小與位置變更。如果想要變更控制元件的設定,可以長按住控制元件,會出現選單,可以編輯、複製、刪除。
我們進去重新變 ICON 大小,也選擇不顯示控制元件邊框,最後完成如下右圖的控制元件。
你按一下控制元件,會發佈主題為 a1b2c3d4e5f6/IOTPowerPlug/set 內容為 0 到 test.mosquitto.org 伺服器,只要有在 test.mosquitto.org 伺服器 訂閱 主題為 a1b2c3d4e5f6/IOTPowerPlug/set 的設備,都會收到 0 這個內容;
再按一下控制元件,會發佈主題為 a1b2c3d4e5f6/IOTPowerPlug/set 內容為 1 到 test.mosquitto.org 伺服器,只要有在 test.mosquitto.org 伺服器 訂閱 主題為 a1b2c3d4e5f6/IOTPowerPlug/set 的設備,都會收到 1 這個內容。
開發環境
使用 Arduino IDE 安裝 ESP8266開發板,如果不知道如何安裝ESP8266開發板,可以參考 “準備你的 ESP12E/F 開發工具” ,安裝開發板之後,記得開發板選擇 “NodeMCU 1.0(ESP-12E Module)” ,之後安裝MQTT 程式庫,如下圖步骤。
ESP12F 範例程式
/*
* 網路智慧開關
* 開發工具 Arduino IDE 必需自行加入ESP12F 開發板
* 開發板 ESP12F(ESP8266)
* 此程式為範例程式,並未加入對繼電器的控制,僅用板上LED來表示開關 ON OFF
* 使用通訊協定 MQTT ,MQTT broker 使用 test.mosquitto.org
* 程式會訂閱 subTopic 設定的主題,只要有對此主題發佈內容1 開關就 ON 內容0 開關就 OFF
* 狀態改變,會發佈最新狀態到 pubTopic 設定的主題,內容為目前開關狀態(ON->1 OFF->0)
* 程式每60秒會發佈 到 pubTopic 設定的主題,內容為目前開關狀態(ON->1 OFF->0)
* https://www.block.tw/blog
*/
// 引用 Wifi AP 程式庫(連上wifi無線AP用)
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
// 引用 Wifi 程式庫(連上網際網路用)
#include <WiFiClient.h>
//引用 MQTT 程式庫 需要自行安裝程式庫 https://github.com/knolleary/pubsubclient
#include <PubSubClient.h>
//宣告 wifi AP網路 連線物件
ESP8266WiFiMulti wifiMulti;
//宣告 wifi 網路連線物件
WiFiClient espClient;
//宣告 MQTT 連線物件
PubSubClient client(espClient);
//WIFI SSID 跟密碼
#define APSSID "2.4G wifi 的SSID"
#define APPW "2.4G wifi 的密碼"
// MQTT test.mosquitto.org 伺服器 不需要使用者名稱 密碼
// 所以每個人都能用,如果有人跟你有相同的主題(topic)就能控制你的設備
const char* brokerUser = ""; //使用者名稱
const char* brokerPass = ""; //使用者密碼
const char* broker = "test.mosquitto.org";
//const char* broker = "mqtt.eclipseprojects.io";
const char* pubTopic = "a1b2c3d4e5f6/IOTPowerPlug/state";
const char* subTopic = "a1b2c3d4e5f6/IOTPowerPlug/set";
byte state = 0;
char msg[10] ;
long currentTime, lastTime;
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
//內建板上 LED 滅
digitalWrite(LED_BUILTIN, HIGH);
Serial.begin(115200);
setupWiFi();
client.setServer(broker, 1883);
client.setCallback(callback);
}
void loop()
{
if (!client.connected())
{
//連接 MQTT 伺服器
MQTTconnect();
}
client.loop();
currentTime = millis();
//60秒發一次訊息
if(currentTime - lastTime > 60000)
{
Serial.print("Sending messages:\t");
dtostrf(state, 1, 0, msg); //byte 轉 char *
Serial.println(msg);
client.publish(pubTopic,msg); //發佈
lastTime = millis();
}
}
//訂閱的主題有人發佈訊息時的處理函式
void callback(char* topic, byte* payload, unsigned int len)
{
Serial.print("Received messages: ");
Serial.println(subTopic);
for (unsigned int i = 0; i < len; i++)
{
Serial.print((char) payload[i]);
if (len == 1 && payload[0] == '1'){
// 1
state=1;
digitalWrite(LED_BUILTIN, LOW);
dtostrf(state, 1, 0, msg);
client.publish(pubTopic,msg);
}else if (len == 1 && payload[0] == '0'){
// 0
state=0;
digitalWrite(LED_BUILTIN, HIGH);
dtostrf(state, 1, 0, msg);
client.publish(pubTopic,msg);
}
}
Serial.println();
}
//連接無線 wifi 的處理函式
void setupWiFi()
{
delay(100);
//連接無線 wifi
wifiMulti.addAP(APSSID, APPW);
Serial.println("Wifi Connecting ...");
//內建板上 LED 亮
digitalWrite(LED_BUILTIN, LOW);
while (wifiMulti.run() != WL_CONNECTED)
{
delay(250);
Serial.print('.');
}
//內建板上 LED 滅
digitalWrite(LED_BUILTIN, HIGH);
Serial.println('\n');
Serial.print("Connected to:\t");
Serial.println(WiFi.SSID());
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
}
void MQTTconnect()
{
while (!client.connected())
{
//連接 MQTT 伺服器,因為是免費無使用帳號跟密碼,所以底下隨便輸入的
if (client.connect("MQTT_CLIENT_ID", "brokerUser", "brokerPass")) {
Serial.print("\nConnected to ");
Serial.println(broker);
//訂閱主題
client.subscribe(subTopic);
} else {
Serial.println("Connecting");
delay(2500);
}
}
}
序列埠監控視窗畫面
功能要求
1.加上繼電器模組,板上 LED 只指示是否連上 Wifi
2.增加1按鈕,按一下狀態變 ON,再按一下狀態變 OFF
3.修改手機 MQTT 應用程式,將原來的 “Toggle” 形式的控制元件(只發送,沒訂閱),新增訂閱 subTopic 所指定的主題,讓手機控制開關狀態與遠端裝置狀態相同
4.設定手機 MQTT 應用程式,多一個 “Toggle” 形式的控制元件(只訂閱,不發送),用來顯示目前裝置 ON 或 OFF
Arduino 輸出實習(單燈閃爍)
Arduino 輸出實習(跑馬燈-愚公移山)
Arduino 輸出實習(跑馬燈-for迴圈)
Arduino 數位輸入實習
Arduino 數位輸入實習(INPUT_PULLUP)
Arduino 類比輸入實習
Arduino PWM 實習 (呼吸燈)
Arduino PWM 實習 (光感應調光燈)
Arduino 8×8 LED Matrix MAX7219 實習
Arduino 紅綠燈小綠人 實習
Arduino 計時器 實習
Arduino 音樂盒
Arduino 電子琴(鍵盤掃描)
Arduino DHT11 溫濕度感應器
Arduino OLED 顯示
Arduino 超音波測距模組 HC-SR04
Arduino 執行時間實習
Arduino 電容測試器
Arduino 紅外線接收實習
Arduino 紅外線發射實習 EPSON 投影機控制
ESP-12F 網路智慧開關(MQTT)
ESP-12F 雲端記錄型 K-Type 溫度計(MQTT ThingSpeak)
ESP-12F 手機雲端紅外線控制
ESP-12F 網路電台收音機
ESP-12F 電子鼓