設備與材料
個人電腦 × 1
手機× 1
ESP12F × 1
麵包板 × 1
紅外線發射器 模組 × 1
電晶體 × 1
電阻 22Ω× 1
電阻 100Ω× 1
連接線 若干
實體接線圖
PWM 相關函式
PWM可用接腳:ESP-12F 可以PWM輸出的接腳 D2(GPIO 4)、D5(GPIO 14)、D6(GPIO 12)、 D8(GPIO 15)
analogWriteFreq(new_frequency):改變 PWM 頻率,频率範圍100Hz-40KHz
例:analogWriteFreq(38000); //設定 PWM 頻率 38kHz 從示波器測量約38.4kHz
analogWrite(pin,val): pin接腳PWM輸出,工作週期 val/255
例:analogWrite(D6,127); //D6接腳 PWM輸出 工作週期 127/255
手機設定
這個專題是手機用 MQTT協定來控制 ESP-12F,必需有手機端的程式, 可以先參考 ESP12F 網路智慧開關(MQTT) 中的手機設定,下載安裝程式並開啟,左上功能選單可以進入MQTT connections 連線設定。按 + 可以新增控制面板,輸入 Name(名稱) 及 Description(描述) 按左上方 ✓ 就可以新增我們的控制面板。
點進去,按 + 就可以新增控制元件了(如下左圖),選擇 “Button” 形式的控制元件,輸入 Name 並開啟 MQTT enable。
選擇要連線到之前設定的那個伺服器,在 “Topic for publish” 輸入你在 ESP12F 程式內訂閱的主題(a1b2c3d4e5f6/IRControl/set),如果程式有變動,這裡也要變動。按 “Button” 在 “Payload” 欄位輸入 P,表示這個按這個按鈕,程式會發佈 “P” 這個內容到 a1b2c3d4e5f6/IRControl/set 這個主題內。按”Icon“可以更改Icon圖樣,按左上方 ✓ 就可以新增我們的控制元件。你自己要再新增 “鎖定”、”黑螢幕”等按鈕。記得 “Button” 的 “Payload” 欄位分別是 F 與 M。(按右上雙框ICON 可以調整位置)
設定好,就可以用手機遠端遙控投影機了。
範例程式
/*
* 手機雲端紅外線控制
* 開發工具 Arduino IDE 必需自行加入ESP12F 開發板
* 開發板 ESP12F(ESP8266)
* 使用通訊協定 MQTT ,MQTT broker 使用 mqtt.eclipseprojects.io
* 程式會訂閱 subTopic 設定的主題,只要有對此主題發佈內容P 就發射 電源的紅外線控制碼
* F 就發射 螢幕鎖定的紅外線控制碼,M 就發射黑螢幕的紅外線控制碼
* 程式每1秒會發佈 1 到 pubTopic 設定的主題,可以用此判斷設備是不是在線上
* 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);
#define IR_send_pin D6
//紅外線發射 NEC 格式參數
#define NEC_START_MARK 9000
#define NEC_START_SPACE 4500
#define NEC_ONE_MARK 550
#define NEC_ONE_SPACE 1550
#define NEC_ZERO_MARK 550
#define NEC_ZERO_SPACE 600
#define NEC_END_MARK 600
#define NEC_END_SPACE 30000
//WIFI SSID 跟密碼
#define APSSID "你的wifi SSID"
#define APPW "wifi 密碼"
// MQTT mqtt.eclipseprojects.io 伺服器 不需要使用者名稱 密碼
// 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/IRControl/state";
const char* subTopic = "a1b2c3d4e5f6/IRControl/set";
byte state = 0;
char msg[10] ;
long currentTime, lastTime;
unsigned char POWER[] = {0x83, 0x55, 0x90, 0x6F };
unsigned char FREEZE[] = {0x83, 0x55, 0x92, 0x6D };
unsigned char MUTE[] = {0x83, 0x55, 0x93, 0x6C };
void setup()
{
pinMode(IR_send_pin,OUTPUT); //設定 PWM接腳為輸出
analogWriteFreq(38000); //設定PWM頻率 38kHz
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();
//1秒發一次訊息
if(currentTime - lastTime > 1000)
{
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] == 'P'){
//發射電源控制碼
state=1;
NECsend(POWER, 4);
dtostrf(state, 1, 0, msg);
client.publish(pubTopic,msg);
}else if (len == 1 && payload[0] == 'F'){
//發射螢幕鎖定控制碼
state=1;
NECsend(FREEZE, 4);
dtostrf(state, 1, 0, msg);
client.publish(pubTopic,msg);
}else if (len == 1 && payload[0] == 'M'){
//發射黑螢幕控制碼
state=1;
NECsend(MUTE, 4);
dtostrf(state, 1, 0, msg);
client.publish(pubTopic,msg);
}
}
Serial.println();
}
//連接無線 wifi 的處理函式
void setupWiFi()
{
delay(100);
//連接無線 wifi 可以設定很多組
wifiMulti.addAP(APSSID, APPW);
wifiMulti.addAP("第2組wifi SSID","密碼");
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);
}
}
}
//NEC 格式的發射函式
void NECsend(unsigned char buf[], int len) {
byte data;
//啟始位元
mark(NEC_START_MARK);
space(NEC_START_SPACE);
//資料位元
for (byte i = 0; i < len; i++) {
data = buf[i];
//並列轉串列
for (byte j = 0; j < 8; j++) {
if ((1 << j & data)) {
mark(NEC_ONE_MARK);
space(NEC_ONE_SPACE);
} else {
mark(NEC_ZERO_MARK);
space(NEC_ZERO_SPACE);
}
}
}
//結束位元
mark(NEC_END_MARK);
space(NEC_END_SPACE);
}
//紅外線接腳輸出38kHz方波 time us
void mark(int time) {
unsigned long beginTime = micros();
unsigned long endTime = (unsigned long)time;
unsigned long nowTime = micros();
analogWrite(IR_send_pin,127);
while (nowTime - beginTime < endTime) {
nowTime = micros();
}
analogWrite(IR_send_pin,0);
}
//紅外線接腳低電位 time us
void space(int time) {
unsigned long beginTime = micros();
unsigned long endTime = (unsigned long)time;
unsigned long nowTime = micros();
while (nowTime - beginTime < endTime) {
nowTime = micros();
}
}
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 電子鼓