別再用很難接線的 ESP-01 了!以正規 NodeMCU/D1 mini(ESP8266)替任何無 WiFi 的開發板打造物聯網應用──燒錄 AT firmware 並傳送 AT 指令

ESP-01(以及記憶體加大的 ESP-01S)出廠時會安裝安可信(Espressif)的 AT 韌體,這韌體讓外部裝置能以序列埠指令(或 AT 指令)來控制此模組的行為,如連上 WiFi、傳送資料等等。

Image for post
Image for post

但問題就在於,ESP-01 模組的接線和供電有點麻煩,想燒錄新韌體就更麻煩了。此外,若想在電腦上用終端機監看 ESP-01 的回應訊息,不僅得買個 USB 轉 TTL 模組,接線複雜度也會進一步增加。對初學者而言,光是對硬體除錯可能就把耐心磨光了。

Image for post
Image for post
外接 ESP-01 模組的方式(包含外部電源,但不含除錯用的 USB-TTL 模組)

相較之下,直接使用正規 ESP8266 開發板(如 NodeMCU 或 WeMos D1 mini)來做 IoT 專案不僅夠便宜,也有 Arduino C++ 或 MicroPython 語言可選。可是回過頭來,BBC micro:bit 這類板子還是很麻煩,因為它非得倚賴外部 WiFi 晶片不可 — — 若不是外接一個 ESP-01,就是去購買某些廠商推出的 ESP-01 擴充板。

筆者以前曾針對 BBC micro:bit 和 ESP-01 模組寫過一些 IoT 應用,近來發現越來越多人詢問,但對於對方遇到的軟硬體問題總是愛莫能助。ESP-01 用起來就是麻煩,軟硬體會出錯的地方多得是,若沒有實際監看其序列埠回應,大概也很難判斷問題究竟在哪。

有鑑於此,筆者在這系列文章提出一個新解法──使用全尺寸、已經內建有 USB 介面晶片的 ESP8266 開發板來燒錄 AT 韌體,並把它當成其他開發板的外部 WiFi 晶片。這麼做有以下好處:

  1. 現在 ESP8266 開發板容易取得且仍相對便宜;
  2. 接線和供電只要 1 至 2 條 USB 線和 3 條杜邦線;
  3. 如果 ESP8266 的 USB 線接在電腦上的話,還可順便監看 ESP8266 AT 韌體的回應。

只要安裝好 AT 韌體,這塊板子也能重複使用。當然由於 AT 指令內容相當多,這邊就只會講最簡單的基礎。

讓我們開始吧。

註:當然囉,本篇的方法只適用於 Windows 環境。

Image for post
Image for post
Photo by Sabri Tuzcu on Unsplash

購買 ESP8266 開發板

首先,你需要一塊 NodeMCU 或 D1 mini,或者其他 ESP8266 開發板。不管造型怎樣,功能都是一樣的。

最容易購買和使用的是 NodeMCU,這又分成 V2 和 V3 兩種:

Image for post
Image for post
比較大的是 V3,較小的是 V2。

V2 V3 的差異只在尺寸和 USB 晶片不同而已(前者使用方形的 CP2102,後者則是長方形的 CH340)。有些 V2 或 V3 在網路上的價格僅有台幣百元出頭,這不會比 ESP-01S 貴上多少,而且又已經焊有針腳,買來就立即可用。

至於 WeMos 的 D1 mini 以及 D1 mini Pro 是因尺寸小所以頗受歡迎的產品(其實你能買到的說不定還是仿製版,但功能沒有差異),缺點是你得自己焊接針腳:

Image for post
Image for post

或者你可買像這樣做成 Arduino Uno 造型的 WeMos D1/D1 R2(同樣的這也有仿製版存在):

Image for post
Image for post

本篇則不討論 ESP-32 開發板,這是 ESP-8266 的升級版,規格上有明顯差異,價格也貴得多。

安裝 USB 驅動程式

取決你的 ESP8266 使用哪種 USB 晶片,你得在 Windows 上安裝 CP2102 或 CH340 的驅動程式,這樣電腦才能跟板子溝通:

  1. CP2102https://cn.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
  2. CH340http://www.wch.cn/download/ch341ser_exe.html
Image for post
Image for post
Photo by Shelbey Miller on Unsplash

下載 AT 韌體及燒錄

你買來的開發板上可能已經裝有某個版本的 AT 韌體,但現在我們要把最新版的燒錄上去。這個辦法適用於已經燒錄過其他程式語言(如 C++ 或 MicroPython)的 ESP8266。筆者目前測試過 NodeMCU V2 和 WeMos D1 mini 都是可行的。

首先,下載下面這兩樣東西:

  1. 最新的 ESP8266_NONOS_SDK:https://github.com/espressif/ESP8266_NONOS_SDK/releases。本篇以 3.0.4 為例。解壓後丟到電腦內某處。
  2. 安可信的 Flash Download Tools:https://www.espressif.com/en/support/download/other-tools。本篇以 v3.8.5 為例。同樣解壓後丟到電腦內。

執行 Flash Download Tools 資料夾中的 flash_download_tool_3.8.5.exe,點選 Developer mode 然後選 ESP8266。這樣就會帶出下面的燒錄畫面。

設定燒錄選項與檔案

在燒錄畫面中,你得做如下的設定:

Image for post
Image for post

首先你要指定需寫入的檔案及位址:(所有檔案在 ESP8266_NONOS_SDK-3.0.4 底下)

  1. \bin\boot_v1.7.bin0x000000
  2. \bin\at\1024+1024\user1.2048.new.5.bin0x01000
  3. \bin\esp_init_data_default_v08.bin0x1FC000
  4. \bin\blank.bin0x7E000
  5. \bin\blank.bin0x1FB000
  6. \bin\blank.bin0x1FE000

此外是其餘設定:

  1. SPI SPEED -> 40MHz
  2. SPI MODE -> QIO
  3. FLASH SIZE -> 16Mbit(但 16Mbit-C1 似乎也可以)
  4. COM -> 板子所在的 COM port
  5. BAUD -> 115200(有時接上板子會跳到 1152000,記得改掉)

按下 START 就能啟動燒錄了。耐心等它跑完。

以上參數其實在 AT 指令集文件內也有寫。如果是 ESP-01,要改選 8Mbit 以及 512+512\user1.2048.new.5.bin。

Image for post
Image for post
Photo by Chinh Le Duc on Unsplash

測試 AT 韌體回應

燒錄完成後,我們可以用終端機軟體來測試 AT 韌體是否正常運作。

安裝 Tera Term(https://osdn.net/projects/ttssh2/releases/),並確保板子仍接在電腦上。執行 Tera Term 後選擇板子所在的 COM port(若選單沒出現,點「文件」→「建立新連線」):

Image for post
Image for post
這張圖中連的是 D1 mini,可見它使用 CH340 USB 晶片

點「確定」就能連線。按一下板子的 RST 或 RESET 鈕重開它,你可能會看到畫面中跑一些垃圾訊息出來,最後一行可能是 Ready:

Image for post
Image for post

點選單的「設定」→「終端機」,調整設定如下:

Image for post
Image for post
至少「發送」和「本地回顧」這兩個要調

接著到「設定」→「連接埠」,將位元速率(baud rate)調為 115200:

Image for post
Image for post

現在,在畫面中用鍵盤輸入 AT 然後按 Enter,你應該會看到下面的字出現:

AATTOK

看到這樣的結果就代表 AT 韌體正在運作,且能回應。

之所以看到 AT 的字有重複,是因為 AT 韌體會將我們輸入的東西重傳一次回來,屬於正常現象。關閉這個功能的指令如下:

ATE0

接著來試些東西。我們可以輸入

AT+GMR

來檢查韌體版本:

AT version:1.7.4.0(May 11 2020 19:13:04)
SDK version:3.0.4(9532ceb)
compile time:May 27 2020 10:12:22
Bin version(Wroom 02):1.7.4
OK

如何?很不錯吧。若是在 ESP-01 上,韌體版本會比這舊多了(可能源自 2013 或 2014 年)。

Image for post
Image for post
Photo by Markus Winkler on Unsplash

再來試另一個指令。首先輸入

AT+CWMODE=1

這會讓板子進入 WiFi station 模式。然後

AT+CWLAP

這會顯示出附近所有的 WiFi 熱點名稱、位址和強度等資訊:

+CWLAP:(3,"FLAG-N007-B",-67,"d8:b0:4c:f2:21:64",1,-24,0,3,3,7,0)
+CWLAP:(3,"FLAG-N007-60",-73,"d8:b0:4c:f2:22:50",1,-74,0,3,3,7,0)
+CWLAP:(0,"FLAG-N007-99",-56,"d8:b0:4c:f2:22:80",1,-14,0,0,0,7,0)
+CWLAP:(0,"FLAG-XXXX",-80,"be:dd:c2:82:43:8f",1,-7,0,0,0,3,0)
+CWLAP:(4,"MicroPython-4e73b8",-82,"52:02:91:4e:73:b8",1,-9,0,5,3,3,0)
+CWLAP:(4,"MicroPython-6c81c2",-86,"be:dd:c2:6c:81:c2",1,8,0,5,3,3,0)
+CWLAP:(4,"AAM-B",-85,"e4:6f:13:2f:73:74",1,-29,0,5,3,7,1)
+CWLAP:(4,"MicroPython-205064",-84,"2e:f4:32:20:50:64",5,-7,0,5,3,3,0)
+CWLAP:(3,"flaginfo",-79,"cc:5d:4e:45:07:10",1,-37,0,4,4,7,0)
+CWLAP:(3,"FLAG",-41,"e8:26:89:bb:2a:64",6,5,0,4,4,7,0)
+CWLAP:(4,"CHT_I040GW1",-68,"1c:49:7b:9b:61:50",7,-26,0,5,3,7,0)
+CWLAP:(0,"CSD_Employee",-91,"24:de:c6:86:1b:90",1,0,0,0,0,7,0)
+CWLAP:(0,"CSD_Guest",-91,"24:de:c6:86:1b:91",1,0,0,0,0,7,0)
+CWLAP:(3,"TN-ASUS-AP01",-93,"54:a0:50:e1:f7:84",9,-32,0,4,4,7,1)
+CWLAP:(3,"",-66,"00:0e:8e:b9:70:56",10,-39,0,4,4,3,0)
+CWLAP:(4,"oh4648",-76,"c8:5b:a0:3f:7b:57",11,-16,0,4,4,7,0)
+CWLAP:(0,"BUFFALO-E0E204-1",-73,"10:6f:3f:e0:e2:04",11,-32,0,0,0,7,1)
+CWLAP:(3,"FLAG-N007-test",-75,"d8:b0:4c:e0:74:ac",11,5,0,4,4,7,0)
+CWLAP:(0,"FlagPub",-73,"10:6f:3f:e0:e2:06",11,-32,0,0,0,7,0)
+CWLAP:(3,"DSL-7740C",-82,"ac:f1:df:01:1f:7f",11,1,0,4,4,7,0)
+CWLAP:(0,"Tainan-user",-83,"1c:3a:60:24:81:d8",11,-6,0,0,0,7,0)
+CWLAP:(3,"Tainan-guest",-85,"1c:3a:60:64:81:d8",11,-6,0,4,4,7,0)

最後將板子重設,好清除上述設定:

AT+RESTORE
Image for post
Image for post
Photo by Annie Spratt on Unsplash

讓開發板以序列埠對 ESP8266 傳送 AT 訊息

只要你懂 AT 指令,你可以直接在終端機軟體內控制 ESP8266 連上網路、發送 HTTP 請求等。可想而知,若把這個過程寫在程式中、由開發板透過序列埠傳給 ESP8266,就能做到相同的結果了。對於 micro:bit 這類天生缺乏網路功能的板子來說,這無疑是一大福音。

那麼,燒錄好的 ESP8266 板子要如何跟其他開發板連接呢?

有趣的地方就在這裡:現在 ESP8266 板子除了會透過 USB 交換 AT 訊息,也會透過其 Tx/Rx 腳位做一樣的事。也就是說,你能將其 Tx 和 Rx 腳位接到其他開發板,同時透過 ESP8266 的 USB 頭來供電/讀取序列埠資料。你總共只需要 2 條 USB 線和 3 條杜邦線。

以 Uno 簡單測試序列埠 AT 訊息交換

在本篇,我們先用 Arduino Uno 做個示範,畢竟 Uno 可以在硬體序列埠外建立軟體序列埠,我們能藉此「透過」Uno 傳 AT 指令給 ESP8266,並看到後者傳回的回應。

下面來連接 Uno 和 ESP8266,兩塊板子各自用 USB 線供電(電腦的 USB 槽電力是夠的):

  1. GND → GND
  2. Tx → 12
  3. Rx → 11
Image for post
Image for post
這裡的圖用的是 NodeMCU V3,沒為什麼,只因 fritzing 裡這板子的圖最好看。
#include <SoftwareSerial.h>SoftwareSerial softSerial(11, 12); // 軟體序列埠 (Rx, Tx)void setup() {

Serial.begin(115200);
softSerial.begin(115200);

}
void loop() {

if (Serial.available()) { // 將序列埠輸入的字串傳給軟體序列埠
softSerial.write(Serial.read());
}

if (softSerial.available()) { // 將軟體序列埠輸入的字串傳給序列埠
Serial.write(softSerial.read());
}

}

在 Arduino IDE 中燒錄以上程式,這會使 Uno 變成一個序列埠「橋梁」 — — 你在序列埠監控視窗裡(記得 baud rate 要設為 115200)輸入 AT 指令,就會被 Uno 傳給 ESP8266,然後其回應會透過 Uno 傳回。不過,若是要在程式中送出 AT 指令,結尾必須記得加上換行符號(\r\n 或 \u000d\u000a)就是,不然 AT 韌體不會回應。

當然,這個程式寫得很簡單,而基於 Uno 的序列埠緩衝區大小限制,你會發現有不少資料遺失,讀到的 AT 回應不完整。某方面而言這是可以改善的,比如不斷把回應讀進字串、在某個時候再放出來。但這裡就暫時不討論了。

Image for post
Image for post
Photo by Jim Sung on Unsplash

使用 ESP8266 上傳資料到 ThingSpeak 物聯網網站

第二個範例是將 BBC micro:bit 接上 ESP8266,這其實也是筆者過去以 ESP-01 做過的應用。為了簡化起見,在此我們完全忽略 ESP8266 的 AT 回應,畢竟傳送資料到 ThinkSpeak,只需要用 HTTP GET 送出一個網址就行了。

這裡我們不介紹如何申請 ThinkSpeak 帳號並設定一個「頻道」──網路上應能找到許多教學文。

在此 micro:bit 會改用 P15/P16 腳位來傳送 UART 訊息。由於 micro:bit 是雙晶片架構,所以它不需要透過序列埠燒錄程式,但改變 UART 腳位後電腦就收不到 UART 訊息了。因此,你得監看 ESP8266 本身的序列埠才能知道程式跑到哪裡。

Image for post
Image for post
如果把 ESP8266 和 micro:bit 的 3.3V 電源接在一起,那麼 micro:bit 燒好程式後,用一條 USB 線直接從 ESP8266 供電就能兩個一起運作了 。據了解 CH340G 在 3.3V 可供 50 mA 的電,這對 micro:bit 來說是夠的。(許多 ESP8266 的 5V 腳位則是直接從 USB 吃電,但要注意 micro:bit 的運作電壓不能超過 3.6V。)

當然,ESP8266 在使用 WiFi 時,尖峰耗電量可能達 300–400 mA。所以有時對 ESP8266 獨立供電可能是更好的主意。

下面我們以 micro:bit 版的 MicroPython 為例,你可以使用官方線上編輯器Mu editor。一開始記得先用編輯器燒錄一個空程式進去,這樣板子上才會有 Python 直譯器。

我們需要使用的 AT 指令如下:

  1. AT+RESTORE(恢復預設設定)
  2. AT+CWMODE=1(設為 STA 或 station 模式)
  3. AT+RST(重置)
  4. AT+CWJAP=”wifi名稱”,”wifi密碼”(連上 WiFi)
  5. AT+CIPSTART=”TCP”,”server路徑”,80(連上伺服器)
  6. AT+CIPSEND=要傳送的字串長度(含換行字元)
    (然後緊接著傳送該字串,也就是 HTTP GET 請求)
SSID    = 'xxxxx'   # WiFi 名稱
PWD = 'ooooo' # WiFi 密碼
API_KEY = '你的API_KEY' # ThinkSpeak api key
URL = 'api.thingspeak.com' # 伺服器位址
REQUEST = '/update?api_key={}&field1={}' # 在伺服器要 GET 的網址

# 匯入所需模組
from microbit import uart, sleep, pin15, pin16, display
# 重新指定 UART 腳位為 P15, P16
uart.init(baudrate=115200, tx=pin15, rx=pin16)

# 用來傳 AT 指令的 function (包含傳送後的等待時間)
def sendAT(cmd, delay=100):
uart.write(str(cmd) + '\r\n')
sleep(delay)
sendAT('AT+RESTORE', 1000) # 恢復預設設定
sendAT('AT+CWMODE=1') # 設為 station 模式
sendAT('AT+RST', 1000) # 重置
# 連到 WiFi (建議等久一點)
sendAT('AT+CWJAP=\"{}\",\"{}\"'.format(SSID, PWD), 12000)

while True:

# 連到伺服器
sendAT('AT+CIPSTART=\"TCP\",\"{}\",80'.format(URL), 1000)

# 產生要送出的 GET 字串 (包含亮度感測值)
sendStr = 'GET ' + REQUEST.format(API_KEY, display.read_light_level())

# 先指定要傳送的字數 (含 \r\n)
sendAT('AT+CIPSEND={}'.format(len(sendStr) + 2))

# 傳送 GET 字串
sendAT(sendStr, 0)

# 等待下次傳送
sleep(9000)

WiFi 連線資料會被記錄在 ESP8266 上,再次通電時就會自動連上那個 WiFi。當然程式每次執行時還是會強制重設 + 重置 ESP8266 就是。

既然沒有讀取 AT 回應,有些指令就必須加上合適的延遲了。比如,有時使用 AT+CWJAP 連上 WiFi 的時間會格外的長,若來不及在時限內連上,後面的指令就會錯到底。所以若你遇到問題,可以試著將延遲時間加多一點。

你可以把 ESP8266 接在電腦上,這麼一來你就可以用 Tera Term 讀它的 AT 回應:

AT+CWJAP="xxxxx","ooooo"
WIFI CONNECTED
WIFI GOT IP
OK
AT+CIPSTART="TCP","api.thingspeak.com",80
CONNECT
OK
AT+CIPSEND=48
OK
>
Recv 48 bytes
SEND OK+IPD,2:11CLOSED
Image for post
Image for post

你能看到 ThinkSpeak 上確實收到資料並顯示出來。

Image for post
Image for post
Photo by Franki Chamaki on Unsplash

結語

本篇簡介了如何在正規 ESP8266 開發板上燒錄最新的 AT firmware,並用它當成其他開發板的 WiFi 晶片。儘管這樣做比不上直接使用 ESP8266 做 IoT 開發,但這樣能給某些無 WiFi 能力的板子朝網路延伸的機會。此外,這樣在供電與接線上,也比使用較舊的 ESP-01 模組容易許多。

當然,如果你想做到更複雜的網路控制,就必須研讀安可信的 AT 指令集。此外,接收資料的難度會更高,因為一不小心就可能錯過回應訊息(如 HTTP GET 的整個傳回結果)。所以,單純傳送資料到外部網站仍是比較容易做的應用。

另一個小問題是 ESP8266 的連線位址必須拆開成伺服器和後續的網域,這使得像是 IFTTT 的 Webhook 服務是沒法以這種方式呼叫的(我想大概是要 GET 整句才能正確轉換 DNS)。因此 ThinkSpeak 大概仍是這類板子上傳感測器資料時最好的對象吧。

Image for post
Image for post
Photo by Benjamin Davies on Unsplash

Written by

Former translator and currently a tech-book editor based in Taiwan. https://krantasblog.blogspot.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store