2015年10月4日 星期日

★ ESP8266 WiFi 模組與 Arduino 連線測試

經過兩個月來的摸索, 對於 Arduino 經由 ESP8266 連上網路的實驗終於來到實作階段. 這當中也分心去研究如何製做 ESP8266 的轉接板, 雖已經有腹案, 但覺得還是先把連網實驗做完再來搞定轉接板好了. 這兩塊板子互連主要有兩個障礙, 一是開發階段串列埠不夠的問題, 二是 Arduino 的 5V 位準與 ESP8266 的 3.3V 位準轉換的問題.

不管是 UNO 還是 Nano, 它們都只有一組 UART 串列埠 TX0 與 RX0, 而且與 USB 是共接的, 亦即如果將 Arduino 的 USB 接到電腦用來上傳程式與透過 Serial.print() 來除錯與追蹤執行結果, 那麼串列埠 TX0/RX0 就不能同時接到 ESP8266 來傳送 AT 指令與接收回應.

解決之道是使用 SoftwareSerial 函式庫來將一般 DIO 針腳模擬成軟體串列埠, 我習慣是使用 Pin 11 當 TX, Pin 10 當 RX, 參考之前寫的 UART 串列埠測試 :

Arduino 串列埠測試 (UART)

第二個問題是 Arduino 與 ESP8266 互連時電壓位準的調適. ESP8266 工作於 3.3V 電源下, 不可以直接將 Ardino 的 TX 接到 ESP8266 的 URXD 腳 (即 RX), 這麼做會讓 ESP8266 陣亡, 參考 ESP8266 規格 :

# https://nurdspace.nl/images/e/e0/ESP8266_Specifications_English.pdf

在這本規格書的第 15 頁, 談到其 DIO 針腳的電氣規格, 最大輸入電壓是 3.6V (Input high voltage, maximum), 與 Arduino 的 5V 有 1.4V 壓差, 這可能將 URXD 針腳與內部電路燒毀. 而其 DIO 腳高邏輯的最低輸出電壓為 0.8*VIO (Output high voltage)=0.8*3.3=2.64V, 這在 TTL 會被視為 High (>2V), 所以直接推動 Arduino 的 RX 腳基本上沒問題 (只是邊限小了些, 只有約 0.64V). 若要可靠些, 可用 MOSFET 2N7000 與兩顆電阻做成 Level shifter 來轉成 5V 系統, 參考 :

用 MOFFET 2N7000 做 5V 與 3.3V 位準轉換

解決了以上這兩個問題, 就可以進行互連實驗了. 這實驗主要是參考 Proteus 君這篇大作 :

初遇 IoT ( Internet of Thing, 物聯網 ) - 使用 Arduino 控制 ESP8266 無線模組上傳資料到 IoT Server ( ThingSpeak )

在這篇文章中, Proteus 使用 UNO 做為主控板, 而我是用小巧方便的 Nano. 他使用了一塊位準轉換模組進行 TX/RX 的 5V/3.3V 轉換, 我則參考底下這篇文章, 採用簡單的 10K+20K 電阻分壓法 (註 : 應該使用 1K+2K) 將 Arduino 的 TX 介接到 ESP8266 的 URXD 腳, RX 則直接與 ESP8266 的 UXTD 腳相連 :

# A Simple IoT Project with the ESP8266 WiFi module

此作者使用 3 個 1K 電阻來分壓, 其實用 10K+20K 也無妨 (註 : 會不穩), 因為 Arduino 的 DIO 腳當輸入時, 輸入阻抗約為 100M Ohms, 還蠻大的, 參考 :

# Properties of Pins Configured as INPUT

電路圖如下 (用 Upverter 繪製) :


註 : 實驗發現分壓電阻不能用 10k+20k 組合, RC 效應太大, 應改用 1K+2K 或 220+470 組合.

麵包板接線圖如下 (用 Fritzing 繪製) :


這裡我使用麵包板專用電源供電給 ESP8266 模組 (上方 3.3V) 與 DHT11 (下方 5V), 而 Arduino Nano 則由 PC 的 USB 供電, 這兩組電源的 GND 必須共接地 (Nano 左上方第三隻腳的黑線). 當然 DHT11 吃 Nano 的 5V 也是可以的, 此處接麵包板專用電源是為了接線方便. DHT11 的第二腳 Data 要接一個 10K 上拉電阻到 5V, 其 VCC 則接一個 0.1uF 電容接地.


硬體弄好後, 得去物聯網伺服器網站 Thingspeak 註冊一個帳號, 在 Proteus 的 "初遇 IoT" 有詳細說明, 不再贅述. Thingspeak 有提供 Arduino 的應用範例, 參考 :

# Using an Arduino + Ethernet Shield to Update a ThingSpeak Channel

在上面這個教學文中, 有一個重要資料必須記下來, 就是 Thingspeak 伺服器的 IP 位址 : 184.106.153.149, 這在 ESP8266 與 Thingspeak 伺服器建立 TCP 連線時會用到, 若網路中有 DNS 伺服器, 也可以用 api.thingspeak.com 取代. 

我將申請的通道 (Channel) 命名為 DHT11 :


按 "Channel Settings" 頁籤可以看到, 每一個 Channel 可以記錄最多 8 個欄位資料, 但在這個實驗中我只用到三個欄位 : 攝氏溫度 Temperature(degC), 華式溫度 Temperature(degF), 與濕度 humidity(%) :


設定好欄位後要按底下的 "Save Chanel" 鈕才會真的存進去 :

 
再切到 API Keys, 裡面有 Read 與 Write 兩種金鑰, Read Key 用來從網路程式讀取 Thingspeak 通道資料, 而 Write Key 用來寫入資料, Arduino 要將取得的溫溼度寫到 Thingspeak 伺服器需要的是 Write Key, 這要記下來程式中要用到 :


這樣我們就可以在 Arduino 程式完成之前, 先用 HTTP 的 GET 方式傳送資料給 Thingspeak 伺服器, 測試看看這個寫入金鑰管不管用, 其格式為 :

http://api.thingspeak.com/update?api_key=[寫入金鑰]&field1=[攝氏溫度]&field2=[華氏溫度]&field3=[濕度]

有些網站 (例如 Proteus) 使用的金鑰名稱是 key 而非 api_key, 其實我測試的結果是兩個都可以, Thingspeak 都接受 :

http://api.thingspeak.com/update?key=[寫入金鑰]&field1=[攝氏溫度]&field2=[華氏溫度]&field3=[濕度]

例如 :

http://api.thingspeak.com/update?api_key=NO5N8C7T2KINFCQE&field1=25.4&field2=87.4&field3=55

把此網址貼到瀏覽器, 會回應一個數字, 表示這是第幾筆資料了. 例如 4 表示剛剛寫進去的是第四筆資料, 這時候在 Thingspeak 網站上切換至 Public View 或 Private View 就可以看到填入的數據隨時間變化的圖形了 :


如果要清除這些測試的資料, 按 "Channel Settings" 頁籤底下的 "Clear Channel" 按鈕即刪除.

最後是 Arduino 程式部分, 為了簡化流程, 我不打算在 Arduino 程式中處理 ESP8266 連線無線基地台的 AT 指令, 而是預先將 ESP8266 以 PL2303HX 之類的 TTL 轉 USB 轉換線連接電腦 USB 埠, 用 Realterm 等軟體將 ESP8266 的工作模式設定成 STA 模式與單一連接, AT 指令如下 :

AT+CWMODE=1  (STA 模式) 

其次, ESP8266 不是當 Server, 因此只需要單一 TCP 連線 :

AT+CIPMUX=0  (單一連線)

建立 TCP設定要連接的無線基地台 (SSID, PASSWORD), 其 AT 指令如下 : 

AT+CWJAP="EDIMAX-tony","123456789111" 

設定完後 ESP8266 會記錄這些設定在 Flash 中, 即使關掉電源也會記住, 只要一通電就會尋找原先設定的基地台自動連線. 參考 :


設定好之後, 我們先用 Realterm 直接對 ESP8266 下 AT 指令來模擬傳送溫溼度紀錄到 Thingspeak 伺服器的動作.

首先須與 Thingspeak 伺服器的 80 埠建立 TCP 連線, AT 指令如下 :

AT+CIPSTART="TCP","184.106.153.149",80 

其中 184.106.153.149 乃是 Thingspeak 伺服器的 IP 位址. 連線成功的話, ESP8266 會回應 :

OK                                                                             
Linked

表示已經建立 TCP 連線了.

其次是要告訴 ESP8266 我們打算要傳送多少字元的資料, 以便其準備所需之緩衝區. 所使用的 AT 指令是 CIPSEND, 參考 ESP8266 快速指南中的第八頁 "Acting as a TCP Client" :

ESP8266 WiFi Module Quick Start Guide (PDF)

不過我們要做些調整, 此文首先是將 CIPMUX 設為 1 (允許多重連線, 預設為 0, 單一連線), 但這是不需要的, 因為我們只是要用到 ESP8266 的 STA 模式而已, 不需要作為伺服器時之多重連線. 也因此, CIPSTART 指令也不需要指定 id, 參考 :

# ESP8266 AT Command Set (PDF)


當然, 要告知資料長度, 得先知道要傳送的是啥資料. 我們在上面測試 Thingspeak 伺服器時, 是在瀏覽器貼上 Thingspeak API 的網址, 但在作為客戶端 (STA 模式) 的 ESP8266 而言, 則是要向目的主機發出如下格式之 GET 請求 :

GET /目的網頁網址

參考 :

https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

而此處目的網頁就是 Thingspeak 的更新通道資料的網頁程式 update :

update?api_key=寫入金鑰&欄位1=數值1&欄位2=數值2&欄位3=數值3....

我們要向 ESP8266 傳送的資料格式如下 :

GET /update?api_key=NO5N8C7T2KINFCQE&field1=29.00&field2=84.20&field3=73.00

將此 GET 指令貼到 WORD 中進行字數統計, 可知含空格 (GET 後面那個) 共 75 字元 :




但我們用 Realterm 傳送 AT 指令給 ESP8266 時都必須在後面加上 \r\n 這兩個跳行字元, 因此全部字元長度須再加上 2, 總共是 75+2=77, 因此 AT 指令如下 :

AT+CIPSEND=77

參考 :

# Tutorial: IoT Datalogger with ESP8266 WiFi Module and FRDM-KL25Z
 
注意, 這個總字元長度必須恰恰好, 多跟少都不行, ESP8266 會因為兜不攏而當在那邊, 無法完成傳送任務. 此 AT 指令下完後, ESP8266 會回應一個大於提示號, 表示可以開始傳送資料 :

>

最後是就是把要溫溼度資料的 GET 指令字串貼到 > 後面傳送 :

>
GET /update?api_key=NO5N8C7T2KINFCQE&field1=24.00&field2=83.20&field3=77.00

成功的話, ESP8266 立刻回應 +IPD 如下 :

SEND OK

+IPD,1:7
OK

OK
Unlink

傳送完資料 ESP8266 就自動拆除 TCP 連線, 顯示 Unlink. 如果是沒有, 必須手動拆線, 其 AT 指令是 AT+CIPCLOSE. 注意, 上面傳送完成後, ESP8266 會向 Arduino 回送 +IPD, 後面的 1 表示伺服器回應資料的長度, 此處 1 表示 1 個 byte, 冒號後面 7 即 Thingspeak 伺服器回應的資料為 7, 表示此為第七筆寫入之資料, 參考 :

# https://github.com/espressif/esp8266_at/wiki/IPD

這樣便確認 ESP8266 可以正確透過 WiFi 基地台向 Thingspeak 伺服器傳送更新數據了.


完成以上測試後, 便可將 PL2303HX 轉換線移除, 將 ESP8266 與 Arduino 照上面電路圖連接. 然後撰寫 Arduino 程式, 模擬上面的人工操作, 自動向 ESP8266 傳送 AT 指令, 使其透過 WiFi 連線向 Thingspeak 伺服器更新溫溼度資料.

摘要以上四個步驟與 Arduino 程式作法 :
  1. 與目的主機建立 TCP 連線 :
    AT+CIPSTART="TCP","184.106.153.149",80   //連線 Thingspeak 主機
    在 Arduino 中以字串表示時, 須將雙引號以倒斜線跳開 :
    String cmd="AT+CIPSTART=\"TCP\",\"184.106.153.149\",80";
  2. 傳送 GET 字串長度給 ESP8266 :
    AT+CIPSEND=GET 字串長度 
  3. 傳送 GET 字串給 ESP8266 :
    sSerial.println(GET 字串)  
  4. 關閉 TCP 連線 :
    AT+CIPCLOSE
下面的測試程式是我參考阿喵就像家的 "ESP8266 Workshop" 投影片中的程式修改來模擬上面 Realterm 傳送 AT 指令, 用來驗證串列埠與軟體串列埠接線是否正常運作 :

#include <SoftwareSerial.h>
SoftwareSerial sSerial(10,11); //(RX,TX) 與 ESP8266 介接的軟體串列埠

void setup() {
  sSerial.begin(9600);
  Serial.begin(9600);
  Serial.println("SoftSerial to ESP8266 AT commands test ...");
  }

void loop() {
  if (sSerial.available()) {  //若軟體串列埠 RX 有收到來自 ESP8266 的回應字元
    Serial.write(sSerial.read());  //在串列埠監控視窗顯示 ESP8266 的回應字元
    }
  if (Serial.available()) {  //若串列埠 RX 有收到來自 PC 的 AT 指令字元 (USB TX)
    char c=Serial.read();  //先暫存在字元變數 c 緩衝一下
    sSerial.write(c);  //將 PC 的傳來的字元傳給 ESP8266
    }
  delay(50);  //緩衝 50ms 以免傳送太快 (不用, 後述)
  }

程式上傳後, 打開序列埠監視視窗, 先把右下方的行尾加送模式選為 "NL & CR", 表示每次傳送時都要在傳送字串後面加上跳行, 然後在上方輸入框敲入 AT 指令, 按傳送, 若接線沒問題, 應可在下方框看到 ESP8266 的回應訊息 :


回應訊息如下 :

SoftSerial to ESP8266 test...
AT

OK


AT+RST

OK
bB��@�Sc��S��"�JL��������H�
[System Ready, Vendor:www.ai-thinker.com

AT+CIPSTART="TCP","184.106.153.149",80


OK
Linked

AT+CIPSEND=77

> GET /update?api_key=NO5N8C7T2KINFCQE&field1=25.00&field2=84.20&field3=78.00

SEND OK

+IPD,1:8
OK

OK
Unlink

可見接線沒問題, 電壓位準也 OK, 整個架構是正確的. 嘿! 我突然發現, 利用上面這個程式我不需要 USB-TTL 轉接線, 用 Arduino 就可以對 ESP8266 下 AT 指令了耶! 這真是太棒了! 不過要注意的是, 上面程式最後一行的 delay(50) 是需要的, 如果取消就似乎太快, 序列部監視視窗根本毫無反應. 我試過大約 40~50 ms 最適當, 但偶而還是會有幾個字元傳送錯誤, 要多試幾次. 如果毫無反應, 可能是接線不良, 特別是 ESP8266 的 TX 到 Arduino 的 RX 這條. 若 AT 指令下下去後, ESP8266 的藍燈沒閃, 表示沒收到信號, 要檢查 Arduino TX 到 ESP8266 RX 這條線. (此 delay 完全不需要, 原因後述)

以上述程式驗證連線無誤, 軟體序列埠與硬體序列埠可正常通訊後, 最後以 "A Simple IoT Project with the ESP8266 WiFi module" 這篇文章的程式為主軸, 綜合之前做 DHT11 溫溼度測試 (參考 Arduino 溫濕度感測器 DHT11 測試), 改寫為如下程式, 由 Arduino 讀取 DHT11 量測之溫濕度數據, 透過軟體序列埠傳送給 ESP8266 經 WiFi 網路給 Thingspeak 伺服器.

這裡用到的 DHT11 函式庫可至 Adafruit 網站下載, 按網頁右下角的 "Download ZIP即可. 注意, Arduino IDE 必須關閉重開才會去抓函式庫, 否則仍編譯失敗.

程式如下 :

#include <SoftwareSerial.h>           //載入軟體串列埠函式庫
#include <DHT.h>                   //載入 DHT11 函式庫
#define DHTPIN 2                    //定義 DIO 腳 2 為 DHT11 輸入
#define DHTTYPE DHT11               //定義 DHT 型態為 DHT11

DHT dht(DHTPIN, DHTTYPE);          //初始化 DHT11 感測器
int LED=13;                         //宣告 DIO 腳 13 為 LED 輸出
String api_key="NO5N8C7T2KINFCQE";  //Thingspeak API Write Key
SoftwareSerial sSerial(10,11);        //設定軟體串列埠腳位 RX, TX為 DIO 腳 10, 11

void setup() {              
  pinMode(LED, OUTPUT);             //設定 DIO Pin 13 為 LED 輸出
  Serial.begin(9600);                //啟始硬體串列埠 (除錯用)
  sSerial.begin(9600);              //啟始軟體串列埠 (與 ESP8266 介接用)
  dht.begin();                      //啟始 DHT11 溫濕度感測器
  sSerial.println("AT+RST");        //軟體串列埠傳送 AT 指令重啟 ESP8266
  }

void loop() {
  float h=dht.readHumidity();         //讀取濕度
  float c=dht.readTemperature();      //讀取攝氏溫度
  float f=dht.readTemperature(true);  //讀取華氏溫度
  //有任何一個是 NAN 就不往下執行資料傳送
  if (isnan(h) || isnan(c) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
    }
  blink_led(1000,500); //進入資料傳送程序 : LED 閃爍一次  
  String param="&field1=" + (String)c + "&field2=" + (String)f +
               "&field3=" + (String)h; //製作參數字串
  //Serial.println(param); //輸出字串參數於監控視窗

  //與 Thingspeak 主機建立 TCP 連線
  String cmd="AT+CIPSTART=\"TCP\",\"184.106.153.149\",80";
  sSerial.println(cmd); //向 ESP8266 傳送 TCP 連線之 AT 指令

  //偵測 TCP 連線是否成功
  if (sSerial.find("Error")) {          
    Serial.println("AT+CIPSTART error!");
    return;  //連線失敗跳出目前迴圈 (不做後續傳送作業)
    }
  Serial.println(cmd);  //輸出 AT 指令於監控視窗

  //製作 GET 字串
  String GET="GET /update?api_key=" + api_key + param + "\r\n\r\n";
  Serial.println(GET);  //顯示 GET 字串內容於監控視窗
  cmd="AT+CIPSEND=" + String(GET.length()); //傳送 GET 字串長度之 AT 指令
  sSerial.println(cmd);  //告知 ESP8266 即將傳送之 GET 字串長度
  Serial.println(cmd); //輸出 AT 指令於監控視窗

  //檢查 ESP8266 是否回應
  if (sSerial.find(">")) {  //若收到 ESP8266 的回應標頭結束字元
    sSerial.print(GET);  //向 ESP8266 傳送 GET 字串內容
    }
  else {  //沒有收到 ESP8266 回應
    sSerial.println("AT+CIPCLOSE");  //關閉 TCP 連線
    Serial.println("AT+CIPCLOSE");    //顯示連線關閉訊息於監控視窗
    }
  delay(16000);  //延遲 16 秒 (因 Thingspeak 每次更新須隔 15 秒)
  }

void blink_led(int on, int off) {  //LED 閃爍函式
  digitalWrite(LED, HIGH);
  delay(on);
  digitalWrite(LED, LOW);
  delay(off);
  }

結果不會動, 我把 Thingspeak 的通道清除後, 資料仍然沒進來, 空空如也. Why?  程式來回檢查好幾遍了, 沒錯呀, 跟原作者的做法相同啊? 而且每 16 秒鐘的 loop 都有看到 ESP8266 的藍燈在閃, 表示有傳送資料, 為何 Thingspeak 沒收到呢?

序列埠監視視窗的輸出如下 :

AT+CIPSTART="TCP","184.106.153.149",80
GET /update?api_key=NO5N8C7T2KINFCQE&field1=28.00&field2=82.40&field3=81.00


AT+CIPSEND=79
AT+CIPCLOSE

可見 GET 指令沒有送出去. .再研究 ....

**********************************************

晚上回高雄後仍不死心, 又重新測試一遍, 結果更糟, 連前面利用序列埠監視視窗對 ESP8266 下 AT 指令的程式也沒反應, 接線稍微喬一喬有改善, 但仍然會遺失字元, 導致 Error. 難道麵包板接線這麼脆弱嗎? 移動一下就不行? 我突然想到這是電訊號問題, 該不會是 10K+20K 分壓電阻太大了吧? 這是唯一跟原作者不一樣的地方.

之前就有懷疑這點, 上周五下班後特地跑去禾樺買了一包 1K+2K 的電阻. 於是拿出來替換掉 10+20k 分壓組合, 而且去掉我自己加的很奇怪的 delay(50), 果然! 序列埠監視視窗傳送 AT 指令不再掉字元, 非常順啊! 原來搞了我兩三天的就是分壓電阻! 我想原因可能是, 雖然 10K/20K 對 100M 的輸入阻抗不算甚麼, 但是, 電阻越高, RC 反應時間變長, 可能使訊號變形, 導致字元錯誤或遺失 (有示波器的話應該就能看得明白了). 電路學中, RC 電路的時間常數 R*C 表示電壓上升至終值得 65% 的時間, 電阻越大時間常數也越大, 當然 High 可能被認為是 Low 而產生訊息錯誤了. 參考 :

RC電路的時間常數

原作者使用 1K 電阻是對的, 我自作聰明換成 10K 根本是自找苦吃.

找到原因後, 再重新上傳 DHT11 溫溼度測量程式, 哇, 終於成功啦 :


圖中溫度突然上升, 濕度突然下降是用吹風機熱風吹的緣故. 這個 Thingspeak 曲線圖會自動更新, 不需要手動重新整理網頁, 蠻不錯的.


參考 :

# ESP8266 Community Forum
# ESP8266 WiFi module and 5V Arduino connection
# ESP8266 wiring with Arduino
# ESP8266 wiring schemas
深入淺出 Wifi 晶片 ESP8266 with Arduino
# SoftwareSerial Library
A Simple IoT Project with the ESP8266 WiFi module
# Programming an Arduino via WiFi with the ESP8266
http://www.arduinesp.com/thingspeak (使用 ESP8266WiFi.h)
# ESP8266 + Arduino Uno: Can't send AT Commands
# How to use ESP8266 ESP-01 as a SENSOR web client
# ESP8266 Wi-Fi Module with Teensy and Arduino
# Freaky response from the ESP8266 with Arduino Nano
# Programming an Arduino via WiFi with the ESP8266
# ThingSpeak-Arduino-Examples (Ethernet)
# Using an Arduino + Ethernet Shield to Update a ThingSpeak Channel
http://electronut.in/posts/ (孟加拉)
Arduino 結合ESP8266將空氣資料送到Synology NAS(取代Thingspeak)


# UPLOAD SENSORS DATA TO THINGSPEAK BY USING ARDUINO AND ESP8266

關於 AT 指令的進一步探討, 參考 :

# Wifi success, for a change!


另外, 在 "A Simple IoT Project with the ESP8266 WiFi module" 這篇文章裡, 作者使用了一個 C 函數 dtstrf() 來將計算所得之溫度浮點數轉成字串, 剛開始時對這怪異的函數名稱很感冒 (意思是 double to string function), 後來在下面這篇看到其用法解釋, 發現還真好用呢 !

# Displaying FLOAT variables in Arduino

其參數與用法簡單說明如下 :

dtstrf(浮點數, 總字元數, 小數點後位數, 字元陣列)

其中, 總字元數轉換為字串後含小數點總共有多少字元, 故 (總字元數-小數點後位數-1) 就是整數部分的位數. 故要先宣告一個字元陣列來儲存轉換後的字串, 其長度須比總字元數長. 例如 d=123.4567 經 dtstrf(d, 5, 1, s) 轉換後, 得到字串 s=123.4.

此作者有一個進階版的溫度資料收集器, 特殊之處在利用 CH_PD 來省電, 在需要傳送資料時將 CH_PD 設為 High, 傳送完畢設為 Low :

An IoT Temperature Monitor for my Balcony Garden

參考 :

# Tutorial: IoT Datalogger with ESP8266 WiFi Module and FRDM-KL25Z
teos0009/ESP8266 Arduino Mega


112 則留言 :

Unknown 提到...

想請問一下,我自己在測試ESP8266透過 WiFi 基地台向 Thingspeak 伺服器傳送數據,直接從SSCOM下指令(wifi連線沒問題)!
指令如下:
AT+CIPSEND=56

> GET /update?key=JJRRYGIO2SK7BTTH&field1=24.5&field2=57.5

busy s...

SEND OK

OK
Unlink
----------------------------------------------
接線是跟您的這篇文章:
http://yhhuang1966.blogspot.tw/2015/07/esp8266-wifi-at-command.html
一樣的接法
----------------------------------------------
他多出了"busy s..."這行,也沒有回應+IPD,有試過加上\r\n但還是一樣,想請問這有可能是哪邊出問題嗎?
萬分感謝~

小狐狸事務所 提到...

您好, 謝謝您的回應. 我認為問題應該出在 AT+CIPSEND=56, 您送的 GET 字串是 56 個沒錯, 但通訊程式在後面有加送 \r\n, 一共是 58 字元才對. 依我測試的經驗, 字元數目不對可能有兩種反應, 一是當在那邊, 過一會兒出現 error 訊息; 二是像您看到的, 回覆 SEND OK, 但卻沒有回應 +IPD, 這其實並未真正傳送成功, 因為 ESP 有回應 IPD, 表示有從 Thingspeak 網站收到回應內容 (目前的總資料筆數), 否則根本就沒有從伺服器收到資料, 請您改送 58 Bytes 試試看吧! 另外, Thingspeak 只能接受最快每 15 秒更新一次資料, 因此程式後面務必加上 delay(16000) 為宜. 預祝您成功!

Unknown 提到...

謝謝您這麼快回覆,我試過未加\r\n 56字元,加上\r\n 58字元,兩個都試過,可是還是沒辦法得到+IPD的回應,這個部份卡了一段時間,不知道該怎麼解決,完全沒頭緒,想再麻煩您幫我看看是哪邊出了問題,非常感謝您~

小狐狸事務所 提到...

嗯, 確實很奇怪, 我就是在 CIPSEND 這邊卡了幾天的, 著實苦惱. 也曾想過直接殺到 NodeMCU, 用 LUA 來做省事多了, 但就是不甘心, AT 指令的運作我一定要搞熟, 因為 GSM 或藍芽等模組也是會用到. AT 都 OK, SEND 也 OK, 為何伺服器圖就是不動? 來回看了前輩們的紀錄, 才發現 CIPSEND 是關鍵, Byte 數不符合 ESP8266 就秀逗了. 您是怎樣貼上 GET 指令的呢? 是在 WORD 嗎? 或許在複製指令時, 有複製到結尾的跳行, 這樣加上通訊程式的跳行又會多 2 個 BYTE, 變成 60. 我建議在記事本複製指令. 不然試試 60 BYTE 看看.

Unknown 提到...

真的很謝謝你的建議,我照您說的方向,慢慢試出正確的byte數,真的非常感謝你,卡了這麼久結果是這個小問題,有點不甘心,不過至少成功了,謝謝你的熱心回覆!!!

小狐狸事務所 提到...

恭喜您成功了! 雖只是個小魚骨, 鯁在喉間便是進退不得. 北宋張載說 : 於不疑處有疑, 方是進矣. 雖然不是大學問, 但總算突破了. 兄弟我為您感到高興.

Unknown 提到...

不好意思,再次打擾您,小弟在esp8266的應用上有些問題想請教您,不知道您方不方便,希望可以用mail跟您聯繫,
以下是小弟的e-amil:thebest1031@gmail.com 非常感謝您~

小狐狸事務所 提到...

OK

Unknown 提到...

不好意思,因為我找不到您的e-mail,不知道方不放便請您留一下您的e-mail,麻煩您了,謝謝

Unknown 提到...

不好意思,想請問您,當arduino透過esp8266連上網路的狀態下,有辦法讓使用者透過瀏覽器傳值到arduino,讓arduino作計算嗎?如果是可行的,可以用什麼方式呢?非常感謝您~

小狐狸事務所 提到...

應該沒問題, 我最近有空就要進行類似的實驗了.

Unknown 提到...

您好!
真的因為您的文章受益良多,現在好像也卡在跟跟您一樣的地方了,不過我是自己架MYSQL來做資料的存取。手動輸入CIPSTART 跟 CIPSEND 時都很順利,但一加到程式內後就出問題了,顯示的東西跟您都一樣,但是好像在GET之前就出問題了,CIPSTART送出後,我試著抓回傳值,但是沒有任何回傳,GET指令後的回傳值居然只有一個A...,不曉得您有解決辦法了沒,非常想向您請教~~~

Unknown 提到...
作者已經移除這則留言。
Unknown 提到...

(恩...原來刪除會有紀錄,上一篇打錯註解了OAQ)
呼...
加了delay,TCP、GET過了,還是沒讀到echo的值...
最後弄成一個一個字元做輸入...
完成後把delay刪掉,剛剛的問題也不見了....(到底為了什麼花那個多時間測dely...OAQ)
以下是最後的程式碼,還請您過目看看,能跑了但是根本不知道為什麼OTZ (過段時間可能又爆了也說不定......)

String cmd2="AT+CIPSTART=\"TCP\",\"";
cmd2 += ServerIP;
cmd2 += "\",80";
esp8266.println(cmd2);
//delay(500);
if (esp8266.find("Error"))
{
Serial.println("AT+CIPSTART error!");
return;
}

String GET = "GET /E_control/receive.php?UID=A23256&type=start\r\n\r\n";
int GNUM = GET.length();//GET轉字元陣列
char GETARRAY[GNUM];//GET轉字元陣列
GET.toCharArray(GETARRAY,GNUM);//GET轉字元陣列
cmd2 = "AT+CIPSEND="+String(GNUM);
esp8266.println(cmd2);
Serial.println(cmd2);

//delay(500);
if(esp8266.find(">"))
{
for(int i =0;i5000)
return;
time++;
}
}
else
{
delay(16000);
return;
}

Unknown 提到...
作者已經移除這則留言。
barryhong 提到...

我是用LM35取代DHT11(剛好手邊沒有),結果發現LM35接到analog input時,配合software serial會有滿嚴重的干擾,溫度的數值跳動的幅度滿大的,就算取多次平均也是改善有限(也採用過跟前一次數值比,差距大於多少就捨棄的方式),直接接D0/D1會好很多,以後再想想看怎麼避免干擾,重點是練習以ESP8266上傳資料到thingspeak,感謝你的心得分享

小狐狸事務所 提到...

謝謝您的分享, 等手邊有 LM35 時, 我也來試試看, 順便比較一下兩者的精確度.

墨香 提到...

老師抱歉打擾了
我想請問8266可不可以就只是單純的建立一個基地台
然後發射訊號給範圍內的其他8266模組
不要連上網站的
謝謝老師!!

小狐狸事務所 提到...

只做 AP 不聯外應該可以的喔! 但是它最多只能允許四個 CLIENT 連線, 而且開啟的伺服器效能也很有限喔! 您這想法很不錯, 讓連到此 AP 的各個 CLIENT 互相通訊, 有空我也來試試, 謝謝您的留言.

小狐狸事務所 提到...

另, 因為您的留言, 我才發現之前 Ji Hung Lin 兄也在此留言過, SORRY, 沒注意喔.

墨香 提到...

其實我對這個模組算是完全沒概念才會問這種問題啦哈哈哈
謝謝老師的回答

墨香 提到...
作者已經移除這則留言。
小光 提到...
作者已經移除這則留言。
小光 提到...

您好,我已經實現esp8266傳值上thinkspeak,但我紀錄的是FSR的數值
想請問您,但是我使用2個esp8266分別傳至不同的field就無法成功,請問有方法解決嗎?

小狐狸事務所 提到...

您是說用兩顆 esp 傳資料到同一個 thingspeak 帳號的不同欄位失敗嗎? 照理說 thingspeak 只認 key, 只要你有正確的 key 應該就會寫入資料庫. 但是要注意, thingspeak 紀錄資料的頻率限制是最快每 15 秒接收 1 筆, 參考 :

http://community.thingspeak.com/forum/thingspeak-api/limits-for-field-data/

The only limits enforced are:
1. The fastest rate you can send data to your channel is once every 15 seconds
2. You can retrieve a maximum of 8000 points per field per call
All the points that you have listed do not have limits.

小光 提到...

您好,抱歉我敘述不清楚,應該說不是失敗,是只會有一個esp8266的資料在上傳
分別拿開來使用就沒問題
如果您方便我們可以用email討論嗎?
joshua820810@gmail.com

thanks a lot

CCTsai 提到...

輸入AT+CWJAP="EDIMAX-tony","123456789111"這個建立TCP設定要連接的無線基地台可是回應FALL是哪裡問題

小狐狸事務所 提到...

您要將您自己的無線基地台 SSID 與 PWD 填進去呀! "EDIMAX-tony","123456789111" 是我家的 WIFI 基地台, 您根本收不到我的訊號. 用手機行動網路分享 WIFI 也可以唷!

CCTsai 提到...

唷了解!第一次玩謝謝

CCTsai 提到...

可是我有試者連接網路分享也無法

小狐狸事務所 提到...

要先確定可以使用序列埠監控視窗對 ESP8266 下 AT 指令, 才能用 AT+CWJAP 連線基地台.

flightpig 提到...

你好,電源供應為LM1117 3.3v降壓器加2顆鋰電池,不過很奇怪的是,我只要一接上ch-pd pin,電壓馬上會降到1.8v,且esp01的燈很暗,好像沒有啟動,但我如果改用arduino的3.3v直接供應電,可以啟動,但是會一直重開,請問你有遇過類似的問題嗎?

小狐狸事務所 提到...

ESP8266 燈變暗表示電源不夠力, 您的鋰電池是 18650 嗎? 充飽時無載應該有 4.2V, 電力應該足夠才對. 建議您試試看從電腦 USB 輸出的 5V 供給 LM1117, 它有 500mA 推動力. Arduino 的 3.3V 輸出只有 50mA 左右, 無法推動 ESP8266 穩定運作, 一定要用獨立且夠力的 3.3V 電源, ESP8266 開機瞬間用電超過 200mA.

Unknown 提到...

不好意思,想請教為何我複製您的dht11程式碼後製作參數那一行會出現錯誤?

小狐狸事務所 提到...

不太了解 "製作參數那一行" 是哪一行? 可否貼出來呢?

匿名 提到...

請問要如何修改esp8266的連線AP, SSID跟password??

小狐狸事務所 提到...

AT+CWJAP="SSID","PWD" : 連線指定之基地台 (Join AP)
參考這篇 :
http://yhhuang1966.blogspot.tw/2015/07/esp8266-wifi-at-command.html

Unknown 提到...

String param="&field1=" + (String)c + "&field2=" + (String)f +
"&field3=" + (String)h; //製作參數字串
在這一段會錯誤,但我把前面的FLOAT宣告換成INT就可以,請問,這樣是什麼問題?

小狐狸事務所 提到...

我編譯都沒有出現問題耶, 怪了. 其實 dht11 解析度只到整數, 故用 int 也沒差. 可否貼出錯誤訊息?

Unknown 提到...

請問我現在想做的是利用ESP8266 + arduino 連區域網路 然後傳值到MYSQL資料庫做儲存

現在可以連到區域網路,但要怎麼丟值到資料庫呢?請老師解惑,謝謝~

Unknown 提到...
作者已經移除這則留言。
Unknown 提到...
作者已經移除這則留言。
Unknown 提到...
作者已經移除這則留言。
Unknown 提到...

他編譯後會顯示"call of overloaded 'String(float&)'is ambiguous,會不會跟版本有關係?我用的是1.0.4板,
還有我想請問一下是每次跑這個程式一定要先用realterm做字元設定嗎?因為我發現arduino的監控式窗跑出來的字原統計是60,而我一開始在realterm設定時是用65,因為多了浮點數的關係,但這樣還是能上傳到Thingspeak,另外您說DHT11只能到整數,那為何在統計字元時您會統計到小數點後兩位?最後一個問題是如果我今天要多加一個感測器,那在Thingspeak就必須要再多開一個通道嗎?不好意思問題有點多

小狐狸事務所 提到...

先回答上面劉兄問題, 使用一般 HTTP 向區網中的伺服器提出要求就可以啦! 用 GET 或 POST 都可以, GET 比較方便. 那台伺服器要先寫好 PHP 應用程式來處理 Arduino 的 HTTP Request, 將參數資料存進 MySQL.

小狐狸事務所 提到...

何兄, 請下載最新版 IDE 試試看.

Unknown 提到...
作者已經移除這則留言。
Unknown 提到...

他會顯示call of overloaded 'string(float)'is ambiguous,會不會跟版本有關係

小狐狸事務所 提到...

最新版 1.6.10 支援較多函式庫

Unknown 提到...

另外我想請問次每次跑這段程式前都要先用realterm作自數傳送嗎?因為我發現我在arduino的監控室窗跑出來的字數是60,但我傳送時是給65,因為多了浮點數的關係,但還是能正常傳送到ThingSpeak

Unknown 提到...

另外我想請問次每次跑這段程式前都要先用realterm作自數傳送嗎?因為我發現我在arduino的監控室窗跑出來的字數是60,但我傳送時是給65,因為多了浮點數的關係,但還是能正常傳送到ThingSpeak

Unknown 提到...
作者已經移除這則留言。
Unknown 提到...
作者已經移除這則留言。
Unknown 提到...
作者已經移除這則留言。
Unknown 提到...

我爬了很多文,還是不太清楚GET怎麼去運用他...老師是否有比較清晰的範例,可以供學生參考~~

Unknown 提到...
作者已經移除這則留言。
Unknown 提到...
作者已經移除這則留言。
Unknown 提到...
作者已經移除這則留言。
Unknown 提到...

我的留言太常都會自動消失,真奇怪

小狐狸事務所 提到...

之前也有網友反應, blogger 有時怪怪的. 有時我修改文章內容, 就給我 duplicate 同樣一篇, 變成兩篇同樣的.

Unknown 提到...

請問我在arduino 打 String GET = "htdocs/WIFI_TEST.php?patient_id=3,SPO2=60,pulse=60";
傳的是cmd = GET+"\r\n"; //"GET /tmp/val.php?string=";
Serial1.print( "AT+CIPSEND=" );
Serial1.println( cmd.length() );
if(Serial1.find( ">" ) )
{
Serial.print(">");
Serial.print(cmd);
Serial1.print(cmd);
}
else
{
Serial1.print( "AT+CIPCLOSE" );
}
if( Serial1.find("OK") )
{
Serial.println( "RECEIVED: OK" );
}

那我再PHP那邊應該怎麼寫才會正常收到值呢?還是上面的有錯押?

我不確定String GET那行對不對~

目前印出來的是我寫的index.php的程式碼= =完全不解><

請老師解惑~感恩敢跟~

小狐狸事務所 提到...

劉兄, 請參考這篇 :

http://yhhuang1966.blogspot.tw/2015/05/php-get-post-request.html

也可參考趙英傑寫的 "Arduino 互動設計入門 2" 第 16 章.

五餅二魚水族倉庫 提到...

老師請問一下,UART+esp8266接上電腦,程式都能正常執行,但我只要將電腦關掉,接esp8266的UART拿走,其它接線皆不變,讓esp8266單獨執行,就會找不到AP,難道esp8266不能單獨執行嗎?,一定要接UART及跟著電腦走嗎?,謝謝指導

註:我只接UART+esp8266,並沒有使用arduino,只是單純讓 esp8266當通訊接收,及利用GPIO做簡易控制

小狐狸事務所 提到...

ESP8266 本身就是一個 32 位元微控器, 性能其實比 Arduino 優, 只是 ESP-01 模組僅接出兩個 GPIO, 控制能力較薄弱而已. 單獨用 ESP-01 做控制我很早之前就想測試了, 使用的函式庫不同, 不是把 Arduino + ESP8266 中的 Arduino 拔掉就可以的. 最近有空我會進行測試, 您先玩看看囉.

匿名 提到...

您好 我想要讓12片的壓力感測器用arduino傳出值再透過wifi傳到thingspeak的網站在下載到pc的excel檔,但是WIFI的程式跟壓力感測的程式是要寫在一起嗎,不太知道要怎麼把兩個東西合在一起,能指導一下嗎

Unknown 提到...

您好,請問一下
與 Thingspeak 伺服器的 80 埠建立 TCP 連線, AT 指令如下 :

AT+CIPSTART="TCP","184.106.153.149",80
我使用Realterm執行這個步驟時回覆ERROR Unlink
以上該怎麼解決或者是該參考哪一篇文章呢?

小狐狸事務所 提到...

回答關於 12片的壓力感測器問題 : 您可參考最近這篇 :

http://yhhuang1966.blogspot.tw/2016/11/20w_8.html

WIFI 程式是由兩支函數負責, 感測資料呼叫 sendData() 即可送至 ThingSpeak

小狐狸事務所 提到...

回答 Roy Wu :

ERROR 就是 ESP8266 無法與該 IP 之主機連線, 可能是該主機的問題. 您可先跟其他主機像 ThingSpeak 建立連線看看. 同樣可參考 :

http://yhhuang1966.blogspot.tw/2016/11/20w_8.html

匿名 提到...

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

小狐狸事務所 提到...

感謝您留言, 我 5110 實驗上回做一半就因故被打斷到現在都還沒時間回頭做, 真是抱歉. 不過您 po 上來沒關係, 我有空會看一看, 若我無法解決, 或許有其他高手會回答喔!

Taylor 提到...

謝協您的回覆,我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);
}

Taylor 提到...

CLIENT是:
#include
#include "DHT.h"
#define _baudrate 9600
#define _rxpin 4
#define _txpin 5
SoftwareSerial debug( _rxpin, _txpin ); // RX, TX
//*-- IoT Information
#define SSID "ALPHABRASS1"
#define PASS "harmony1"
#define IP "192.168.4.1" // ThingSpeak IP Address: 184.106.153.149
#define DHTPIN1 A5

#define DHTTYPE DHT22
DHT dht1(DHTPIN1, DHTTYPE);

void setup() {
Serial.begin( _baudrate );
debug.begin( _baudrate );
dht1.begin();

sendDebug("AT");
Loding("sent AT");

sendDebug("AT+RST");
delay(2000);
Loding("sent AT+RST");

sendDebug("AT+CWMODE=1");
Loding("sent AT+CWMODE=1");

connectWiFi();
}
void loop() {
delay(6000); // 60 second

float h1 = dht1.readHumidity();
float t1 = dht1.readTemperature();


// 設定 ESP8266 作為 Client 端
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
sendDebug(cmd);
delay(2000);
if( debug.find( "Error" ) )
{
Serial.print( "RECEIVED: Error\nExit1" );
return;
}

Serial.print("AT+CIPSEND=5");
delay(2000);
debug.print( "AT+CIPSEND=5" );
delay(2000);
Serial.print("\r\n");
debug.print( "\r\n" );

if(debug.find( ">" ) )
{
Serial.print(">");
Serial.print(t1);
Serial.print(" ");
Serial.print(h1);

Serial.print("AT+CIPCLOSE");
debug.print( "AT+CIPCLOSE");
}
else
{
debug.print( "AT+CIPCLOSE" );
}
if( debug.find("OK") )
{
Serial.println( "RECEIVED: OK" );
}
else
{
Serial.println( "RECEIVED: Error\nExit2" );
}

}
boolean connectWiFi()
{
debug.println("AT+CWMODE=1");
Wifi_connect();
}


void Wifi_connect()
{
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
sendDebug(cmd);
delay(2000);
Loding("Wifi_connect");
}
void Loding(String state){
for (int timeout=0 ; timeout<10 ; timeout++)
{
if(debug.find("OK"))
{
Serial.println("RECEIVED: OK");
break;
}
else if(timeout==9){
Serial.print( state );
Serial.println(" fail...\nExit2");
}
else
{
Serial.print("Wifi Loading...");
delay(500);
}
}
}
void sendDebug(String cmd)
{
Serial.print("SEND: ");
Serial.println(cmd);
debug.println(cmd);
}

目前CLIENT程式會將溫度值傳給AP,打開AP及CLIENT端的COM PORT,都可看到互傳的溫度值,但就是無法將AP端+IPD,..的後面溫度值 顯示在LCD5110上,
試了快二個月了,也爬了許多文,希望能有高手指點.再次謝謝您.

Taylor 提到...

謝協您的回覆,我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);
}

匿名 提到...

CLIENT是:
#include
#include "DHT.h"
#define _baudrate 9600
#define _rxpin 4
#define _txpin 5
SoftwareSerial debug( _rxpin, _txpin ); // RX, TX
//*-- IoT Information
#define SSID "ALPHABRASS1"
#define PASS "harmony1"
#define IP "192.168.4.1" // ThingSpeak IP Address: 184.106.153.149
#define DHTPIN1 A5

#define DHTTYPE DHT22
DHT dht1(DHTPIN1, DHTTYPE);

void setup() {
Serial.begin( _baudrate );
debug.begin( _baudrate );
dht1.begin();

sendDebug("AT");
Loding("sent AT");

sendDebug("AT+RST");
delay(2000);
Loding("sent AT+RST");

sendDebug("AT+CWMODE=1");
Loding("sent AT+CWMODE=1");

connectWiFi();
}
void loop() {
delay(6000); // 60 second

float h1 = dht1.readHumidity();
float t1 = dht1.readTemperature();


// 設定 ESP8266 作為 Client 端
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
sendDebug(cmd);
delay(2000);
if( debug.find( "Error" ) )
{
Serial.print( "RECEIVED: Error\nExit1" );
return;
}

Serial.print("AT+CIPSEND=5");
delay(2000);
debug.print( "AT+CIPSEND=5" );
delay(2000);
Serial.print("\r\n");
debug.print( "\r\n" );

if(debug.find( ">" ) )
{
Serial.print(">");
Serial.print(t1);
Serial.print(" ");
Serial.print(h1);

Serial.print("AT+CIPCLOSE");
debug.print( "AT+CIPCLOSE");
}
else
{
debug.print( "AT+CIPCLOSE" );
}
if( debug.find("OK") )
{
Serial.println( "RECEIVED: OK" );
}
else
{
Serial.println( "RECEIVED: Error\nExit2" );
}

}
boolean connectWiFi()
{
debug.println("AT+CWMODE=1");
Wifi_connect();
}


void Wifi_connect()
{
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
sendDebug(cmd);
delay(2000);
Loding("Wifi_connect");
}
void Loding(String state){
for (int timeout=0 ; timeout<10 ; timeout++)
{
if(debug.find("OK"))
{
Serial.println("RECEIVED: OK");
break;
}
else if(timeout==9){
Serial.print( state );
Serial.println(" fail...\nExit2");
}
else
{
Serial.print("Wifi Loading...");
delay(500);
}
}
}
void sendDebug(String cmd)
{
Serial.print("SEND: ");
Serial.println(cmd);
debug.println(cmd);
}

目前CLIENT程式會將溫度值傳給AP,打開AP及CLIENT端的COM PORT,都可看到互傳的溫度值,但就是無法將AP端+IPD,..的後面溫度值 顯示在LCD5110上,
試了快二個月了,也爬了許多文,希望能有高手指點.再次謝謝您.

Taylor 提到...

謝協您的回覆,我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);
}

HTML限制4096個字,CLIENT PO不上來....
目前CLIENT程式會將溫度值傳給AP,打開AP及CLIENT端的COM PORT,都可看到互傳的溫度值,但就是無法將AP端+IPD,..的後面溫度值 顯示在LCD5110上,
試了快二個月了,也爬了許多文,希望能有高手指點.再次謝謝您.

小狐狸事務所 提到...

感謝 Taylor 兄留言, 因 blogger 留言有限制只能使用某些 html, 否則會被視為垃圾留言, 需要人工移回來. 我找時間研究一下您的問題, 看看能否解決.

Taylor 提到...

感謝大大,
我CLIENT的程式:
#include
#include "DHT.h"
#define _baudrate 9600
#define _rxpin 4
#define _txpin 5
SoftwareSerial debug( _rxpin, _txpin ); // RX, TX
//*-- IoT Information
#define SSID "ALPHABRASS1"
#define PASS "harmony1"
#define IP "192.168.4.1" // ThingSpeak IP Address: 184.106.153.149
#define DHTPIN1 A5

#define DHTTYPE DHT22
DHT dht1(DHTPIN1, DHTTYPE);

void setup() {
Serial.begin( _baudrate );
debug.begin( _baudrate );
dht1.begin();

sendDebug("AT");
Loding("sent AT");

sendDebug("AT+RST");
delay(2000);
Loding("sent AT+RST");

sendDebug("AT+CWMODE=1");
Loding("sent AT+CWMODE=1");

connectWiFi();
}
void loop() {
delay(6000); // 60 second

float h1 = dht1.readHumidity();
float t1 = dht1.readTemperature();


// 設定 ESP8266 作為 Client 端
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
sendDebug(cmd);
delay(2000);
if( debug.find( "Error" ) )
{
Serial.print( "RECEIVED: Error\nExit1" );
return;
}

Serial.print("AT+CIPSEND=5");
delay(2000);
debug.print( "AT+CIPSEND=5" );
delay(2000);
Serial.print("\r\n");
debug.print( "\r\n" );

if(debug.find( ">" ) )
{
Serial.print(">");
Serial.print(t1);
Serial.print(" ");
Serial.print(h1);

Serial.print("AT+CIPCLOSE");
debug.print( "AT+CIPCLOSE");
}
else
{
debug.print( "AT+CIPCLOSE" );
}
if( debug.find("OK") )
{
Serial.println( "RECEIVED: OK" );
}
else
{
Serial.println( "RECEIVED: Error\nExit2" );
}

}
boolean connectWiFi()
{
debug.println("AT+CWMODE=1");
Wifi_connect();
}

void Wifi_connect()
{
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
sendDebug(cmd);
delay(2000);
Loding("Wifi_connect");
}
void Loding(String state){
for (int timeout=0 ; timeout<10 ; timeout++)
{
if(debug.find("OK"))
{
Serial.println("RECEIVED: OK");
break;
}
else if(timeout==9){
Serial.print( state );
Serial.println(" fail...\nExit2");
}
else
{
Serial.print("Wifi Loading...");
delay(500);
}
}
}
void sendDebug(String cmd)
{
Serial.print("SEND: ");
Serial.println(cmd);
debug.println(cmd);
}

CLIENT會送溫度及濕度,但AP端我先只收溫度,但LCD5110只會一直show 48.0,若我改 c = debug.read()-48 ; LCD5110只會一直show 0.0 Orz

Taylor 提到...

我CLIENT的程式:
#include
#include "DHT.h"
#define _baudrate 9600
#define _rxpin 4
#define _txpin 5
SoftwareSerial debug( _rxpin, _txpin ); // RX, TX
//*-- IoT Information
#define SSID "ALPHABRASS1"
#define PASS "harmony1"
#define IP "192.168.4.1" // ThingSpeak IP Address: 184.106.153.149
#define DHTPIN1 A5

#define DHTTYPE DHT22
DHT dht1(DHTPIN1, DHTTYPE);

void setup() {
Serial.begin( _baudrate );
debug.begin( _baudrate );
dht1.begin();

sendDebug("AT");
Loding("sent AT");

sendDebug("AT+RST");
delay(2000);
Loding("sent AT+RST");

sendDebug("AT+CWMODE=1");
Loding("sent AT+CWMODE=1");

connectWiFi();
}
void loop() {
delay(6000); // 60 second

float h1 = dht1.readHumidity();
float t1 = dht1.readTemperature();

String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
sendDebug(cmd);
delay(2000);
if( debug.find( "Error" ) )
{
Serial.print( "RECEIVED: Error\nExit1" );
return;
}

Serial.print("AT+CIPSEND=5");
delay(2000);
debug.print( "AT+CIPSEND=5" );
delay(2000);
Serial.print("\r\n");
debug.print( "\r\n" );

if(debug.find( ">" ) )
{
Serial.print(">");
Serial.print(t1);
Serial.print(" ");
Serial.print(h1);

Serial.print("AT+CIPCLOSE");
debug.print( "AT+CIPCLOSE");
}
else
{
debug.print( "AT+CIPCLOSE" );
}
if( debug.find("OK") )
{
Serial.println( "RECEIVED: OK" );
}
else
{
Serial.println( "RECEIVED: Error\nExit2" );
}

}
boolean connectWiFi()
{
debug.println("AT+CWMODE=1");
Wifi_connect();
}

void Wifi_connect()
{
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
sendDebug(cmd);
delay(2000);
Loding("Wifi_connect");
}
void Loding(String state){
for (int timeout=0 ; timeout<10 ; timeout++)
{
if(debug.find("OK"))
{
Serial.println("RECEIVED: OK");
break;
}
else if(timeout==9){
Serial.print( state );
Serial.println(" fail...\nExit2");
}
else
{
Serial.print("Wifi Loading...");
delay(500);
}
}
}
void sendDebug(String cmd)
{
Serial.print("SEND: ");
Serial.println(cmd);
debug.println(cmd);
}

CLIENT會送溫度及濕度,但AP端我先只收溫度,但LCD5110在AP端只會一直show 48.0,若我改 c = debug.read()-48 ; LCD5110只會一直show 0.0

謝謝大大...

Taylor 提到...

大大您好,
因程式在html中show不出 #include 後面的SoftwareSerial.h及LCD5110_Basic.h 故底下CLIENT端的#include後面我用說明的方式..

#include 這裡有SoftwareSerial.h 因網頁show不出來,故在此說明
#include "DHT.h"
#define _baudrate 9600
#define _rxpin 4
#define _txpin 5
SoftwareSerial debug( _rxpin, _txpin ); // RX, TX
//*-- IoT Information
#define SSID "ALPHABRASS1"
#define PASS "harmony1"
#define IP "192.168.4.1" // ThingSpeak IP Address: 184.106.153.149
#define DHTPIN1 A5

#define DHTTYPE DHT22
DHT dht1(DHTPIN1, DHTTYPE);

void setup() {
Serial.begin( _baudrate );
debug.begin( _baudrate );
dht1.begin();

sendDebug("AT");
Loding("sent AT");

sendDebug("AT+RST");
delay(2000);
Loding("sent AT+RST");

sendDebug("AT+CWMODE=1");
Loding("sent AT+CWMODE=1");

connectWiFi();
}
void loop() {
delay(6000); // 60 second

float h1 = dht1.readHumidity();
float t1 = dht1.readTemperature();

String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
sendDebug(cmd);
delay(2000);
if( debug.find( "Error" ) )
{
Serial.print( "RECEIVED: Error\nExit1" );
return;
}

Serial.print("AT+CIPSEND=5");
delay(2000);
debug.print( "AT+CIPSEND=5" );
delay(2000);
Serial.print("\r\n");
debug.print( "\r\n" );

if(debug.find( ">" ) )
{
Serial.print(">");
Serial.print(t1);
Serial.print(" ");
Serial.print(h1);

Serial.print("AT+CIPCLOSE");
debug.print( "AT+CIPCLOSE");
}
else
{
debug.print( "AT+CIPCLOSE" );
}
if( debug.find("OK") )
{
Serial.println( "RECEIVED: OK" );
}
else
{
Serial.println( "RECEIVED: Error\nExit2" );
}

}
boolean connectWiFi()
{
debug.println("AT+CWMODE=1");
Wifi_connect();
}

void Wifi_connect()
{
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
sendDebug(cmd);
delay(2000);
Loding("Wifi_connect");
}
void Loding(String state){
for (int timeout=0 ; timeout<10 ; timeout++)
{
if(debug.find("OK"))
{
Serial.println("RECEIVED: OK");
break;
}
else if(timeout==9){
Serial.print( state );
Serial.println(" fail...\nExit2");
}
else
{
Serial.print("Wifi Loading...");
delay(500);
}
}
}
void sendDebug(String cmd)
{
Serial.print("SEND: ");
Serial.println(cmd);
debug.println(cmd);
}

CLIENT會送溫度及濕度,但AP端我先只收溫度,但LCD5110在AP端只會一直show 48.0,若我改 c = debug.read()-48 ; LCD5110只會一直show 0.0

謝謝大大鼎力相助...

Zonwee 提到...

請問,ESP8266只能夠用AT指令進行傳輸嗎?
我希望能達到一秒20筆資料的傳輸速度(資料形式為XXX.XX的浮點數)
但自己用兩個ESP做AT模式傳輸測試時,1秒一筆就已經會有資料遺漏,
所以在想是我使用方式錯誤,還是AT模式有其限制(速度過快),或有其他的傳輸方法?

小狐狸事務所 提到...

潘兄您好, AT 模式確實有頻寬限制, 因為它是透過序列埠傳遞, 需要時間等待對方回應. 或許可以試試看 NodeMCU, 但我沒用過.

Unknown 提到...
作者已經移除這則留言。
Unknown 提到...
作者已經移除這則留言。
Unknown 提到...

作者您好
請問ESP8266要傳DATA前一定要先發"AT+CIPSEND=X,X"的指令先告知接收端有多少個字元嗎?
請問有指令可以直接傳DATA嗎?
因為我想要用ESP8266在短時間連續傳DATA
但每次傳DATA都要發"AT+CIPSEND=X,X"有點太花時間了..
例如我在觸控板畫一條直線,一條直線有50筆位置資料(例如123 124 125....),要連續把這50筆資料傳給接收端
希望可以直接傳,而不是傳完一個"123",要在下指令才能傳"124"
謝謝!

小狐狸事務所 提到...

顏兄您好, 是喔, 用 AT 指令必須先傳送字元數才行. 或許可以試試看用 NodeMCU, 但我還沒測試過.

阿哲 提到...

Hi Tony大大,
感謝您的分享, 我在自製的舒肥機中因為您跟Jetter大大的分享而漸漸成形, 想請問的是: 上傳ThingSpeak跟接收網頁控制資訊能一併進行嗎??

目前當我的ESP8266在等著接收訊息時, 上傳ThingSpeak都會Error.

目前想做的動作是: 用溫度感測器感應水溫=>當到達設定溫度時(透過網頁進行溫度的設定)切斷加熱器並且每5秒將水溫上傳至ThingSpeak(用來確認加熱曲線).

請問當同時要進行時會不會衝突呢??

小狐狸事務所 提到...

嗯, 照理說一個是送, 一個是收, 感覺應該不會有問題才對, 但 Arduino 是顆小腦袋, 結構精簡, 它的序列埠緩衝器是很有限的 (預設好像是 64 Bytes), 送收若同時導致 conflict 是有可能的 (串列埠中斷). 詳細原因須對 AVR 硬體深入研究才知道. 不過您可以參考下面這篇文章, 試試看在傳送至 ThingSpeak 前用 noninterrupt() 指令來暫時禁止串列埠中斷, 傳送完再恢復, 印證一下猜測是否正確 :

noInterrupts();
//傳送至 ThingSpeak 的指令
interrupts();

小狐狸事務所 提到...

參考這篇 :

https://arduino.stackexchange.com/questions/9242/what-happens-if-an-interrupt-is-triggered-while-sending-data-via-serial

阿哲 提到...

謝謝Tony大大, 沒想到您隔天就回了, 我今天才回國, 等等回家立馬試試!!

Unknown 提到...

您好,
我是新手.
我有一個問題想請教, 如果今天我買了一個Nodemcu的板子, 如果說我用arduino去開發一個讀取溫度的程式,然後下載到控制板去,是不是會影響到原本燒錄在ESP8266的wifi功能?
謝謝指點!

小狐狸事務所 提到...

ESP8266 晶片的 WIFI 功能是透過韌體提供的 API 完成的, arduino 應該有提供操作 wifi 的函數. 不過若燒錄
ARDUINO 韌體進去, NodeMCU 裡面預燒的韌體 (Lua解譯器) 倒是會被覆蓋掉 (但可以自行下載燒回去). 任何寫入 ESP8266 的韌體都應該提供 WIFI 函數或指令, 不然就太浪費了.

Unknown 提到...

大大你好
我目前使用溫溼度上傳thingspeak出現一個問題,使用的模組為ESP8266+OLED-ssd1306+HTU21D+UNO

OLED-ssd1306+HTU21D+UNO OLED顯示沒問題

ESP8266+HTU21D+UNO 上傳數據也沒問題

ESP8266+OLED-ssd1306+HTU21D+UNO 全部兜起來後

OLED 出現白花花一片,UNO 監控視窗 不會傳送AT 程式如下


#include
#include "ESP8266.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#include
#include "HTU21D.h"
#include

#define _baudrate 9600
#define _rxpin 4
#define _txpin 5
#define OLED_RESET 13
Adafruit_SSD1306 display(OLED_RESET);
SoftwareSerial debug( _rxpin, _txpin ); // RX, TX
ESP8266 wifi(Serial);

HTU21D myHumidity;

//*-- IoT Information
#define SSID "Ice"
#define PASS "10131223"
#define IP "184.106.153.149" // ThingSpeak IP Address: 184.106.153.149
// 使用 GET 傳送資料的格式
// GET /update?key=[THINGSPEAK_KEY]&field1=[data 1]&filed2=[data 2]...;
String GET = "GET /update?key=OIJTQ90TDMBUHUHR";

void setup() {
myHumidity.begin();
Serial.begin(9600);
Serial.begin( _baudrate );
debug.begin( _baudrate );
sendDebug("AT");
delay(1000);
if(debug.find("OK"))
{
Serial.println("RECEIVED: OK\nData ready to sent!");
connectWiFi();
}
else{
Serial.println("NO RESEPONCE!");
}
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
display.clearDisplay();
}
void loop() {
delay(30000); // 60 second
int h = myHumidity.readHumidity();
int t = myHumidity.readTemperature();
SentOnCloud( int (t), int (h) );
OLED( int (t), int (h) );


}
void SentOnCloud( int T, int H )
{
// 設定 ESP8266 作為 Client 端
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
sendDebug(cmd);
if( debug.find( "Error" ) )
{
Serial.println( "RECEIVED: Error\nExit1" );
return;
}
cmd = GET + "&field1=" + T + "&field2=" + H +"\r\n";
debug.print( "AT+CIPSEND=" );
debug.println( cmd.length() );
if(debug.find( ">" ) )
{
Serial.print(">");
Serial.print(cmd);
debug.print(cmd);
}
else
{
debug.print( "AT+CIPCLOSE" );
}
if( debug.find("OK") )
{
Serial.println( "RECEIVED: OK" );
}
else
{
Serial.println( "RECEIVED: Error\nExit2" );
}
}
void sendDebug(String cmd)
{
Serial.print("SEND: ");
Serial.println(cmd);
debug.println(cmd);
}

boolean connectWiFi()
{
debug.println("AT+CWMODE=1");
delay(2000);
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
sendDebug(cmd);
delay(5000);
//cmd = "AT+CIFSR";
//sendDebug( cmd );

Serial.println(wifi.getLocalIP().c_str());
if(debug.find("OK"))
{
Serial.println("RECEIVED: OK");
return true;
}
else
{
Serial.println("RECEIVED: Error");
return false;
}
cmd = "AT+CIPMUX=0";
sendDebug( cmd );
if( debug.find( "Error") )
{
Serial.print( "RECEIVED: Error" );
return false;
}
}

void OLED (int T, int H){
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Temp:");
display.print(T);
display.println("C");
display.print("Humd:");
display.print(H);
display.println("%");
display.display();
display.clearDisplay();
delay(2000);
}

請問程式方面有問題嗎??請幫忙指點一下 謝謝

小狐狸事務所 提到...

Sorry, 沒實作實在不清楚問題在哪. OLED 都沒顯示可能要先檢查硬體接線, 我自己常遇到麵包板與杜邦線接觸不良問題. 建議您開啟序列埠監控視窗看看 setup() 的輸出有出來嗎? Debug 要充分利用輸出訊息一步步看程式死在那裡.

Unknown 提到...
作者已經移除這則留言。
Unknown 提到...

今日無意間發現問題了,一直沒有好好仔細的看編譯完後的訊息。原來動態記憶體被使用到94%
後面把一些雜七雜八與序列傳輸的部份加上 F(),節省之後 降到84% 就一切正常了。

OLED的部分用掉太誇張,底子還不夠不知道函示庫那些東西可以刪除節省掉,不然可以在省下更多空間。

小狐狸事務所 提到...

94% 也太誇張了, 我用 WIFI 操到 70% 以上就不太穩.

不要憐惜她 提到...

老師您好 我的問題無法新增在這裡會顯示您的 HTML 不被接受: 不允許使用的標記: HTML 故能否用email交流?
我的email為gosick223345@gmail.com 謝謝您

小狐狸事務所 提到...

我 email : tony1966@ms5.hinet.net

Unknown 提到...

您好:我依您的線路圖與程式,一步一步的試,以realterm可經ESP01將資訊傳送至thingspeak。發訊號時ESP01版藍燈會閃。
但以ESP01+NANO將資訊傳送至thingspeak時,thingspeak無回應(表示無新訊息進來),而ESP01版藍燈不會閃。重新接過D10/D11迴路後,仍無法使ESP01版閃藍燈。會不會是SoftwareSerial.h版本的問題?

小狐狸事務所 提到...

Dear Paul :
應該不是 SoftwareSerial.h 的問題, 前輩們寫的函式庫千錘百鍊, 我用到現在從未發現它們有問題. 實驗失敗主要問題大致不出下列幾個 :

1.接線有誤
2.接觸不良
3.零件燒毀
4.程式有 BUG

實務上 ESP01+NANO 不是個好主意, 太委屈 ESP8266 了, 它本身就比 Arduino 運算能力強, 只是類比方面比較弱.

Unknown 提到...
作者已經移除這則留言。
Unknown 提到...

老師您好 請問我如果要把thinkspeak的資料導回mysql的資料庫要如何製作呢?

小狐狸事務所 提到...

你可以在 Data input/Output 頁籤看到 channel 的 json 輸出連結, 可以用 PHP 去讀取此 JSON 例如 :

{"channel":{"id":BLABLA,"name":"Atmosphere","description":"氣候觀測資料","latitude":"0.0","longitude":"0.0","field1":"Temperature ( degC )","field2":"Temperature ( degF )","field3":"Humidity ( % )","field4":"Luminance (%)","field5":"TriggerCount","created_at":"2015-07-22T01:12:05Z","updated_at":"2017-09-16T13:29:54Z","last_entry_id":null},"feeds":[]}

解析 JSON 就可以得到裡面的資料, 再寫到 MySQL 中即可. 搜尋 php+mysql 用法可找到很多資料.

Unknown 提到...

Tony Huang 大大您好,小弟看到您的文章真心覺得真是太厲害了,但我對nodemcu跟uno版的接收有一些問題,不知道可否請教你一下,我的gmail:b123563833@gmail.com,謝謝了!!

小狐狸事務所 提到...

您好, 若有疑問可直接 po 在此處, 我盡我能力回答, 不方便的話請 mail 到 tony1966@ms5.hinet.net.

Unknown 提到...

大大您好,我是b123563833@gmail.com的那個人,我沒直接提出來是因為程式有點多,網站那邊不讓我直接上傳,如果有打擾到您那真是太對不起了!!還有真是抱歉這麼慢回你!!這幾天都在忙別的事...

正文:

小弟我有一快nodemcu esp8266 跟一個arduino uno,還有一個三軸加速度感測器ADXL335,我目前是把三軸接到UNO上面,因為nodemcu只有一個analog而已...我希望如果三軸加速度感測器的x超過某個範圍的話就傳送一個Y字元給nodemcu,再經由nodemcu上的esp8266上傳到ThingSpeak上面,但是我怎麼測都不會成功,我程式是寫說x<=300的話就傳到ThingSpeak2,如果沒的話則傳1,但我現在不管怎麼樣他都只會傳1,不知道是怎麼了,對了,我的nodemcu的電源是直接接uno的

程式如下:

ARDUINO UNO :程式我還有寫其他的東西有點亂,還請見諒...
#include  
#define TRIGGER_PIN 12 // 定義模組triger端為數位接腳12
#define ECHO_PIN 11 // 定義模組echo端為數位接腳11
int spk=13; // 定義揚聲器為數位接腳13
Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN); //設定HC-SR04初始化參數
#define X_PIN A0
#define Y_PIN A1
#define Z_PIN A2
void setup()
{
Serial.begin(9600);
pinMode(spk, OUTPUT);
// 注意,在呼叫analogRead之前必須先呼叫analogReference
pinMode(7,OUTPUT);
}


void loop()
{
ggg();
delay(500);
xyz();
delay(500);
}





void xyz()
{
int x = analogRead(X_PIN);
int y = analogRead(Y_PIN);
int z = analogRead(Z_PIN);

Serial.print("X: ");
Serial.print(x);
Serial.print(", Y: ");
Serial.print(y);
Serial.print(", Z: ");
Serial.print(z);
Serial.print('\n');
if (x<=300)
{
digitalWrite(7, 1);
Serial.write('Y'); //先對 TX 送出字元 Y TX/RX RX/TX ESP8266GND要接UNOGND
}
else
{
digitalWrite(7, 0);
Serial.write('K');
}
delay(100);
}









void ggg()
{
float cmMsec; // 定義浮動數
long microsec = ultrasonic.timing(); //  測距,返回的是一個時間單位(microsec)



cmMsec = ultrasonic.convert(microsec,Ultrasonic::CM); //將測得的時間單位計算為距離單位
Serial.print(" CM: ");
Serial.println(cmMsec);




if( cmMsec >= 80 && cmMsec <= 100){ // 假設距離介於80~100之間
for(int i = 0; i < 12000; i++) // 迴圈重複
digitalWrite(spk, 0);
digitalWrite(spk, 1);
delay(300);



}
else if (cmMsec >= 60 && cmMsec <= 79){ // 假設距離介於60~79之間
for(int i = 0; i < 12000; i++) // 迴圈重複
digitalWrite(spk, 1);

digitalWrite(spk, 0);
delay(100);



}
else if (cmMsec >= 40 && cmMsec <= 59){ // 假設距離介於40~59之間
for(int i = 0; i < 12000; i++) // 迴圈重複
digitalWrite(spk, 1);

digitalWrite(spk, 0);
delay(50);
}
else if (cmMsec >= 30 && cmMsec <= 39){ // 假設距離介於30~39之間
for(int i = 0; i < 12000; i++) // 迴圈重複
digitalWrite(spk, 1);
digitalWrite(spk, 0);
delay(20);
}
else if (cmMsec >= 20 && cmMsec <= 29){ // 假設距離介於20~29之間
for(int i = 0; i < 6000; i++) // 迴圈重複
digitalWrite(spk, 1);

digitalWrite(spk, 0);
delay(10);



}
else if (cmMsec <19){ // 假設距離小於19

digitalWrite(spk, 1);


delay(10);



}
else
digitalWrite(spk, 0);

}

Unknown 提到...

NODEMCU ESP8266的:
#include
int u = 1 ;
//*-- Hardware Serial
//#define _baudrate 9600


//*-- IoT Information
#define SSID "MY SSDI" //這是我把它拿掉的
#define PASS "MY PWD" //這是我把它拿掉的
#define HOST "api.thingspeak.com" // ThingSpeak IP Address: 184.106.153.149
#define PORT 80
// 使用 GET 傳送資料的格式
// GET /update?key=[THINGSPEAK_KEY]&field1=[data 1]&filed2=[data 2]...;
String GET = "GET /update?key=T2O7II4RQVFLCW2T";

void setup()
{
Serial.begin(9600);
//Serial.begin( _baudrate );
Serial.println( "ESP8266 Ready!" );
// Connecting to a WiFi network
Serial.print("Connect to ");
Serial.println( SSID );
WiFi.begin( SSID, PASS );
// 持續等待並連接到指定的 WiFi SSID
while( WiFi.status() != WL_CONNECTED )
{
delay(500);
Serial.print( "." );
}
Serial.println( "" );

Serial.println( "WiFi connected" );
Serial.println( "IP address: " );
Serial.println( WiFi.localIP() );
Serial.println( "" );

delay(2000);
}

void loop()
{
Serial.println (u);
Serial.println ('\n');
//while (!Serial.available()) {} //檢查 RX 緩衝區, 直到有資料進來
if (Serial.read()=='Y') //若收到字元 Y,
{
u = 2 ;
update878();
}
else
{
u = 1 ;
update878();
}
delay( 500 ); // 0.5 second
}

void update878()
{
// 設定 ESP8266 作為 Client 端
WiFiClient client;
if( !client.connect( HOST, PORT ) )
{
Serial.println( "connection failed" );
return;
}
else
{
// 準備上傳到 ThingSpeak IoT Server 的資料
// 已經預先設定好 ThingSpeak IoT Channel 的欄位
// field1:溫度;field2:濕度
String getStr = GET + "&field1=" + String((int)u) +

" HTTP/1.1\r\n";;
client.print( getStr );
client.print( "Host: api.thingspeak.com\n" );
client.print( "Connection: close\r\n\r\n" );

delay(10);
//
// 處理遠端伺服器回傳的訊息,程式碼可以寫在這裡!
//


client.stop();
}
}
因為有字數最多限制,所以我分了兩組傳
大致上就是這樣了,還請您多多幫忙了...
敬祝 平安 喜樂 一切順心

小狐狸事務所 提到...

可考慮使用 ESP32, 它有許多 Analog 輸入.

小狐狸事務所 提到...

用 GET 傳資料時要注意 % ? 等特殊符號問題, 必須跳脫否則後面的資料會斷掉. 等手邊有 ADX 再來實測.

Gordon 提到...

您好,我想把thingspeak改成用line notify 但是網路都找不到教程,請問該如何修改呢?

小狐狸事務所 提到...

嗨 Gordon, 這個項目早已在我的學習計畫中, 但卻一直還找不到空檔來做實驗, 市面上有幾本介紹作法的書籍, 回頭我寫個書名給您參考.

Gordon 提到...

好的謝謝您,我是想直接在esp8266燒錄程式,然後接收來自arduino的tx訊號,esp8266讀到arduino的溫度訊號,上傳至line(我已用nodemcu做出這個功能)