我拿出上一版的佈線圖, 仔細端詳後, 發現模式切換開關上面還有空位可以擠進 2*1 的針腳座, 但佈線需做局部更動, 正面還需加焊一條跳線將 3.3V 引出來. 參考 :
# 製作 Arduino Nano + ESP8266 物聯網模組 (三)
修改後的佈線圖如下 :
正面
反面
圖例 : 橘色為正面跳線 (使用細包覆線), 藍色為反面焊接線, 綠色為電阻兩端金屬線. AMS1117 是焊在反面.
我把已經在使用的一塊板子拿來修改, 加焊一個 2*1 針腳與一條跳線, 測試 OK. 接下來我想是不是要把 GPIO0 接出來, 看看此模組能不能取代 USB-TTL 轉換線, 直接燒錄 ESP8266 的韌體 (GPIO0 要接地). 不過要先測試看看是否可行, 如果可以的話, 還可以再放一個 2*1 針腳來控制 GPIO0 的準位, 工作模式為 HIGH (3.3V), 燒錄模式為 LOW.
2016-07-12 補充 :
晚上進行了 IOT 模組是否能取代 USB-TTL 轉換線的實驗, 我使用了最早製作的 ESP8266 轉換板來模擬 IOT 模組, 並將其 GPIO0 接地. 然後拆封了一顆新的 ESP-01 模組來測試, 其韌體版本比較新, 不是最穩的 0.9.2 版 (是 0.9.5 版), 其預設速率是 115200. 我把 IOT 模組設在工作模式, 並且上傳了簡單的軟體串列埠送收程式 (loop 中) :
if (esp8266.available()) {Serial.write(esp8266.read());}
//send char to ESP8266 if got char from serial monitor window
if (Serial.available()) {esp8266.write(Serial.read());}
結果是失敗, 不論用 Arduino IDE 序列埠監控視窗還是 Realterm 在任何速率都沒反應, 直接用韌體更新程式也顯示 connection failed. 我想可能是因為 Arduino 串列埠速率固定是 9600 之故. 所以透過軟體序列埠轉送燒錄訊息至 ESP8266 的想法是錯誤的, 上面的佈線圖就是此模組的最終更新了, 不需要再把 GPIO0 接出來了.
另外記一下我在九乘九買到的富士 A108 三秒膠 (特價 19 元), 免得忘記是哪一款 :
這款封裝設計得不錯, 放了一陣子還是很容易打開, 不像之前買的 10 元傳統三秒膠, 使用前必須用美工刀削掉管嘴尖端, 放了幾天就無法旋開蓋子 (久沒用就整個乾掉囉), 逼得我只好暴力破壞, 但這麼一來整管都必須用掉, 但實際上我只要用一點點, 換句話說整條都報廢了. 這個富士的就不會這樣, 雖然貴一點也值得.
三秒膠在焊接前固定元件蠻好用的, 但是要注意不要擠太多, 用一點點可以稍微固定即可, 擠太多若滲入元件內部就不妙了, 特別是滑動開關與排母, 三秒膠若進到裡面, 滑動開關就固化無法滑動, 排母就插不進去了.
2016-08-13 補充 :
為了優化記憶體耗用情形, 我把 IOT 模組的程式架構用 F() 函數將字串常數放到 Flash, 最新程式如下 :
#include <SoftwareSerial.h>
#define DEBUG true
//-----application include & def listed HERE-----
//system use please do not edit
SoftwareSerial esp8266(7,8); //(RX,TX)
const int SW_PIN=4; //Pin to switch configuration or working mode
const int MAX_PAGE_NAME_LEN=48; //buffer size
char buffer[MAX_PAGE_NAME_LEN + 1]; //store page_name/ssid/pwd
int mode; //store current mode(LOW=wifi setup, HIGH=working)
//-----application global variables listed HERE-----
void setup() {
//system use please do not edit
Serial.begin(9600);
esp8266.begin(9600);
sendData(F("AT+RST\r\n"),2000,DEBUG); // reset ESP8266
pinMode(SW_PIN, INPUT);
mode=digitalRead(SW_PIN);
sendData(F("AT+GMR\r\n"),1000,DEBUG);
if (mode==LOW) { //setup mode : for wifi configuration
sendData(F("AT+CWMODE=3\r\n"),1000,DEBUG); //configure as access point
sendData(F("AT+CIPMUX=1\r\n"),1000,DEBUG); //enable multiple connections
sendData(F("AT+CIPSERVER=1,80\r\n"),2000,DEBUG); //turn on server 80 port
}
else { //working mode : for running application
sendData(F("AT+CWMODE=1\r\n"),1000,DEBUG); //configure as a station
delay(3000); //wait for wifi connection to get local ip
}
sendData(F("AT+CIFSR\r\n"),1000,DEBUG); //get ip address
//-----application setup codes listed HERE-----
}
void loop() {
if (mode==LOW) {setupWifi();} //system use please do not edit
else {
//-----application loop codes listed HERE-----
}
}
void setupWifi() { //system use please do not edit
if (esp8266.available()) { // check if the esp is sending a message
if (esp8266.find("+IPD,")) {
delay(1000);
//esp8266 link response : +IPD,0,498:GET / HTTP/1.1
//retrieve connection ID from response (0~4, after "+IPD,")
int connectionId=esp8266.read()-48; //from ASCII to number
//subtract 48 because read() returns ASCII decimal value
//and in ASCII, "0" (the first decimal number) starts at 48
if (esp8266.find("GET /")) { //retrieve page name (router)
memset(buffer, 0, sizeof(buffer)); //clear buffer (all set to 0)
if (esp8266.readBytesUntil('/', buffer, sizeof(buffer))) {
if (strcmp(buffer, "update") == 0) { //update wifi
//"?ssid=aaa&pwd=bbb HTTP/1.1"
esp8266.find("?ssid="); //skip ssid token
memset(buffer, 0, sizeof(buffer)); //clear buffer (all set to 0)
esp8266.readBytesUntil('&', buffer, sizeof(buffer)); //retrieve ssid
String ssid=buffer;
esp8266.find("pwd="); //skip pwd token
memset(buffer, 0, sizeof(buffer)); //clear buffer (all set to 0)
esp8266.readBytesUntil(' ', buffer, sizeof(buffer)); //retrieve pwd
String pwd=buffer;
//configure as a station
String res=sendData("AT+CWJAP=\"" + ssid + "\",\"" + pwd + "\"\r\n",6000,DEBUG);
//show setup result
String webpage=F("<html>Wifi setup ");
if (res.indexOf("OK") != -1) {webpage += F("OK!</html>");}
else {webpage += F("Failed!</html>");}
String cipSend=F("AT+CIPSEND=");
cipSend += connectionId;
cipSend += F(",");
cipSend += webpage.length();
cipSend += F("\r\n");
sendData(cipSend,1000,DEBUG);
sendData(webpage,2000,DEBUG);
String closeCommand=F("AT+CIPCLOSE=");
closeCommand += connectionId; // append connection id
closeCommand += F("\r\n");
sendData(closeCommand,3000,DEBUG);
}
else { //show setup page
String webpage=F("<html><form method=get action='/update/'>SSID ");
webpage += F("<input name=ssid type=text><br>");
String cipSend=F("AT+CIPSEND=");
cipSend += connectionId;
cipSend += F(",");
cipSend += webpage.length();
cipSend += F("\r\n");
sendData(cipSend,1000,DEBUG);
sendData(webpage,2000,DEBUG);
webpage=F("PWD <input name=pwd type=text> ");
cipSend=F("AT+CIPSEND=");
cipSend += connectionId;
cipSend += F(",");
cipSend += webpage.length();
cipSend += F("\r\n");
sendData(cipSend,1000,DEBUG);
sendData(webpage,2000,DEBUG);
webpage=F("<input type=submit value=Connect></form></html>");
cipSend = F("AT+CIPSEND=");
cipSend += connectionId;
cipSend += F(",");
cipSend += webpage.length();
cipSend += F("\r\n");
sendData(cipSend,1000,DEBUG);
sendData(webpage,2000,DEBUG);
String closeCommand =F("AT+CIPCLOSE=");
closeCommand += connectionId; // append connection id
closeCommand += F("\r\n");
sendData(closeCommand,3000,DEBUG);
}
}
}
}
}
}
String sendData(String command, const int timeout, boolean debug) {
String response="";
esp8266.print(command); // send the read character to the esp8266
long int time=millis();
while ((time+timeout) > millis()) {
while(esp8266.available()) {
// The esp has data so display its output to the serial window
char c=esp8266.read(); // read the next character.
response += c;
}
}
if (debug) {Serial.print(response);}
return response;
}
編譯後記憶體耗用如下 :
草稿碼使用了 9,278 bytes (30%) 的程式存儲空間。最大值為 30,720 bytes。
全域變數使用了 412 bytes (20%) 的動態記憶體,剩餘 1,636 bytes 供局部變數。最大值為 2,048 bytes 。
與優化之前的 35% 相比, 全域變數節省了 15%, 真是太驚人了! 而代價僅僅是 Flash 程式從 29% 提升為 30% 而已, 非常值得. 參考 :
# 製作 Arduino Nano + ESP8266 物聯網模組 (三)
此 IOT 模組電路圖如下 :
若懶得焊接板子, 可以照上面電路圖自行用麵包板接線, 只不過 AMS1117 不是 DIP 封裝, 沒辦法插入麵包板, 比較麻煩而已.
沒有留言 :
張貼留言