替 Arduino Nano 開無線外掛 (一) 接一片ESP-01

Arduino Nano 是一片蠻理想的 MCU,功能跟 Arduino Uno 一樣多,面積、體積卻小很多,是開發物連網應用、實踐一些有趣想法的好工具。美中不足的是,它沒有無線功能,不能實現遠端監控。直覺的想法,是把手上現成的 ESP8266模組,ESP-01 ,接上 Arduion Nano,弄成像下圖的架構,這樣就可以接上無線路由器,透過家裡的ADSL實現遠端控制了,甚至架一個有資料庫的小伺服器 (Raspberry+SQLite):

跟早年利用市話的複頻電話信號 (DTMF) 的音調,透過一個解碼器,從遠端撥電話,來控制家裡某個東西的裝置。這樣就能在家裡以外的地方,從遠端對 Nano 下命令,或者讓  Nano蒐集一些感測器的資料回來,甚至更進一步存進去資料庫。

當然,買一片 NodeMcu 比較快,不過手頭現成的東西,可以物盡其用,並順便研究一下 ESP8266 的功能。

簡易連接 Arduino Nano 與 ESP-01

Google 一下 Arduino ESP8266,就能找到很多教學資料,在中文教學的網站中,我覺得小狐狸事務所 的 Tony 寫得最詳細,這篇詳盡的教學可以參考,Tony的筆記做得非常詳細,很棒的網站,像創客百科全書。
要連接 Arduino 跟 ESP-01,第一個會遇到的問題,就是兩者的電壓準位不一樣,Arduino是5V的,而ESP8266這種需要盡量省電的物聯網晶片,走的是 3.3V。要把兩個不同電壓準位的板子接起來,需要 Logic Level Shift 這種雙向電壓準位轉換器,才是正道:
SparkFun 雙向電壓準位轉換器
也可以直接買Arduino專用的 ESP8266 轉接板,可以從PCB上面的零件來看,除了兩顆準位轉換器外,下面還有一顆穩壓器把Arduino的5V轉成 3.3V,供電給 ESP-01:

ESP-01 轉接板
如果只是像我一樣玩票性的朋友,能有簡單的替代方案,那是再好不過的事情,免得零件越買越多、越堆越多。Arduino 的 I/O,可以相容 3.3V 沒問題,問題是 ESP-01 無法承受5V,據說會燒壞。但實際上,之前已經試過連接 Tx Rx,沒事,可見信號線不容易弄壞板子,不要接錯電源就沒事。根據以上概念,解決方案是 ESP Tx 到 Nano Rx 這條,直接對接就行。而 Nano 過去 ESP-01 這條,設法把電壓變成原本的 2/3,也就是 5V * 2 / 3 = 3.3334V,拿電阻分壓就成了。像下圖這樣的接法。那個 2K歐姆的電阻,也可以用兩顆1KΩ 歐姆電阻串連獲得,用3顆棕黑紅電阻湊出分壓電路。
接線圖

讓兩片板子開始通訊

接好就可以開始把Arduino 載入程式來試試了,測試過程難免會遇到一些障礙,畢竟是 PC <-> Arduino <-> ESP8266 這樣間接控制,會有硬體接線、ESP8266參數、Arduino程式的多重變因存在。但不必灰心,搞不定的時候,回頭把ESP-01接上USB轉TTL模組,下AT指令,確定它還正常運作,心裡就比較踏實一點,重複操作幾次,熟練之後,會更快收斂問題。
在 Arduino Nano 程式中,除了控制硬體本身的 UART (USB serial port 就是 D0 D1上的 Tx Rx),得要有另外一個 UART,才能把其中一組UART接 ESP-01,另外一組接電腦來傳送指令、接收回應,才知道這兩個小東西在聊些什麼。所以要用 Software Serial,把D2跟D3,變成UART串列埠,這樣就多一組UART接到ESP-01了。
用 Software Serial (SW Tx, SW Rx) 連接 ESP-01,原本的 Rx Tx 透過USB連電腦 

序列埠串口通訊,是一種問答式的通訊方式 Poll/Response,除非像可外接COM port的電子磅秤、電錶那種裝置,定時自動回報重量值、電壓值的設計例外。

Arduino這邊的程式很簡單,像下面程式這樣,把電腦傳過去Nano的命令轉傳給ESP-01,同時把ESP-01回答給Arduino的,如實轉傳回電腦。我稍微改一下Tony的程式,因為發現 API 的 read buffer 有長度限制,查了一下,原來只有 64 byte。在Serial Monitor下 AT+GMR這個指令之後,會掉資料。每一個 loop()循環,用單一個 read 命令讀取,serial buffer 來不及被取完就已經溢位。下面程式改成根據byte數量,在同一個loop,執行數個read指令讀回來,這樣就不會掉資料了:

#include <SoftwareSerial.h>
//開一個軟體序列埠串口,留主要的TX,RX,可以從IDE讀信號。
SoftwareSerial ESPserial(2, 3); //設定RX在D2腳位接到ESP01的TX;TX在D3腳位,降壓後接到ESP01的RX

void setup()
{
    Serial.begin(115200);//Baud rate 根據實際Arduino IDE,Serial Monitor的Baud Rate設定改動
    ESPserial.begin(57600);//這個Baud Rate,要跟ESP-01通信,要遷就上面ESP8266的鮑率設定
    //一般ESP01剛買來,內建的設定是 9600,但如果更新韌體固件,有可能預設為 115200

    Serial.println("");
    Serial.println("Select Both NL & CR, for sending command to ESP01");
    Serial.println("Start Communication");
}

void loop()
{
    int numbyte=0;
    // 定時去查看有沒有資料傳回,如果Buffer中有資料,則馬上讀回並印出來
    if ( numbyte = ESPserial.available() )   {
      for (int n = 0; n < numbyte; n++) {
        Serial.write( ESPserial.read() );
      }
    }

    // 如果 User在終端機軟體上發出指令,則傳出去給ESP-01
    if ( Serial.available() )       {  ESPserial.write( Serial.read() );  }
}

實驗結果,Arduino <-> ESP01這端,Baud Rate 在 57600 bps 以下,都可以正常工作,但是在 115200bps 下達 AT+GMR指令,則會回覆不完整的訊息。應該是阻抗匹配的問題,線路上有雜訊。也可能是 Software Serial 處理速度的問題。目前還沒有試驗,直接用 Arduino 的 Tx Rx來通訊,會不會就OK了。但沒有示波器、邏輯分析儀也沒辦法Debug,只求能動就好,57600bps 也遠比用 9600bps 快多了。利用USB轉TTL模組,下 AT+UART_DEF=57600,8,1,0,0 指令,將ESP-01的鮑率 Baud Rate 設定成 57600 bps。

指令的參數細節,可以讀一下ESP8266 AT指令集手冊。Arduino-PC這端,則可以用最快的 115200 bps,目前的實驗,是用手動下命令,PC <-> Arduino 與 Arduino <-> ESP01 兩邊的速度不一定要一樣,設成不一樣沒問題。要設成一樣都是 57600 bps 也可以,操作的時候,記得把終端機的 Baud Rate 改成這個設定值就好。

接下來

後文《替 Arduino Nano 開無線外掛 (二) 使用 WiFiEsp 函式庫》會告訴你,要怎麼控制 ESP-01,讓 ESP-01連接上無線分享器之後,跟遠端伺服器,以UDP通訊協定來快速交換編碼後的資料,或執行遠端控制。

1 則留言:

  1. 請問一下您的電容加進去的目的是? 我想讓Arduino直接供電給ESP01,但又怕Ardunio的電不夠,謝謝您的回覆,祝您新年快樂

    回覆刪除