物聯網開發入門:ESP8266 Arduino 教程
已發表: 2022-03-11本 ESP8266 Arduino 教程的目的是熟悉在芯片上使用 Arduino 進行嵌入式編程,該芯片因其在物聯網領域的可訪問性和易用性而在創客社區(和一般開發人員)中變得非常流行。 本教程還使用非官方的“黑客”讓 Alexa 在家中進行競標(該技術不適用於生產,僅用於在家演示)。 在家裡試試這個,但不是在工作中。
這項技術的美妙之處在於,我們可以在自己的家中使用它來讓 Alexa 幾乎可以自動化任何依靠電力運行的東西。 作為額外的獎勵,我們可以深入了解使用 Arduino 進行嵌入式編程,這一技能在當今的主流程序員中可能並不常見。 最後,我們開始使用流行的 ESP8266 芯片,這是 DIY 愛好者的最愛; 這是一個了不起的小芯片,能夠運行各種東西,內置 Wifi 芯片,我們將在這個項目中需要它。 這將使 Alexa 設備和芯片能夠直接相互通信。
只是 Alexa 編程的一些背景知識:Alexa“技能”編程模型的工作原理如下:
- 你和你的 Alexa 說話。
- Alexa 將您的語音一路路由回亞馬遜的雲。
- 語音命令被路由到 Alexa“技能”(在亞馬遜雲中運行的程序)。
Alexa“技能”接管了命令的處理; 通常,它會導致將響應發送回 Alexa 設備,使其向用戶說些什麼作為響應。 在 Alexa IoT 的情況下,命令被路由到亞馬遜雲上的“設備影子”,最終導致響應被發送到您家中的其他設備。 我們正在通過我們的 hack 繞過所有這些。 我們想讓 Alexa 設備直接與我們家中的 ESP8266 芯片對話,而無需向雲端發送任何內容並返回。 我們希望 Alexa 僅通過我們的家庭 wifi 網絡直接向我們的 ESP8266 發送請求。
我們的 hack 並不是什麼秘密。 我們將讓我們的 ESP8266 “模擬” Wemo Belkin,這是一種具有亞馬遜特殊許可證的設備,允許它直接與 Alexa 設備通信,繞過上述所有亞馬遜云通信。
偽裝成 WeMo,我們的 ESP8266 享有能夠直接從 Alexa 接收命令的特權。
ESP8266 Arduino 教程的基本計劃
- 在 ESP8266 上監聽 Alexa 設備在本地 wifi 網絡上為兼容設備發送探測,並通過說“我是 Wemo”來響應這些探測。
- 一旦被 Alexa 設備信任,請收聽來自所述設備的進一步命令。 通過紅外發射器發送紅外代碼來處理它們,打開/關閉我們的電視。
硬件要求
要完成本教程,您將需要自己獲得一些物品,所有這些物品都很容易獲得。
- 任何 Alexa 設備。 我使用 Alexa Dot 開發了本教程。 本教程是否適用於 Echo 模擬器? 它可能! (但我沒有測試過)。 如果您喜歡冒險(或節儉),請嘗試一下。 Alexa 設備需要零用錢,但使用 Echosim 是免費的。
- ESP8266 芯片。 在撰寫本文時,它們的成本僅為幾美元。 您可以在 Ebay 或任何庫存充足的在線五金店買到它們。
- IR(紅外)二極管。 你需要把它連接到你的 ESP8266 芯片上,你必須自己做。 對於這個項目,我們只需要發送能力; 我們不關心 IR 接收。 確保將二極管連接到 GND 並輸出 0 以使本教程正常工作。 (如果您以任何其他方式執行此操作,那很好,但您還必須負責相應地修改教程代碼。此鏈接可能會對您有所幫助。請注意,由於 ESP8266 上使用的編號方案,引腳 0可能被標記為“D3”。
- 一個串行適配器,一側是 USB(插入您的開發計算機),另一側適合 ESP8266 芯片。
- 您知道用戶名和密碼的本地 wifi 網絡。
Arduino軟件工具
- Arduino IDE。 有適用於所有主要操作系統的版本,包括 Windows。 本教程是在 Ubuntu 版本上開發的,但我也在 Windows 上安裝和使用了 Arduino,沒有問題。
- 用於 Arduino 的 ESP8266 開發庫。
- 司機。 幸運的是,適配器的驅動程序很可能是即插即用的,因此不需要額外的驅動程序。
設置一切
- 安裝 Arduino IDE。
- 使用 Boards Manager 安裝 ESP8266 庫。
使用 Boards Manager 安裝 ESP8266 庫:
- 在 Arduino IDE 中,打開File -> Preferences 。
- 在“Additional Boards Manager URL”中輸入此 URL:http://arduino.esp8266.com/stable/package_esp8266com_index.json
- 點擊確定
轉到 Boards Manager ( Tools -> Board: [current board] -> Boards Manager )。
- 在“過濾器”文本框中,輸入“ESP8266”。
- 既然您添加了額外的板管理器,您應該會獲得“esp8266”的條目。 選擇它,然後單擊“安裝”。
- 稍等片刻——下載所有內容需要一些時間。
- 重新啟動您的 Arduino IDE。
- 打開工具 -> 板:這次,向下滾動到“通用 ESP8266 模塊”並選擇它。
添加第三方庫
Arduino 提供了許多不同的方法來將外部庫添加到您的項目中,或者他們稱之為“Sketch”。 為了讓事情盡可能簡單,對於本教程,我們將採取最快的解釋,即簡單地複製文件夾。 我們將需要添加兩個外部庫才能使教程正常工作:IRemoteESP8266 和 https://github.com/me-no-dev/ESPAsyncTCP。
- 在 GitHub 的教程代碼中,找到“libraries”目錄。
- 在 Arduino 的根安裝目錄(例如,C:\Program Files\Arduino)中,找到“libraries”子目錄。
- 將教程的“libraries”目錄中的 IRemoteESP8266 目錄複製到 Arduino 的“libraries”目錄中。
- 將教程的“libraries”目錄中的 ESPAsyncTCP 目錄複製到 Arduino 的“libraries”目錄中。
- 重新啟動 Arduino IDE。
現在,用於 IR 傳輸和異步 TCP 的庫已包含在項目中。
設置
下圖顯示了典型設置,適用於我和我的硬件,但可能因每個用戶而異。 您可以嘗試以下設置,但您可能需要根據您的特定芯片和適配器進行調整。 例如,我的是 nodemcu,所以我不得不將重置方法從“ck”(默認)更改為“nodemcu”。 此外,將“調試端口”設置為“串行”,以便您可以使用串行調試器。 我的是一個非常典型的設置,所以你可以使用我的設置作為基礎; 我只是說,如果您必須與他們搞混才能使編譯和閃存過程正常工作,請不要感到驚訝。
使用 ESP8266 Hello World 驗證您的設置
Arduino 項目以 .ino 文件開始。 .ino 文件定義了兩個入口點:設置和循環。 對於我們的“hello world”,我們將在 ESP8266 上點亮一點燈,以驗證我們的代碼是否有效。
//SET TO MATCH YOUR HARDWARE #define SERIAL_BAUD_RATE 9600 #define LED_PIN 2 /*---------------------------------------*/ //Runs once, when device is powered on or code has just been flashed void setup() { //if set wrong, your serial debugger will not be readable Serial.begin(SERIAL_BAUD_RATE); pinMode(LED_PIN, OUTPUT); } /*---------------------------------------*/ //Runs constantly void loop() { digitalWrite(LED_PIN, LOW); delay(1000); digitalWrite(LED_PIN, HIGH); delay(1000); }
編譯並刷新代碼
如果到目前為止您的設置是正確的,編譯和刷寫是簡單的步驟。 要在不閃爍的情況下進行編譯,只需從 Arduino 菜單轉到Sketch -> Verify/Compile 。
要將代碼閃存到芯片並進行編譯,請從 Arduino 菜單中選擇Sketch -> Upload 。
如果閃存成功,您將看到進度顯示從 0% 變為 100%,在此期間,您芯片上的 LED 很可能會實際閃爍或閃爍。
要測試串行調試是否正常工作:
- 首先確保調試端口設置為串行(工具 -> 調試端口)。
- 在您的代碼完成閃存到芯片後,選擇Tools -> Serial Monitor 。
成功啟動後串行調試器的輸出:
太好了,這樣行得通; 接下來,我們要驗證我們的 IR 輸出。 讓我們通過我們的紅外發射器發送一個信號,並驗證信號是否通過。
我們將利用現有的 Arduino IR 庫來幫助我們。 Arduino 的一大優點是可以輕鬆地插入和取出庫和模塊。 對於 C++ 框架來說非常令人耳目一新!
只需按照 Git repo 的 README 文件中的說明在 Arduino 中安裝即可。
此代碼只是反复閃爍紅外發射器。 紅外對人眼是不可見的,但有一個測試它的專業提示; 運行此代碼,驗證(通過調試器)它是否在您的芯片上運行,然後打開您的移動設備的相機。 通過你的相機直接看紅外二極管燈泡。 如果它工作正常,您應該會看到燈泡明顯地打開和關閉。 您也可以使用任何可用的遙控器(例如,標準電視遙控器)嘗試此操作。 以下代碼應使 IR 燈泡開始每 0.5 秒閃爍一次。 實際上它會發送 LG 開/關命令,因此如果它在附近,它實際上可能會關閉和打開您的 LG 電視。
#include <IRremoteESP8266.h> // IR Library IRsend* irSend; // infrared sender //SET TO MATCH YOUR HARDWARE #define SERIAL_BAUD_RATE 9600 //PIN 0 is D3 ON THE CHIP #define IR_PIN 0 /*---------------------------------------*/ //Runs once, when device is powered on or code has just been flashed void setup() { //if set wrong, your serial debugger will not be readable Serial.begin(SERIAL_BAUD_RATE); //initialize the IR irSend = new IRsend(IR_PIN, true); irSend->begin(); } /*---------------------------------------*/ //Runs constantly void loop() { irSend->sendNEC(0x20DF10EF, 32, 3); delay(1000); }
開始 ESP8266 教程
如果到目前為止一切正常,我認為我們可以對基本設備和設置正常工作感到滿意,並且我們已準備好開始本教程的內容。
連接到無線網絡
首先,我們需要連接到本地 wifi。 下面的代碼將嘗試連接到 Wifi,並報告連接成功(通過串行調試器)。 在代碼示例中,不要忘記將 myWifiSsid 的值替換為您的 wifi 網絡的用戶名,並將 myWifiPassword 的值替換為正確的密碼。
#include "debug.h" // Serial debugger printing #include "WifiConnection.h" // Wifi connection // this file is part of my tutorial code #include <IRremoteESP8266.h> // IR library WifiConnection* wifi; // wifi connection IRsend* irSend; // infrared sender //SET YOUR WIFI CREDS const char* myWifiSs; const char* myWifiPassword = "*******"; //SET TO MATCH YOUR HARDWARE #define SERIAL_BAUD_RATE 9600 //PIN 0 is D3 ON THE CHIP #define IR_PIN 0 /*---------------------------------------*/ //Runs once, when device is powered on or code has just been flashed void setup() { //if set wrong, your serial debugger will not be readable Serial.begin(SERIAL_BAUD_RATE); //initialize wifi connection wifi = new WifiConnection(myWifiSsid, myWifiPassword); wifi->begin(); //connect to wifi if (wifi->connect()) { debugPrint("Wifi Connected"); } } /*---------------------------------------*/ //Runs constantly void loop() { }
運行 WeMo 服務器
連接的? 好的。 現在我們進入項目的核心:WeMo 服務器。

我自己的 WeMo 模擬器包含在本教程的源文件中。 現在,您可以搜索 Google 並找到更簡單的 WeMo 模擬器。 您可以找到使用較少代碼編寫且易於理解的代碼。 無論如何,請隨意檢查、實驗、編寫您自己的等等。這就是使本教程成為您自己的所有部分。
我背後的原因是它使用 ESPAsyncTCP。 為什麼這樣好? 好吧,在 ESP8266 開始變得不可靠之前,您只能使用這種方法在 ESP8266 上運行這麼多服務器(或設備),因為 Alexa 將開始丟失設備(未找到它們),命令將被丟棄,並且性能變慢。 我發現這個數字是通過使用 ESPAsyncTCP 庫最大化的。
沒有它,我發現在大約 10 到 12 台設備上運行不可靠; 有了它,我發現這個數字上升到 16 左右。如果您想擴展本教程並探索芯片可以做什麼的限制,我建議使用我的版本。 如果你想看一個更簡單的版本只是為了你自己的理解,隨意在谷歌上搜索“wemo emulator Arduino”; 你應該找到很多例子。
現在,我們必須安裝 ESPAsyncTCP 庫。 就像我們安裝 IR 庫一樣安裝它; 轉到 Git 頁面並按照說明進行操作。
這個庫也包含在我的 esp8266 arduino 示例代碼中。 這只是打開 wifi 連接、偵聽 Alexa 發現請求並通過返回“I am Wemo”響應來處理它的代碼。
#include "debug.h" // Serial debugger printing #include "WifiConnection.h" // Wifi connection #include "Wemulator.h" // Our Wemo emulator #include <IRremoteESP8266.h> // IR library WifiConnection* wifi; // wifi connection Wemulator* wemulator; // wemo emulator IRsend* irSend; // infrared sender //SET YOUR WIFI CREDS const char* myWifiSs; const char* myWifiPassword = "*******"; //SET TO MATCH YOUR HARDWARE #define SERIAL_BAUD_RATE 9600 //PIN 0 is D3 ON THE CHIP #define IR_PIN 0 /*---------------------------------------*/ //Runs once, when device is powered on or code has just been flashed void setup() { //if set wrong, your serial debugger will not be readable Serial.begin(SERIAL_BAUD_RATE); //initialize wifi connection wifi = new WifiConnection(myWifiSsid, myWifiPassword); wifi->begin(); //initialize the IR irSend = new IRsend(IR_PIN, false); irSend->begin(); //initialize wemo emulator wemulator = new Wemulator(); //connect to wifi if (wifi->connect()) { wemulator->begin(); //start the wemo emulator (it runs as a series of webservers) wemulator->addDevice("tv", new WemoCallbackHandler(&commandReceived)); wemulator->addDevice("television", new WemoCallbackHandler(&commandReceived)); wemulator->addDevice("my tv", new WemoCallbackHandler(&commandReceived)); wemulator->addDevice("my television", new WemoCallbackHandler(&commandReceived)); } } /*---------------------------------------*/ //Runs constantly void loop() { //let the wemulator listen for voice commands if (wifi->isConnected) { wemulator->listen(); } }
預測試
通過使用 Alexa 運行它來測試我們目前所擁有的(wifi 和模擬器)。 本教程假設您的 Alexa 設備已設置並安裝在您的家中。
測試發現:
對 Alexa 說: “Alexa,發現設備。”
這將導致 Alexa 在您的本地 wifi 網絡上廣播 UDP 請求,掃描 Wemos 和其他兼容設備。 這個請求應該在對wemulator->listen();
在循環()函數中。 這又將其路由到 Wemulator 的handleUDPPacket(*)
方法。 在nextUDPResponse()
方法中發出響應。 請注意該響應的內容:
const char UDP_TEMPLATE[] PROGMEM = "HTTP/1.1 200 OK\r\n" "CACHE-CONTROL: max-age=86400\r\n" "DATE: Sun, 20 Nov 2016 00:00:00 GMT\r\n" "EXT:\r\n" "LOCATION: http://%s:%d/setup.xml\r\n" "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" "01-NLS: %s\r\n" "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n" "ST: urn:Belkin:device:**\r\n" "USN: uuid:Socket-1_0-%s::urn:Belkin:device:**\r\n\r\n";
這是告訴 Alexa “我是 Wemo (Belkin),我有什麼可以幫助你的代碼”的代碼。 一旦 Alexa 收到此響應,它就會知道並記住未來的智能家居命令可能會路由到此設備。
此時串行調試器的輸出應如下圖所示。 完成發現後,Alexa 會口頭告訴您它已在您的網絡上“發現 [N] 台設備”。
在setup()
函數中,請注意以下代碼段:
new WemoCallbackHandler(&commandReceived)
這是我們將從 Alexa 捕獲命令的回調。 它的主體在 WemoCallbackHandler.h (WemoCallbackHandler::handleCallback) 中定義。 一旦我們從 Alexa 捕獲命令,我們就可以用它做我們喜歡的事情。 在之前的幾行中,我們已經設置了可以使用的可能命令,這些代碼行:
wemulator->addDevice("tv"); wemulator->addDevice("television"); wemulator->addDevice("my tv"); wemulator->addDevice("my television");
所以這些是我們在芯片上運行的 4 個獨立的“服務器”或偵聽器。 這設置了向 Alexa 說出以下任何命令的能力:
Alexa,打開電視 Alexa,關閉電視 Alexa,打開電視 Alexa,關閉電視 Alexa,打開我的電視 Alexa,關閉我的電視 Alexa,打開我的電視 Alexa,關閉我的電視
這就是我們將如何測試它。 我們希望說這些命令中的任何一個都應該喚醒我們的代碼並進入回調,在那裡我們可以用它做我們喜歡的事情。
添加紅外命令
現在我們收到了命令,是時候通過……打開/關閉我們的電視來處理它了。 所以這將是一切——wifi、wemo 模擬器和 IR——都放在一起。 我的電視是 LG,所以我查找了打開/關閉的適當順序,並通過我們的 IR 庫的 sendNEC 函數發送(LG 使用 NEC 協議)。 IR編碼/解碼本身是一個獨立的主題,其中消息是在信號調製中編碼的; 它是非常精確的時間、標記和空間的規範。 每個製造商都傾向於使用自己專有的命令協議,並使用不同的時間; 這很有趣,您可以通過查看該 IR 庫的源代碼、谷歌搜索等來更深入地挖掘。但為了方便起見,我們的 IR 庫為我們處理的所有細節。
你的電視不是LG的? 只需谷歌正確的代碼。 這是索尼電視的命令(警告:未經測試):
irSend.sendSony(0xa90, 12);
如果你想自己動手,你可以設置一個紅外接收器,將你的遙控器(或任何紅外發射器)對準它,然後解碼它發送的代碼; 不過,這是一個不同的教程。
端到端測試
- 將您的 Alexa 放在它可以聽到您的任何地方。
- 將帶有紅外二極管的 ESP8266 放置在電視的遙控範圍內。
- 說“Alexa,發現設備”。 等待它報告成功(它應該至少發現了一個設備)。
- 說“Alexa,打開我的電視”或“Alexa,關閉我的電視”。
Alexa 應該理解您的命令(作為智能家居命令,而不是針對特定技能),搜索本地設備來處理它,並將命令發送到設備(您的 ESP8266)。 您的設備應該會收到它並將遙控命令發送到電視。 您可以通過手機攝像頭查看您的二極管,以確保它正在發光。
由於關閉電視的 IR 代碼與打開電視的代碼相同,因此無論您發出“打開”還是“關閉”命令都沒有關係。 這是相同的代碼,它會切換狀態。 如果電視關閉,它應該打開,如果打開,它應該關閉。
故障排除
你連接到Wifi了嗎?
您是否在正確的變量值中輸入了正確的用戶名/密碼?
//SET YOUR WIFI CREDS const char* myWifiSs; const char* myWifiPassword = "*******";
連接到 Wifi 時,您是否收到失敗消息或通過串行調試端口出現任何錯誤?
您的 Wifi 是否打開,您可以通過其他任何普通方式連接到它嗎?
Alexa 是否發現了您的設備?
當您說“Alexa,發現設備”時,Alexa 會發出發現設備的請求。
您的 Alexa 必須正確配置和設置,並連接到與 ESP8266 相同的 Wifi 網絡。
查看 Fauxmo.h。 參見函數 Fauxmo::handle()。 這是 ESP8266 聽到呼叫後將運行的第一個代碼。 放入調試消息以查看之後是否有任何代碼
if (len > 0) {
在跑。 如果不是,則沒有接收到命令。 如果是,則似乎正在接收命令,但未正確處理。 按照那裡的代碼找出問題所在。
您的網絡上是否還有許多其他可發現的設備? 太多會導致發現運行更慢,甚至有時會失敗。
您的設備是否收到命令?
當您發出命令“Alexa,打開我的電視”時,執行應該進入您的WemoCallbackHandler::handleCallback handler
(在 WemoCallbackHandler.h 文件中)。 如果您還沒有這樣做,請嘗試在其中輸出一些調試消息,以確保在您發出命令時它會觸發。 此外,在發出命令之前,請嘗試通過說“Alexa,發現設備”來確保 Alexa 了解您的設備。 此步驟假定設備發現已成功。
IR 二極管是否發光?
如前所述,當您認為您的設備應該發光時,請將手機的攝像頭對準它,然後通過攝像頭查看二極管。 雖然在現實生活中你什麼都看不到,但通過相機它應該看起來像一個正常的燈光點亮和閃爍。 如果你看到這個,那麼它正在散發……什麼東西。
IR 信號是否反轉?
您的 IR 二極管的接線方式可能使信號基本反轉。 請耐心等待我的解釋,因為我不是電子或接線人員,但錯誤接線二極管的結果將是紅外燈默認打開,但當 IRSend 庫打算打開時關閉它在。 如果是這種情況,則默認情況下,在setup()
代碼運行之後,但在其他任何事情發生之前,您的 IR 燈應該打開(通過相機可見)。 如果您要註釋掉loop()
內的所有代碼,您應該會看到它一直保持打開狀態。
要更清楚地了解如何解決此問題,請進入教程代碼的library/IRemoteESP8266/src文件夾。 查看構造函數:
IRsend::IRsend(uint16_t IRsendPin, bool inverted) : IRpin(IRsendPin), periodOffset(PERIOD_OFFSET) { if (inverted) { outputOn = LOW; outputOff = HIGH; } else { outputOn = HIGH; outputOff = LOW; } }
“顛倒”的論點和處理它的邏輯就是我們所說的。 如果你的接線是倒置的,最簡單的解決方案是在代碼中做一個小的改動以允許這樣做(而不是重新接線……但如果你願意的話當然可以這樣做)。 只需在 AlexaTvRemote.ino 中更改此行:
//initialize the IR irSend = new IRsend(IR_PIN, false);
到
//initialize the IR irSend = new IRsend(IR_PIN, true);
你有正確的遙控代碼和命令嗎?
如果其他一切似乎都正常,但電視只是不服從,則很可能是 IR 代碼有問題。 在該 IR 庫接口上嘗試不同的函數調用(例如sendLG
、 sendPanasonic
、 sendSharp
等),或者確保您使用的函數與您的硬件相匹配。 該庫不支持您的電視硬件不太可能,但我想這在技術上是可能的。
確保您發送的代碼適合您的硬件。 您可能需要在谷歌上進行一些挖掘才能找到合適的。 如果一切都失敗了,當您按下電源按鈕時,始終可以選擇檢測從您的工作遙控器發出的代碼 - 但這是一個不同的教程並且需要不同的硬件。
包起來
希望一切都為你解決。 如果是這樣(甚至可能不是),這是一次在多個主題上切齒的好方法:
- 亞歷克斯
- 嵌入式編程
- ESP8266 芯片
- Arduino IDE
當然,你也有一點點方便,可以通過語音命令打開/關閉電視。
為什麼黑客?
為什麼這是一個 hack,而不是 Alexa 基本 API 的一部分? 在學習瞭如何開發我的第一個 Alexa 技能之後,我真正想知道的是“我怎樣才能直接從 Alexa 向網絡上的另一台設備發送命令?” 遺憾的是,亞馬遜沒有通過“技能”或“智能家居”範式(其中所有內容都必鬚髮送到 AWS在做任何事情之前),但他們只是沒有。
嘗試更進一步
嘗試使用一套遠程控制命令來更全面地控制您的電視,例如更改頻道和控制音量。 通過查看您可以在一個 ESP8266 上聽多少個不同的命令來測試芯片的極限(提示:這個數字幾乎不會突破兩位數,沒有一些非常聰明的編程)。 如果您擅長硬件,請嘗試不通過 IR 控制其他設備,將它們直接連接到 ESP8266 芯片; 比如燈光之類的。 重塑 wemo!
- 我如何製作一個全功能的 Arduino 氣象站
- 使用 ESP32 音頻採樣