2017年4月13日 星期四

[NodeMCU] 雲端飼料機完整做法大公開

今天來和大家分享一下雲端飼料機的完整做法和介紹, 包含了NodeMCU的程式碼, 有興趣的人可以自己DIY看看

把電源接上NodeMCU天線旁的LED會開始閃爍, 代表正在連線中, 但是因為是第一次, 沒有儲存任何WiFi設定資料, 所以一定連不上, 約15秒後(timeout)會自動轉為AP Mode, 這時用你的PC或手機可看到下圖FeedAP這個WiFi 存取點, 連上它時需要輸入密碼, 目前預設為12345678




連上FeedAP後, 在網址列輸入192.168.4.1按Enter

就會看到目前可連線的WiFi存取點, 在下方的SSID欄位和PASSWORD欄位輸入你想連線的WiFi資料後按儲存並自動連線, 若看不到你想連線的WiFi存取點, 則可按左下方的重新掃瞄周邊無線網路, 應該就能看到, 若還是看不到, 則要確認AP電源有沒有打開或設定有沒有問題

按下儲存並自動連線後, 按ModeMCU的Reset鈕後, 即會自動嘗試連線15秒

連上後, 找到NodeMCU連上的IP, NodeMCU也沒接螢幕, 那要怎麼找IP呢? 我是利用arduino ide裡UART視窗來得到IP, 因為程式裡有把連上的IP送到UART來, 如下圖ip是192.168.11.11連上後可看到如下畫面, 若連不上需確認PC和NodeMCU是否在同一個網域, 簡單介紹一下, 點心就是份量比較少, 正餐就是份量多一點, 其它看字面上的意思應該就能懂



控制板就NodeMCU這樣, 沒有任何其它的東西, 排線是接到MG995, 旁邊的電容只是希望減少MG995啟動時造成的壓降

點心的份量如下

正餐的份量如下

整個機構構造如下, 3D機構檔案有需要的話, 我再把它分享出來

STL檔案連結如下, 請自行下載
MG995支架
漏斗上蓋
加量上蓋
轉軸
外盒1
外盒2



完整程式碼如下

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <ESP8266mDNS.h>
#include <Servo.h>

Servo myservo;

const char* host = "Feed";
const char* ssid = "FeedAP";
const char* passphrase = "12345678";

String content;                
String st;                    
int statusCode;
int status = WL_IDLE_STATUS;  
char charBuf[32];              

#define WiFi_Status_LED   D4    

String ReceiveString = "";
bool ReceiveFinish = 0;
String InsString = "";

bool debug = 1;

byte ipTypeAddr                  = 200;
byte SSID_Start_Addr             = 4;
byte SSID_End_Addr               = 36;
byte PW_Start_Addr               = 36;
byte PW_End_Addr                 = 100;
byte FixedIP_Start_Addr          = 201;
byte FixedIP_End_Addr            = 216;
byte FixedIP_Gateway_Start_Addr  = 221;
byte FixedIP_Gateway_End_Addr    = 236;

ESP8266WebServer server(80);  

void setup() {
  WiFi.disconnect();                                          
  WiFi.mode(WIFI_OFF);                                        
  delay(100);
  WiFi.mode(WIFI_STA);                                        
  pinMode(WiFi_Status_LED, OUTPUT);                            
  digitalWrite(WiFi_Status_LED, HIGH);                        
  Serial.begin(115200);
  EEPROM.begin(512);                                        
  pinMode(D2, OUTPUT);


  if (debug) {
    if (debug) Serial.println();
    if (debug) Serial.println("The program startup...");
  }
  LoginWiFi();                                                
}

void LoginWiFi() {
  if (debug) Serial.println("Reading EEPROM SSID (MAX=32 BYTE)");
  String essid = "";
  for (int i = SSID_Start_Addr; i < SSID_End_Addr; ++i)                
  {
    if (EEPROM.read(i) == 0) {                                      
      break;
    }
    else {
      essid += char(EEPROM.read(i));
    }
  }
  if (debug) {
    Serial.print("SSID NAME : ");
    Serial.println(essid);
  }

  if (debug) Serial.println("Reading EEPROM PASSWORD (MAX=64 BYTE)");    
  String epassword = "";
  for (int i = PW_Start_Addr; i < PW_End_Addr; ++i)
  {
    if (EEPROM.read(i) == 0) {                                      
      break;
    }
    else {
      epassword += char(EEPROM.read(i));
    }
  }

  if (debug) {
    Serial.print("PASSWORD NAME : ");
    Serial.println(epassword);
  }

  char iptype = EEPROM.read(ipTypeAddr);                                        
  if (debug) {
    Serial.print("EEPROM ip type = ");
    Serial.println(iptype);
  }

  if (iptype == 'F') {                                                              
    if (debug) Serial.println("use Fixed IP");
    String UserIP = "";
    for (int i = 0; i < 16; ++i) {                                                  
      if (EEPROM.read(FixedIP_Start_Addr + i) == 0) {                            
        break;
      }
      else UserIP += char(EEPROM.read(FixedIP_Start_Addr + i));                  
    }
    if (debug) {
      Serial.print("User want to use Fixed IP = ");
      Serial.println(UserIP);
    }
    String UserGateway = "";
    for (int i = 0; i < 16; ++i) {                                                  
      if (EEPROM.read(FixedIP_Gateway_Start_Addr + i) == 0) {                    
        break;
      }
      else UserGateway += char(EEPROM.read(FixedIP_Gateway_Start_Addr + i));    
    }
    if (debug) {
      Serial.print("User want to use Fixed IP Gateway= ");
      Serial.println(UserGateway);
    }

    String iparray[4] = { "", "", "", "" };                                        
    UserIP += ".";                                                                
    for (byte i = 0; i < 4; i++) {
      byte w = UserIP.indexOf(".");                                                
      if (debug) {
        Serial.print("find w(,) on = ");
        Serial.println(w);
      }
      iparray[i] = UserIP.substring(0, w);                                        
      if (debug) {
        Serial.print("iparray = ");
        Serial.println(iparray[i]);
      }
      UserIP = UserIP.substring(w + 1, UserIP.length());                          
      if (debug) {
        Serial.print("UserIP string = ");
        Serial.println(UserIP);
      }
    }

    String gwarray[4] = { "", "", "", "" };                                        
    UserGateway += ".";                                                            
    for (byte i = 0; i < 4; i++) {
      byte w = UserGateway.indexOf(".");                                          
      if (debug) {
        Serial.print("find w(,) on = ");
        Serial.println(w);
      }
      gwarray[i] = UserGateway.substring(0, w);                                    
      if (debug) {
        Serial.print("gwarray = ");
        Serial.println(gwarray[i]);
      }
      UserGateway = UserGateway.substring(w + 1, UserGateway.length());            
      if (debug) {
        Serial.print("UserGateway string = ");
        Serial.println(UserGateway);
      }
    }

    IPAddress ip(iparray[0].toInt(), iparray[1].toInt(), iparray[2].toInt(), iparray[3].toInt());        
    IPAddress gateway(gwarray[0].toInt(), gwarray[1].toInt(), gwarray[2].toInt(), gwarray[3].toInt());  
    IPAddress subnet(255, 255, 255, 0);                                                                  

    WiFi.mode(WIFI_STA);
    WiFi.config(ip, gateway, subnet, gateway);
    delay(100);
    WiFi.hostname("WiFiBox_FixedIP");
    WiFi.begin(essid.c_str(), epassword.c_str());                          
  }
  else {
    if (debug) Serial.println("use Random IP");
    WiFi.mode(WIFI_STA);
    WiFi.hostname("WiFiBox_RandomIP");
    WiFi.begin(essid.c_str(), epassword.c_str());                          
  }

  if (TryToLoginWiFi()) {
    launchWeb(0);                                                        
    return;                                                              
  }
  SetupToAPMode();                                                        
}

void SetupToAPMode(void) {
  ScanNetwork();                                              
  WiFi.softAP(ssid, passphrase, 9, 0);                        
  if (debug) Serial.println("Soft AP Starting...");
  launchWeb(1);                                                
  if (debug) {
    Serial.println("");
    Serial.print("Please connect to ");
    Serial.print(ssid);
    Serial.println(" WiFi rounter first");
    Serial.println("");
    Serial.println("The End.");
  }
}

bool TryToLoginWiFi(void) {
  /* WiFi連線的狀態碼
  WL_NO_SHIELD = 255,
  WL_IDLE_STATUS = 0,
  WL_NO_SSID_AVAIL = 1
  WL_SCAN_COMPLETED = 2
  WL_CONNECTED = 3
  WL_CONNECT_FAILED = 4
  WL_CONNECTION_LOST = 5
  WL_DISCONNECTED = 6
  */
  int c = 0;                                                              
  if (debug) Serial.println("Waiting for Wifi to connect...");

  while ( c < 15 ) {
    if (WiFi.status() == WL_CONNECTED) {
      return true;                                                        
    }
 
    delay(500);
    digitalWrite(WiFi_Status_LED, LOW);
    delay(500);
    digitalWrite(WiFi_Status_LED, HIGH);
    if (debug) Serial.print(WiFi.status());                                
    c++;
  }
  if (debug) {
    Serial.println("");
    Serial.println("Connect timed out, ESP8266 change to AP mode");
  }
  return false;
}

void launchWeb(int webtype) {
  if (debug) Serial.println("");
  if (webtype) {                  
    char SoftAP[16];
    sprintf(SoftAP, "%d.%d.%d.%d", WiFi.softAPIP()[0], WiFi.softAPIP()[1], WiFi.softAPIP()[2], WiFi.softAPIP()[3]);
    if (debug) Serial.println("Operation in AP Mode.");
    if (debug) Serial.print("SoftAP IP: ");
    if (debug) Serial.println(WiFi.softAPIP());                                                                      
    if (debug) Serial.println("Write IP Type(ipTypeAddr) = R");
    EEPROM.write(ipTypeAddr, 'R');                                                                                        
    EEPROM.commit();                                                                                              
    delay(100);
    if (debug) {
      Serial.print("IP Type(ipTypeAddr) = ");
      Serial.println(char(EEPROM.read(ipTypeAddr)));
    }
  }
  else                              
  {
    char LocalIP[16];
    sprintf(LocalIP, "%d.%d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);    
    if (debug) Serial.println("");
    if (debug) Serial.println("WiFi connected.");
    if (debug) Serial.print("Local IP: ");
    if (debug) Serial.println(WiFi.localIP());                                    
    digitalWrite(WiFi_Status_LED, LOW);                                            
    delay(500);
  }

  if (debug) Serial.println("Create Web Server...");
  createWebServer(webtype);                                                      
  server.begin();                                                                
  if (debug) Serial.println("Server started");
}

void createWebServer(int webtype)
{
  if ( webtype == 1 ) {          
    server.on("/", []() {
      IPAddress ip = WiFi.softAPIP();
      content = "<!DOCTYPE HTML><html><title>雲端飼料機WiFi設定</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><p>     你好, 請輸入您的無線網路設定</p>";
      content += st;    
      content += "<br>";
      content += "<form method='get' action='setting'>";
      content += "<table border=\"0\">";
      content += "<table border=\"0\"><tr><td><label>SSID</label></td><td><input type=\"text\" placeholder=\"請輸入要連接的SSID\" name='ssid' maxlength=32 size=64></td></tr>";
      content += "<tr><td><label>PASSWORD</label></td><td><input type=\"text\" placeholder=\"請輸入要連接的密碼\" name='pass' maxlength=64 size=64></td></tr></table>";
      content += "<input type=\"button\" value=\"重新掃瞄周邊無線網路\" onclick=\"self.location.href='/rescannetwork'\">";
      content += "&nbsp;&nbsp;&nbsp;<input type='reset' value=\"重設\">&nbsp;&nbsp;&nbsp;<input type='submit' value=\"儲存並自動連線\"></form></html>";
      server.send(200, "text/html", content);
    });

    server.on("/rescannetwork", []() {
      content = "<!DOCTYPE HTML><html><title>雲端飼料機WiFi設定</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><p>重新掃瞄無線網路中...</p>";
      content += "<Meta http-equiv=\"ReFresh\" Content=\"5; URL='/'\">";
      server.send(200, "text/html", content);
      ScanNetwork();
    });

      server.on("/setting", []() {
      String qsid = server.arg("ssid");                                
      String qpass = server.arg("pass");                                

      if (qsid.length() > 0 && qpass.length() > 0) {                    
        if (debug) Serial.println("clearing eeprom");
        for (int i = 4; i < 100; ++i) {
          EEPROM.write(i, 0);                                        
        }
        EEPROM.commit();
        delay(100);
        if (debug) Serial.println("writing eeprom ssid:");
        for (int i = 0; i < qsid.length(); ++i)                        
        {
          EEPROM.write(4 + i, qsid[i]);
          if (debug) Serial.print("Wrote: ");
          if (debug) Serial.println(qsid[i]);
        }
        EEPROM.commit();
        delay(100);
        if (debug) Serial.println("writing eeprom pass:");
        for (int i = 0; i < qpass.length(); ++i)                      
        {
          EEPROM.write(36 + i, qpass[i]);
          if (debug) Serial.print("Wrote: ");
          if (debug) Serial.println(qpass[i]);
        }
        EEPROM.commit();                                            
        delay(100);

        content = "<!DOCTYPE HTML>\r\n<html>";
        content += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
        content += "<title>雲端飼料機WiFi設定</title>";
        content += "<p>儲存WiFi設定成功, 請手動關閉網頁並等待雲端飼料機重新啟動...</p>";
        content += "</html>";
        server.send(200, "text/html", content);
      }
      else {
        content = "<!DOCTYPE HTML>\r\n<html>";
        content += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
        content += "<title>雲端飼料機WiFi設定</title>";
        content = "<p>輸入錯誤!!!SSID或PASSWORD欄位不能是空白, 按上一頁重新輸入</p>";
        content += "<input type=\"button\" value=\"上一頁\" onclick=\"self.location.href='/'\"></html>";
        statusCode = 404;
        if (debug) Serial.println("Sending 404");
      }
      server.send(statusCode, "text/html", content);
    });
  }
  else if (webtype == 0) {                    
    server.on("/", []() {
      char LocalIP[16];
      sprintf(LocalIP, "%d.%d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
      content = "<!DOCTYPE HTML><html><title>雲端飼料機控制網頁</title>";
      content += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
      content += "<Meta http-equiv=\"ReFresh\" Content=\"60; URL='/'\">";
      content += "<form method=\"get\" action=\"setip\" name=\"reg\" style=\"margin-bottom: 20px\">";
      content += "目前雲端飼料機 IP : ";
      content += LocalIP;
      content += "<br><br>";
      content += "IP型式設定<br>";
      content += "<input type=\"radio\" name=\"IPTYPE\" value=\"RandomIP\" checked> 隨機IP<br>";
      content += "<input type=\"radio\" name=\"IPTYPE\" value=\"FixedIP\"> 固定IP(請填下方IP欄位)<br>";
      content += "固定IP位址<br>";
      content += "<input type=\"text\" name=\"IPS\" size=\"16\"><br>";
      content += "閘道器IP位址<br>";
      content += "<input type=\"text\" name=\"GWS\" size=\"16\"><br>";
      content += "<p><input type=\"submit\" style=\"width:200px;height:40px;font-size:20px;\" value=\"送出\"></p>";
      content += "<br><br>";
      content += "<input type=\"button\" value=\"點心\" style=\"width:200px;height:40px;font-size:20px;\" onclick=\"self.location.href='/Feed/On/Small'\">";
      content += "<br><br>";
      content += "<input type=\"button\" value=\"正餐\" style=\"width:200px;height:40px;font-size:20px;\" onclick=\"self.location.href='/Feed/On/Standard'\">";
      content += "<br><br>";
      content += "</form>";
      content += "若要清除無線網路設定, 請按下方的清除無線網路設定按鈕<br>";
      content += "<input type=\"button\" value=\"清除無線網路設定\" style=\"width:200px;height:40px;font-size:20px;\" onclick=\"self.location.href='/cleareeprom'\"></html>";
      server.send(200, "text/html", content);
    });

    server.on("/setip", []() {                                              
      String IPTYPE = server.arg("IPTYPE");
      String IPS = server.arg("IPS");                                        
      String GWS = server.arg("GWS");                                        

      Serial.print("IPTYPE = "); Serial.println(IPTYPE);
      Serial.print("IPS = "); Serial.println(IPS);
      Serial.print("GWS = "); Serial.println(GWS);

      for (int i = 0; i < 36; ++i) {
        EEPROM.write(200 + i, 0);                                            
      }
      EEPROM.commit();                                            
      delay(100);

      Serial.println("Clear EEPROM Address 200~216");
      if (IPTYPE.equals("FixedIP")) EEPROM.write(ipTypeAddr, 'F');
      if (IPTYPE.equals("RandomIP")) EEPROM.write(ipTypeAddr, 'R');
      EEPROM.commit();                                            
      delay(100);
      Serial.print("IPTYPE(ipTypeAddr) = "); Serial.println(char(EEPROM.read(ipTypeAddr)));

      if (debug) Serial.println("writing fixed ip adress :");
      for (int i = 0; i < IPS.length() ; i++)                                  
      {
        EEPROM.write(201 + i, IPS[i]);
        if (debug) Serial.print("Wrote: ");
        if (debug) Serial.println(IPS[i]);
      }
      EEPROM.commit();
      delay(100);    
      for (int i = 0; i < GWS.length() ; i++)                                  
      {
        EEPROM.write(221 + i, GWS[i]);
        if (debug) Serial.print("Wrote: ");
        if (debug) Serial.println(GWS[i]);
      }
      EEPROM.commit();                                            
      delay(100);

      content = "<!DOCTYPE HTML>\r\n<html>";
      content += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
      content += "<title>雲端飼料機IP型式設定</title>";
      content += "<p>請稍待...雲端飼料機開始重新設定IP</p>";
      content += "<Meta http-equiv=\"ReFresh\" Content=\"3; URL='/reset'\">";
      content += "</html>";
      server.send(200, "text/html", content);
    });

    server.on("/reset", []() {
      content = "<!DOCTYPE HTML>\r\n<html>";
      content += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
      content += "<title>雲端飼料機IP型式設定</title>";
      content += "<p>雲端飼料機已經重新啟動, 請檢查IP是否已依照你的需求設定完成, 若沒問題, 則可以關閉本頁面了...</p>";
      content += "</html>";
      server.send(200, "text/html", content);
    });

    server.on("/Feed/On/Small", []() {
      content = "<!DOCTYPE HTML>\r\n<html>";
      content += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
      content += "<title>雲端飼料機控制網頁</title>";
      content += "<p>餵食器動作中...";
      content += "<Meta http-equiv=\"ReFresh\" Content=\"5; URL='/'\">";
      content += "</p></html>";
      server.send(200, "text/html", content);
      myservo.attach(D2);                    
      myservo.write(100);
      delay(5000);
      myservo.detach();
    });

    server.on("/Feed/On/Standard", []() {
      content = "<!DOCTYPE HTML>\r\n<html>";
      content += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
      content += "<title>雲端飼料機控制網頁</title>";
      content += "<p>餵食器動作中...";
      content += "<Meta http-equiv=\"ReFresh\" Content=\"10; URL='/'\">";
      content += "</p></html>";
      server.send(200, "text/html", content);
      myservo.attach(D2);                    
      myservo.write(100);
      delay(10000);
      myservo.detach();
    });

    server.on("/cleareeprom", []() {                                      
      for (int i = 4; i < 236; ++i) {
        EEPROM.write(i, 0);
      }
      EEPROM.commit();
      content = "<!DOCTYPE HTML>\r\n<html>";
      content += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
      content += "<title>雲端飼料機控制網頁</title>";
      content += "<p>已關閉WiFi連線並清除WiFi設定, 請手動關閉網頁並等待雲端飼料機重新啟動...</p>";
      content += "</html>";
      server.send(200, "text/html", content);
      if (debug) Serial.println("clearing eeprom");
    });
  }
}

void ScanNetwork() {
  WiFi.disconnect();                                                  
  delay(100);
  WiFi.mode(WIFI_STA);                                                
  delay(100);
  int n = WiFi.scanNetworks();                                        
  if (debug) Serial.println("");
  if (debug) Serial.print("Scan Network Done...and ");
  if (n == 0)
    if (debug) Serial.println("No Any Networks Found!");
    else
    {
      if (debug) Serial.print(n);
      if (debug) Serial.println(" Networks Found!");
      if (debug) Serial.println("");
      for (int i = 0; i < n; ++i)
      {
     
        if (debug) Serial.print(i + 1);
        if (debug) Serial.print(": ");
        if (debug) Serial.print(WiFi.SSID(i));
        if (debug) Serial.print(" (");
        if (debug) Serial.print(WiFi.RSSI(i));
        if (debug) Serial.print(")");
        byte encryption = WiFi.encryptionType(i);
        if (debug) Serial.print(" Encryption Type:");
     
        switch (encryption) {
          case 2: if (debug) Serial.println("TKIP(WPA)"); break;
          case 5: if (debug) Serial.println("WEP"); break;
          case 4: if (debug) Serial.println("CCMP(WPA)"); break;
          case 7: if (debug) Serial.println("NONE"); break;
          case 8: if (debug) Serial.println("AUTO(WPA or WPA2)"); break;
        }
     
        digitalWrite(WiFi_Status_LED, LOW);
        delay(50);
        digitalWrite(WiFi_Status_LED, HIGH);
        delay(50);
      }
    }
  if (debug) Serial.println("");
  String k;
  st = "<ol type=\"1\" start=\"1\">";
  for (int i = 0; i < n; ++i)
  {  
    st += "<table border=\"0\"><tr><td width=\"300px\">";
    k = String(i + 1);
    st += k + ". ";
    st += WiFi.SSID(i);
    st += " (";
    st += WiFi.RSSI(i);
    st += ")";
    st += "</td><td width=\"200px\">";  
    byte encryption = WiFi.encryptionType(i);
    switch (encryption) {
      case 2: st += "TKIP(WPA)"; break;
      case 5: st += "WEP"; break;
      case 4: st += "CCMP(WPA)"; break;
      case 7: st += "NONE"; break;
      case 8: st += "AUTO(WPA or WPA2)"; break;
    }  
    st += "</td></tr>";
  }
  st += "</ol></table><br>";
}



/* WiFi連線的狀態碼
 WL_NO_SHIELD = 255,
 WL_IDLE_STATUS = 0,
 WL_NO_SSID_AVAIL = 1
 WL_SCAN_COMPLETED = 2
 WL_CONNECTED = 3
 WL_CONNECT_FAILED = 4
 WL_CONNECTION_LOST = 5
 WL_DISCONNECTED = 6
 */

void loop() {
  if (WiFi.status() == WL_CONNECTION_LOST || WiFi.status() == WL_CONNECT_FAILED || WiFi.status() == WL_DISCONNECTED) {
    ESP.restart();
  }
  server.handleClient();
}

PS: 小弟不是coding的專才, 請不要再說小弟的程式寫得很爛, 如果你看不下去, 可以把你認為搬得上抬面的code貼出來造福大家, 小弟也會同步更新的

實際動作影片如下

33 則留言:

  1. 好厲害,可以拜你為師嗎?

    回覆刪除
  2. 也許沒有很好的程式碼..
    但版主有很棒的分享精神..
    由衷感謝分享..Orz

    回覆刪除
    回覆
    1. 程式碼的寫法, 可以給個建議嗎?

      刪除
    2. if(debug)....
      一般在我看到的會用前置定義的方式去撰寫
      比如在上方加入
      #define DEBUG
      下方則寫成
      #ifdef DEBUG
      驗證程式
      #endif

      這樣會比較清楚知道這類程式是驗證用..
      最上面那行
      #define DEBUG
      沒寫就不會編譯DEBUG的程式碼..
      不然你的寫法..
      當debug等於0..
      依然會編譯DEBUG程式碼..
      像是有這麼一群
      if (debug) Serial.print(i + 1);
      if (debug) Serial.print(": ");
      if (debug) Serial.print(WiFi.SSID(i));
      if (debug) Serial.print(" (");
      if (debug) Serial.print(WiFi.RSSI(i));
      if (debug) Serial.print(")");
      程式碼
      可以改寫成..
      if (debug)
      {
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      }
      這樣會更明瞭..
      我的方式則會變成
      #ifdef DEBUG
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      #endif
      你我的方式差異則是在有沒有被編譯入程式碼的差異而已..
      但最終我覺得能動就好..
      只是要給第三方人看..
      對方就會比較吃力一點而已..
      如果自己看就能動就好..
      無妨..
      獻醜了..

      刪除
  3. 版主要不要試試改使用MQTT協定
    搭配MediaTek Cloud Sandbox (MCS)
    來達到雲端遙控的目的

    回覆刪除
  4. 版主要不要試試改使用MQTT協定
    搭配MediaTek Cloud Sandbox (MCS)
    來達到雲端遙控的目的

    回覆刪除
    回覆
    1. 改用MQTT有更好用嗎?

      刪除
    2. MQTT的狀態就像是聊天室
      可以自架MQTT server或用別人的(MCS)
      讓使用者跟MCU都連進指定頻道
      就可以達到遠端遙控了

      刪除
    3. 或者用 Firebase ?
      就不用固定IP也能上雲端了 :D

      刪除
    4. 也許用firebase更好, 用固定ip有點麻煩, 你可以分享給大家嗎?

      刪除
    5. http://darrentlear.blogspot.com/2018/10/blog-post.html
      程式碼沒帶出來,沒貼上去,另補。

      刪除
  5. 版主你好:
    閣下真是不簡單,可以自已完成整個系統,不過還是有些問題想請教一下,在前面畫面中看到的"192.168.11.11",這個IP位址應該是本地區域的位址,可是當你在外面要使用手機或PC透過網際網路(Internet)從遠端去控制時需要實際分配到的IP(不管是動態的或是固定的),不知道你如何去取的它(IP)呢?

    回覆刪除
    回覆
    1. 沒錯, 192.168.11.11是內部網址, 我家是申請固定ip的, 點這個網址就可以知道你當下對外的ip
      http://www.j4.com.tw/james/remoip.php
      如果你是固定ip, 那這個查到的值就不會變, 再用port forward方式來對應到內部的ip

      刪除
  6. 還有你使用了WIFI router跟ESP8266連線,這樣一來外部的實體IP如何對應到內部本地的區域IP呢?是不是使用Port Forward的方式呢?還請麻煩指教一下,謝謝!

    回覆刪除
    回覆
    1. 如你所說, 就是用port forward方式, 搭配esp8266固定內部ip, 外部ip也要固定(申請), 這樣就可達到由外部來控制內部的device

      刪除
  7. 請問你NODEMCU是怎麼和MG995接線的呢?

    回覆刪除
    回覆
    1. 從上面程式myservo.attach(D2); 可以看出, MG995的信號pin是接在D2, VCC就接
      nodemcu的vin, gnd接gnd

      刪除
  8. 老師你好:
    你的程式 很值得好好研究 有一事想請教 你的教學中 對於利用Arduino IDE序列阜得到192.168.11.11 是否能改成靜態IP呢 如果可以 似乎到哪裡 都可以快速地使用.
    謝謝老師

    回覆刪除
    回覆
    1. 可以, 甚至可以指定, 指定後存在EEPROM裡, 以後開機initial後, 把它叫回來即可, 但是這有點複雜, 我找一找後把它貼上來, 變成靜態IP後, 可以用AP的轉埠功能, 把你對外的ip, 轉到這個靜態IP, 這樣你的ESP8266就能從外面連進來, 做remote控制

      刪除
    2. 我剛才看了一下程式碼, 上面我po的程式碼已經包含了fixed ip功能了, 實際跟著做一次, 應該就可以看到

      刪除
    3. 謝謝老師 我會再仔細 讀懂每個環節

      刪除
  9. 大大請問一下 首次執行程式(無WIFI SSID PASSWORD) 按下[重新掃瞄周邊無線網路]會當機耶
    要如何排除??

    回覆刪除
    回覆
    1. 請把code寄到nhs54798799@gmail.com, 我run一次看看問題在哪裡?

      刪除
  10. 那個MG995接好之後似乎轉不太起來請問是什麼問題呀,我改接SG-90就正常轉了

    回覆刪除
  11. 那請問一下這個可以做成APP嗎

    回覆刪除
  12. 還有一個問題~~~~
    請問你3D列印的轉軸那邊不轉的話不是沒東西可以卡住飼料嗎
    那停止的時候要怎麼不讓飼料掉下來呢?
    是有在做隔板卡著嗎

    回覆刪除
    回覆
    1. 有, 有用EVA軟泡棉卡著飼料, 當轉軸不軸的時候, 就靠它卡著

      刪除

歡迎大家來討論交流一下~~~