2017年1月2日 星期一

{有獎徵答} 給我一個可操作 AT 指令的 Arduino 函式庫 - 解決 AT 指令處理的蛋疼問題 (親測 Ai-Mod, AT v1.2.0.0 based on SDK v1.5.4.1 韌體)

網頁最後修改時間:2017/01/03  
AT 指令函式庫範例輸出畫面
接續上一篇 "自行更新 ESP8266 無線模組韌體至 - AT:1.2.0.0, SDK:1.5.4.1" 最後面談論到的,關於 AT 指令 Arduino 函式庫的問題。這一篇將就我實際使用與測試的結果,給出一個可用於上一篇網頁所升級的 AT 韌體的 Arduino 函式庫,最後使用該函式庫的範例程式進行實際測試得出所要的結果 !

如果你 (妳) 一直糾結於 ESP8266 AT 指令在 Arduino 使用上的便利性,又或是為了教學上的需求一定要用 AT 指令!那麼在熟悉 AT 指令操作之後的同時,一個將 AT 指令封裝成函式的函式庫,就是接下來撰寫無線通訊程式和  AT 指令初學者進階學習的一個最佳的選擇 !
*********************************************************************************
此網頁所用的材料可自行準備,或選用新版本的升級套件
更多 ESP8266 相關商品,請至分類賣場*********************************************************************************
ESP8266 模組 ( 若對於網頁中一些名詞不是很清楚的話,建議先看一下 "ESP8266 Arduino IDE 開發問與答 Q&A ( 1 )"  網頁中【ESP8266 / 模組 / 開發板】這一段的說明 ) 出廠的時候絕大部分都是預先載入 AT 韌體,每個製造商出廠的預設 AT 韌體版本不太相同,但只有燒錄了 AT 韌體,且能在雲端資料庫被查詢到的 ID設備才能被激活。有被激活的模組在接上 UART 轉 TTL 模組到電腦後,ESP8266 (以賣場 ESP-01/S為例) 輸出都會顯示模組製造商以及在最後輸出顯示 ready 這行字;如果是顯示 invalid,那麼就表示模組沒有被激活,沒有被激活的可以使用軟體激活,但不是所有的 ID 都可以被激活 !

有被激活的模組,就擁有模組製造商:
  • 免費雲端服務;否則只能在區域網路用
  • 支援 AT+CIOWRITEAT+CIOREAD 指令讀寫 GPIO
  • 支援 AT+CIOADC 指令讀取 ADC 電壓
  • 支援 AT 指令更新模組製造商官方最新版本
  • 支援 AT+CSYSHEAP 查詢模組剩餘 RAM 2的大小
  • 支援 AT+CWSTARTSMART,Smart Config 的功能 ( AT 1.2.0 之後的版本 ),使用ESP-TOUCH 手機 APP 進行無線配置 (不知道 Smart Config ? "ESP8266 Arduino IDE 開發問與答 Q&A ( 1 )" 網頁有說明 )
  • .... 等
否則上述功能就可能沒有或是喪失 !

新 AT 韌體版本更詳細的指令說明與操作範例,請關注部落格的消息發佈 !

上面有一點廣告的嫌疑 ! 但這邊要說明的是,不管你手邊的模組啟動的時候顯示的是 ready 或是 invalid,在上一篇所燒錄的 AT 韌體是屬於模組製造商發佈的官方版本,基本架構都是晶片商所發佈 SDK 的 AT 程式,多加入了幾個自己開發的功能;所以上面說的這些指令在晶片商 SDK 的 AT 指令集資料手冊是找不到的。
所以,題外話說了一堆,就是如果要跟著網頁做,那麼就先燒錄此篇網頁所使用的 AT 韌體版本;其他韌體版本不在此篇討論與問答之內,請跳轉 !

Arduino 函式庫:
我測試過幾個 Arduino AT 函式庫,程式都是使用內部範例,只有簡單的修改範例內的參數以符合實際的硬體設定。我知道 AT 韌體更新速度不算慢,所以會產生編譯或是執行上的錯誤難免,但是需要的函式庫至少要能夠處理簡單的幾個基本 AT 指令,並且要有切換選擇使用硬體 (HardwareSerial) 或是軟體 (SoftwareSerial) 通訊功能,基本測試的接線圖如下所示:

Arduino ESP8266 AT 函式庫測試接線圖
下載這個函式庫,並手動安裝;不知道怎麼手動安裝的,可看這裡的說明。

中間的電壓轉換模組沒有接 3V3 電壓的緣故是因為這個 3V3 電壓是輸出不是輸入,所以不需要再另外輸入 3V3 的電給它,但這只是特例 ! 實際要看電壓轉換模組的電路圖或是說明,一般 3V3 電壓都是需要再另外接上的,例如四通道雙向電壓轉換模組。

*********************************************************************************
如果需要中間那個電壓轉換模組,可以依照 "使用 N-Channel MOSFET 做 I2C 電壓準位轉換電路" 網頁中的說明自己佈線,或是到下面連結購買
*********************************************************************************

/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 第一次測試:
載入函式庫裡面的範例程式 "File/Examples/Sparkfun ESP8266 AT Library/ESP8266 _Ping" 這個範例程式,修改 line 26, 27 裡面關於無線網路的 SSID 與密碼

const char mySSID[] = "yourSSIDhere";
const char myPSK[] = "yourPWDhere";

修改 line 34 為
esp8266.begin(115200)

完成後進行編譯上傳。打開 "Serial Monitor" 並設定通訊速度為 9600 bps
ESP8266_Ping 範例測試結果 - 01
從輸出之中可以看出,一開始會出現 Error connecting to ESP8266.,接著每個一秒鐘 PING sparkfun.com 一次,輸出響應時間。
AT+PING 指令的使用範例
先不管那個錯誤 ! 再打開範例程式 "File/Examples/Sparkfun ESP8266 AT Library/ESP8266 _Shield_Demo" 這個範例程式,修改 line 36, 37 裡面關於無線網路的 SSID 與密碼

const char mySSID[] = "yourSSIDhere";
const char myPSK[] = "yourPWDhere";

修改 line 101 為
esp8266.begin(115200)

完成後進行編譯上傳。打開 "Serial Monitor" 並設定通訊速度為 9600 bps
ESP8266_Shield_Demo 範例測試結果 - 01
由輸出可以發現,當輸入任意字元之後,程式開始執行。第一個指令 ( initializeESP8266() ) 確定 ESP8266 可以開始進行操作,不過運行第二個指令 ( connectESP8266() ) 時就 GG 了 !

這個情形在我測試的幾個函式庫裡面算是最好的結果,而且由於它支援的 AT 韌體版本比較高 (晶片商 AT 韌體版本 AT v0.6.0, SDK v1.5.2),所以我決定深入找一下可能出現的問題,而且也找到了原因,完成了接下來的第二次測試。

/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 第二次測試:
同樣的兩個程式,但是:
恢復 "File/Examples/Sparkfun ESP8266 AT Library/ESP8266 _Ping"  line 34 如下
esp8266.begin()

恢復 "File/Examples/Sparkfun ESP8266 AT Library/ESP8266 _Shield_Demo"  line 101 如下
esp8266.begin()

兩個程式重新編譯後上傳,打開 "Serial Monitor" 並設定通訊速度為 9600 bps,兩個程式的輸出變的正常
ESP8266_Ping 範例測試結果 - 02
ESP8266_Shield_Demo 範例測試結果 - 02

ESP8266_Shield_Demo 範例的完整輸出
ESP8266_Shield_Demo 範例完整輸出
/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*
有購買 ESP8266 相關商品的使用者,網頁中所需相關資料已放置於雲端硬碟,都是在 Firmware 目錄下面的兩個資料夾中:
  • AT Firmware(AT v1.2.0.0 basd on ESP8266 SDK v1.5.4.1)
  • Flash Download Tools/Flash Download Tools V3.4.4.0
根據 Flash Size 已經分類好,有需要自行下載燒錄即可 !

其他使用者,可由下面網頁中的連結下載 AT 韌體檔案。

燒錄有風險,動作之前請確定知道自己在做什麼 !
/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*

/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* ESP8266 UART:

經過上面兩個測試之後應該不難發現到:更改的地方只有 SoftwareSerial::begin() 這個函式裡的參數設定;由第一次測試的 115200 改為預設值 (就是不加參數,9600 bps) 的第二次測試。

所以可以得到下面兩種使用情況之下的解決方法:

  • ESP8266 @ 115200 bps
    在這種情況下要穩定通訊必須使用硬體 UART 通訊方式,盡量不要使用 SoftwareSerial 函式庫 (軟體 UART)。
  • ESP8266 @ 9600 bps
    在這種情況下,硬體和軟體 UART 都可以使用。

有人問說 ESP8266 的 UART 設定是否可以完全設定不需要再每次開機再設定一次 ?

這是可以的 ! 在 "自行更新 ESP8266 , ESP-01 無線模組韌體至 AT:0.23, SDK:1.0.1" 這篇其中一段的說明就有提到,更新到這個版本之後,指令有了新的改變 ! 後綴  _CUR 是指使用一次的變更,再次開機值就會變回預設值;而後綴  _DEF 則是變更的值儲存到 Flash 中,下次開機就沿用此次變更的值。

所以,對於支援後綴 _CUR 和 _DEF 的 AT 韌體版本,要變更使用 UART 通訊速度使用的 AT 指令就是 AT_UART_DEF 來儲存變更 UART 的數值,例如 9600 bps 指令就是

AT+UART_DEF=9600,8,1,0,0

ESP8266_Shield_Demo 範例最後一段程式碼的測試:

Server Started! Go to ###.###.###.### 文字出現之後就是開始 ESP8266 最為 Server 的測試。這一部分的程式碼在 Serial Monitor 是看不出效果的,但是可以使用手機或是電腦連上與 ESP8266 同一個區域網路,打開瀏覽器輸入 http://###.###.###.### 與 ESP8266 連線,成功連線之後就會顯示如下類似畫面 (取得的數值會不同而已)

ESP8266_Shield_Demo 範例,瀏覽器連線到 ESP8266 的輸出網頁
接著使用手機或是其他電腦依相同方式與 ESP8266 連線,還是會顯示相同的畫面(數值不同)。

好了,現在問題來了! 為什麼你不能像我一樣很平順正常的與 ESP8266 連線得到相同的網頁結果;即便連線上了,再次連線或是使用其他電腦或手機的瀏覽器卻又很難連上去;又或是一開始連線就會連很久,值到按下停止才會輸出結果,又或是得不到結果,連線很不穩定 !

有獎徵答:

上面的問題剛開始時真找不到,不曉得是哪邊的問題:是硬體、AT 函式庫或是範例程式碼  ?

所以有獎徵答的問題就是:
哪裡出錯了 ? 出錯的地方在哪裡 ? 怎麼改才能可以同時多方連線且同時正常運作 ? 
簡化一下問題與提示一下解答方向:問題出在 ESP8266_Shield_Demo 範例程式裡面 !

正常的運作就像是下面展示影片一樣

答案請直接填在下面"問與答"即可,我收到後就會發佈出來;第一個答對的人,會收到回覆留言,就可以得到下面的獎品 (但是運費要自己付),這時再將自己的露天帳號填在問與答回覆即可(這封不會被發佈出來,資料會被隱藏),我收到之後就會開一個該帳號補運費的賣場給你下標。

獎品的相關說明與附帶資料如下面說明。
ESP8266 Black Board T5 雲功能測試板
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 簡介:
超簡單的物聯網開發平台,一款開源快速的硬件原形平台,包括任體和開發板,用簡單的AT指令即可調入加入雲端的服務器指令,直接遠程收發數據。

  • 支持 802.11b/n/g 無線標準;
  • 自主開發 MCU 平台,超高性價比;
  • 支持 UART/GPIO 數據通訊介面;
  • 支持 STA/AP/STA+AP 共存工作模式;
  • 支持 SmartLink 智慧聯網功能(提供APP );
  • 支持無線升級韌體;
  • 支持 WPS 聯網配置;
  • 內置板載天線;
  • 溫濕度傳感器;
  • RGB 三色燈可調;
  • 提供豐富 AT 指令集配置;
  • 免費的雲服務可供調試;
  • 支援鹼性電池與 5V 電源供電;
  • 尺寸:61.6mm x 56.2mm ;
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 特點:
開源,小體積,交互式,程式可編輯,低成本,一鍵配置,簡單,智能,WiFi硬件

/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 開發板附件資料:
  • 電路圖 (PDF)
  • APP 原始碼
  • 開發板單晶片原始碼
結論:

雖然使用 AT 函式庫操作 AT 指令變得輕鬆許多,但是有利就有弊 ! 利就不用多說了;弊的話,就是使用 AT 函式庫之前必須對 AT 指令有一定的了解,在不了解 AT 指令的情況之下進行操作,一但出現問題那會很難解決與除錯的 ! 所以千萬不要忘記一定要先熟悉 AT 指令的操作或是運作方式之後在來使用這個函式庫一定可以更得心應手 !

下面網頁是一個很好的開始之處:
操控 ESP8266 無線模組 - 經由 AP、STA 和 AP+STA 三種模式,學習 ESP8266 AT 指令

下一篇,就來使用 AT 函式庫改寫 "初遇 IoT ( Internet of Thing, 物聯網 ) - 使用 Arduino 控制 ESP8266 無線模組上傳資料到 IoT Server ( ThingSpeak )" 網頁中的範例,看結果會變得如何 ?

<< 部落格相關文章 >>

11 則留言:

  1. 您好,請問您有將+ipd,..後面所讀到的值,顯示在LCD5110的經驗嗎? 我是用一個ESP8266+NANO+DHT22將溫度值傳至另一個ESP8266+NANO+LCD5110,但無法顯示在LCD5110.可以的話,能否幫我看看成是哪裡有問題嗎? 可以的話,我在PO上來,感恩..

    回覆刪除
  2. 5110 顯示是使用函式庫,原則上只要你的格式正確,顯示的動作函式庫會幫你做! 先確認你的傳送與接收端的數據是否能夠正常接收與 print 出來,只要能 print 出來,會出錯大多是丟給5110顯示函式不被接受;再者就是檢查你的 5110 接線與程式定義是不是有錯!
    覺的有幫助,想找問題就將程式碼丟上來!

    回覆刪除
    回覆
    1. 謝謝您的回覆:
      我AP端的程式:
      #include
      #include
      #define _baudrate 9600
      #define _rxpin 8
      #define _txpin 9
      SoftwareSerial debug( _rxpin, _txpin ); // RX, TX
      #define SSID "ALPHABRASS1"
      #define PASS "harmony1"
      #define IP "192.168.4.1"
      #include
      LCD5110 myGLCD(3,4,5,6,7);
      extern uint8_t SmallFont[];
      extern uint8_t MediumNumbers[];
      extern uint8_t BigNumbers[];
      float t1;

      void setup() {
      myGLCD.InitLCD();
      Serial.begin( _baudrate );
      debug.begin( _baudrate );
      sendDebug("AT");
      Loding("sent AT");
      sendDebug("AT+CWMODE=2");
      delay(1000);
      Loding("AT+CWMODE=2");
      delay(4000);
      connectWiFi();
      }

      void loop() {
      if (debug.available())
      {
      myGLCD.clrScr();
      myGLCD.setFont(SmallFont);
      String s = "";
      char c = debug.read() ;
      Serial.print(c);
      myGLCD.printNumF(c, 1, LEFT, 0);
      }
      if (Serial.available())
      { char c = Serial.read();
      debug.print(c);
      }
      }

      boolean connectWiFi()
      {
      Wifi_connect();
      }

      void Wifi_connect()
      {
      String cmd="AT+CWSAP=\"";
      cmd+=SSID;
      cmd+="\",\"";
      cmd+=PASS;
      cmd+="\",6,4";
      sendDebug(cmd);
      delay(2000);
      sendDebug("AT+CIFSR");
      delay(1000);
      Loding("AT+CIFSR");
      delay(2000);
      sendDebug("AT+CIPMUX=1");
      delay(1000);
      Loding("AT+CIPMUX=1");
      delay(2000);
      sendDebug("AT+CIPSERVER=1,80");
      delay(1000);
      Loding("AT+CIPSERVER=1,80");
      delay(2000);
      }

      void Loding(String state){
      if(debug.find("OK"))
      {
      Serial.println("RECEIVED: OK");
      }
      else
      {
      Serial.println("RECEIVED: NG");

      }
      }

      void sendDebug(String cmd)
      {
      Serial.print("SEND: ");
      Serial.println(cmd);
      debug.println(cmd);
      }

      刪除
  3. LCD5110會一直顯示48.0,若我將AP端讀到的 char c = debug.read()-48 ; 變成一直顯示0.0,就是無法顯示讀到的值...

    回覆刪除
    回覆
    1. 大概看一下你的程式碼!
      就如之前回覆的,如果你已經可以在 com port 上面看到發送與接收的字串,但是無法顯示在LCD5110,那個應該就是你的 LCD5110 顯示的函式使用錯誤 !
      你的接收顯示的程式碼中,並沒有去處理接收到 +IPD... 的字串,而是直接將它由 com port 顯示出來,所以可以看到接收到的字串,那是當然的!也由於你沒有去處理,而是將它直接使用 myGLCD.printNumF(c, 1, LEFT, 0); 做輸出,所以會造成錯誤。
      由 LCD5110 basic 資料手冊上面可以看到三個使用於輸出的函式:print, printNumI(), printNumF,分別是顯示字串, 整數和浮點數,而程式收到的是字串卻用顯示浮點數的函式做顯示,因為一次只輸出一個浮點數,所以只會找到最後面接收到的字元,所以才會一直顯示 48.0 !
      建議你,若直是想直接輸出接收到的字串,直接使用 print 就可以,但是因為你是單一字元接收作顯示,因此座標要輸出一次變一次,不然有可以只有最左邊的字元會做變化。
      有問題可以去參考一夏 LCD5110 的資料手冊,相關函式有很清楚的說明 !
      以上,希望對你有所幫助!

      刪除
  4. 感謝神大指點,
    趕快先去找使用手冊,不知要怎麼感謝神大,如我能力範圍可及,請再告訴我.謝謝.

    回覆刪除
  5. 神大您好
    我改用myGLCD.print(Serial.read(), CENTER, 55);
    但arduino verify時卻出現 conversion from 'int' to 'String' is ambiguous
    程式中並沒有設定int的部分,您知道為什麼會這樣嗎?

    回覆刪除
  6. Arduino IDE v1.6.12 單獨跑下面程式碼沒有任何錯誤產生,不清楚你為什麼會發生問題!
    而且,你的程式碼應該是接收一整個資料之後再丟進去 print 做顯示,而不是接收一個顯示一個!這樣只會顯示一個字元的資料。
    //---------
    #include

    LCD5110 myGLCD(8,9,10,11,12);
    extern uint8_t SmallFont[];
    extern uint8_t MediumNumbers[];
    extern uint8_t BigNumbers[];

    void setup()
    {
    myGLCD.InitLCD();
    Serial.begin(9600);
    }

    void loop()
    {
    myGLCD.setFont(SmallFont);
    myGLCD.print(Serial.read(), CENTER, 55);
    }

    ///---------------------
    如果你的編譯有問題,試試改這樣試試
    myGLCD.print( (char)Serial.read(), CENTER, 55);

    回覆刪除
  7. 神大您好,
    因我想先確定LCD51110可以顯示,故程式還沒改成接收一個顯示一個.

    您說改成myGLCD.print( (char)Serial.read(), CENTER, 55);的方式,但我編譯還是會出現相同錯誤,可是您說沒問題,想請問您#include後面是用LCD5110_Basic.h函式嗎?

    回覆刪除
    回覆
    1. 是 LCD5110_Basic.h 沒錯 !
      你確定是那一行產生錯誤而不是其他的地方? 因為不管有沒加,我這邊編譯時沒有產生任何錯誤!

      刪除
  8. 我的Arduino是1.06版的,改成arduino 1.8.1編譯就沒問題了.謝謝您.

    回覆刪除

留言屬名為"Unknown"或"不明"的用戶,大多這樣的留言都會直接被刪除掉,不會得到任何回覆!

發問問題,請描述清楚你(妳)的問題,別人回答前不會想去 "猜" 問題是什麼?

不知道怎麼發問,請看 [公告] 部落格提問須知 - 如何問問題 !