วันพุธที่ 20 พฤษภาคม พ.ศ. 2558

เมื่อ NodeMCU Firmware มีปัญหา!

หลายๆ คนที่เล่น ESP8266 WIFI Module ในแบบ LUA Script บางครั้งอาจเจอปัญหาว่าอยู่ดีๆทำไม Upload Script ไม่ได้ หรืออยู่ดีๆ ทำไมใช่งานไม่ได้ซ่ะงั้น

เปิดขึ้นมาค้างไม่ยอม boot ค้างทำอะไรไม่ถูกไปต่อไม่ได้ซึ่งอาการแบบนี้บางทีแค่ Flash Firmware ใหม่อย่างเดียวก็ไม่หาย


ซึ่งอาจจะมี file ขยะอยู่เลยทำให้ระบรวน


ก่อนอื่นให้เราทำการล้าง flash ใหม่โดยใช้โปรแกรม ESP8266Flasher โดยทำการตั้งค่าดังนี้แล้วกดปุ่ม Flass ตามปรกติรอจนกว่าจะเสร็จ จากนั้นก็ทำการ Flash Firmware ตามประติ แตือย่าลืมเอา check ที่ address 0x40000, 0x7C000, 0x7E000 ออกก่อนด้วย


หลังจาก Flash Firmware กดปุ่ม File List แล้วยังเจอ File ขยะแบบนี้อีก


ให้เราทำการ Format File System ก่อน โดยไปที่ Menu ESP -> Format ESP 



กดปุ่ม File List ดูใหม่ File ขยะต้องหายไปสะอาดเอี่ยม


ทีนี้ ESP ของเราก็กลัมมาใช้งานได้อีกครั้ง





Donate

วันอาทิตย์ที่ 3 พฤษภาคม พ.ศ. 2558

การใช้งาน MyPi IoT Cloud Server

ในบทความนี้จะมากล่าวถึงการใช้งาน MyPi IoT Cloud Server เบื้องต้นสำหรับผู้ที่เป็นอาสาสมัครในการทำสอบ ก่อนอื่นต้อง Dowmload  File สำหรับที่ต้องใช้งานมาก่อนจะประกอบไปด้วย
  1. init.lua เป็น File startup ของ NodeMCU
  2. iothink_relay.lua File Script ที่ใช้ทำงานหลัก
  3. iothink.lua File Script Module
  4. app-debug.apk Android Application ไว้สำหรับทดสอบ
ในการ Connect เข้าระบบ Cloud จะใช้ ID ของ Client เป็นตัว Identify ขั้นตอนในการ Upload LUA Script

ให้ทำการ Upload File iothink.lua กดที่ปุ่ม Save to ESP


ให้ทำการ Upload File iothink_relay.lua กดที่ปุ่ม Save to ESP


ให้ทำการ Upload File init.lua ใน script เราต้องทำารกำหนด ssid และ pass ของเราให้ถูกต้องเสียก่อน
จากนั้นกดที่ปุ่ม Save to ESP


Restart ESP8266 กดที่ปุ่ม Restart ESP


หลังจาก Restart แล้ว script init.lua จะถูกเรียกให้ขึ้นมาทำงานก่อนโดยอัตโนมัติ แล้วทำการ Connect เข้ากับ Access Point ตาม SSID ที่เรากำหนดไว้ ถ้าไม่มีอะไรผิดพลาดหลังจากที่ Connect กับ Access Point ได้แล้ว Script iothink_relay.lua ก็จะถูกเรียกให้ทำงาน แล้งทำการ   Connect เข้ากับ Server แล้วรายงาน หมายเลข ID ออกมา ให้เราจด หมายเลข ID ไว้ใช้งานต่อไป

GPIO ที่ใช้งานใน Android App ที่ใช้ทดสอบจะเป็น 5 (GPIO14),  6 (GPIO12),  7 (GPIO13) ใครใช้ต่างจากนี้จะต้อง Build Code ของ Android ใหม่ก็ให้ขอ Source Code มาได้ครับ

Link สำหรับ Download จะส่งให้กับผู้ที่ลงรายชื่อไว้ใน Page MyPi IoT Lerning Center ก่อนเท่านั้น

การใช้งาน Android App ต้องทำการแก้ไข Device Id ก่อนโดยกดที่ปุ่มบนขวาสุดรูตัว i



ป้อน Device Id




LED RGB


1 Device 4 GPIO


1 Device 2 GPIO x 2





วันศุกร์ที่ 3 เมษายน พ.ศ. 2558

ArduinoESP IDE

เป็นสิ่งที่หลายๆ คนอยากให้เป็นคือการเขียน Code แบบ Native บน ESP8266 ยังไงให้งายกว่าที่เป็นอยู่ในปัจุบันนี้ ซึ่งตอนนี้ได้มีการออก  IDE ในรูปแบบเดียวกันกับ Arduino .ทำให้เราสามารถเขียน Code ในรูปแบบเดียวกับกับ Arduino แล้วทำการ upload ลงใน ESP8266 ได้โดยตรงทำให้ชิวิตงายขึ้นเยอะ ข้อมูลเพิ่มเติมสามารถหาอ่านได้ที่นี่

ก่อนอื่นเราต้องไป Download ArduinoESP IDE มาติดตั่งก่อน Version จะเป็น 1.6.1 ก่อนการใช้งานเราจำเป็นต้องกำหนดค่าเบื่องต้นก่อน

กำหนด Board ใการใช้งานตามรูป



กำหนด Port ที่ใช้ในการติดต่อกับ Module


กำหนด Programmer ที่ใช้ในการ Upload


แค่นี้ดราก็พร้อมที่จะใช้งาน Arduino ESP IDE แล้ว เราสามารถทดลองจากตัวอย่าง Code ได้จาก Example


จากนี้เราก็สามารถเขียน Application ควบคุมการทำงานผ่านหน้าWeb ได้โดยงาย



ตัวอย่าง Source  Code

#include <ESP8266WiFi.h>

const char* ssid = "ssid";
const char* password = "password";
String gpio12 = "OFF";
String gpio13 = "OFF";
String gpio14 = "OFF";
String gpio16 = "OFF";

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(10);

  // prepare GPIO2
  pinMode(12, OUTPUT);
  digitalWrite(12, 0);
  
  pinMode(13, OUTPUT);
  digitalWrite(13, 0);
  
  pinMode(14, OUTPUT);
  digitalWrite(14, 0);
  
  pinMode(16, OUTPUT);
  digitalWrite(16, 0);
  
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  // Start the server
  server.begin();
  Serial.println("Server started");
  // Print the IP address
  Serial.println(WiFi.localIP());
}

void loop() {
  // put your main code here, to run repeatedly:
  
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
  
  // Read the first line of the request
  String req = client.readStringUntil('\r');
  
  client.flush();  
  if (req.startsWith("GET /")){
    send_index(&client);
  }
  if (req.startsWith("POST")){
    process_io(req);
    send_index(&client);
  }  
}

void process_io(String req){
  Serial.print("HTTP Request: ");
  Serial.println(req);
  
  // POST /digital/12/0 HTTP/1.1
  if (req.indexOf("POST /digital") != -1){
    int firstVal, secondVal;
    firstVal = req.substring(14, 16).toInt();
    secondVal = req.substring(17, 18).toInt();
    
    Serial.print("PIN: ");
    Serial.println(firstVal, DEC);  
    Serial.print("STATE: ");
    Serial.println(secondVal, DEC); 
    
    digitalWrite(firstVal, !secondVal);     
  }
}

void send_index(WiFiClient *client){
  
  gpio12 = digitalRead(12) == HIGH ? "ON" : "OFF";
  gpio13 = digitalRead(13) == HIGH ? "ON" : "OFF";
  gpio14 = digitalRead(14) == HIGH ? "ON" : "OFF";
  gpio16 = digitalRead(16) == HIGH ? "ON" : "OFF";
  
  String s = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n";
  s += "<!DOCTYPE HTML><html><head><style>input[type=submit] {font-size:large;width:8em;height:4em;}</style>";
  s += "<meta content=\"text/html;charset=utf-8\"><title>ESP8266</title>";
  s += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">";
  s += "<body bgcolor=\"#ffe4c4\"><h2>ESP8266-12</h2><hr></body></html>";
  
  s += "<form action=\"/digital/" + String(12) + "/" + String(digitalRead(12)) + "\" method=\"POST\">";
  s += "<input type=\"submit\" value=\"GPI12 " + gpio12 + "\"/></form><br>";
  
  s += "<form action=\"/digital/" + String(13) + "/" + String(digitalRead(13)) + "\" method=\"POST\">";
  s += "<input type=\"submit\" value=\"GPI13 " + gpio13 + "\"/></form><br>";

  s += "<form action=\"/digital/" + String(14) + "/" + String(digitalRead(14)) + "\" method=\"POST\">";
  s += "<input type=\"submit\" value=\"GPI14 " + gpio14 + "\"/></form><br>";  
  
  s += "<form action=\"/digital/" + String(16) + "/" + String(digitalRead(16)) + "\" method=\"POST\">";
  s += "<input type=\"submit\" value=\"GPI16 " + gpio16 + "\"/></form>";  
  client->print(s);
  delay(1);
  Serial.println("Client disonnected");
}

ก่อน Upload ต้องเข้า Mode ฺBoot loader ก่อนน่ะครับโดยการทำให้ GPIO0 Active Low ตอน Module Startup หรือ Module Reset







Donate

วันอังคารที่ 3 มีนาคม พ.ศ. 2558

ESP8266 GPIO Http Server

ในบทความนี้จะต่อจากครั้งที่แล้วโดยจะใช้ ESP8266-01 เป็นตัวทดสอบ

เราใจใช้ GPIO0(3) กับ GPIO2(4)


ซึ่งผมได้ปรับปรุง Codeจากครั้งที่แล้วเพื่อให้สามารถควบคุมการทำงานของ GPIO ได้

Source Code

gpio.mode(3,gpio.OUTPUT)
gpio.mode(4,gpio.OUTPUT)
function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end
function urldecode(payload)
    result = {};
    list=split(payload,"\r\n")
    list=split(list[1]," ")
    list=split(list[2],"\/")
    table.insert(result, list[1]);
    table.insert(result, list[2]);
    table.insert(result, list[3]);
    return result;
end

function index(conn)

    gpio3 = 'ON'
    gpio4 = 'ON'
    if (gpio.read(3) == 1) then
       gpio3 = 'OFF'
    end
    if (gpio.read(4) == 1) then
       gpio4 = 'OFF'
    end
    conn:send('HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
     <!DOCTYPE HTML><html><head><style>input[type=submit] {font-size:large;width:8em;height:4em;}</style>\
     <meta content="text/html;charset=utf-8"><title>ESP8266</title>\
     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">\
     <body bgcolor="#ffe4c4"><h2>ESP8266-01</h2><hr>\
     <form action="/digital/3/'..gpio.read(3)..'" method="POST">\
     <input type="submit" value="GPIO3 '..gpio3..'"/></form><br><br>\
     <form action="/digital/4/'..gpio.read(4)..'" method="POST">\
     <input type="submit" value="GPIO4 '..gpio4..'" /></form>\
     </body></html>')
end
function notfound(conn)
     conn:send('HTTP/1.1 404 Not Found\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
          <!DOCTYPE HTML>\
         <html><head><meta content="text/html;charset=utf-8"><title>ESP8266</title></head>\
          <body bgcolor="#ffe4c4"><h2>Page Not Found</h2>\
          </body></html>') 
end

srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive",function(conn,payload)
      print("Http Request..\r\n")
      --print (payload)
      list=urldecode(payload) 
      if ((list[2]=="") or (list[2]=="index.html")) then 
          index(conn)   
      elseif (list[2]=="digital") then
          local pin = tonumber(list[3]) 
          local status = tonumber(list[4]) 
          if (status == 1) then
               gpio.write(pin, 0)   
          else
               gpio.write(pin, 1)
          end  
          --print(gpio.read(pin))        
          index(conn)
      else
          notfound(conn)   
      end      
      conn:close() 
    end)
end)


อุปกรณ์ที่ใช้ในการทดสอย





Donate

วันจันทร์ที่ 2 มีนาคม พ.ศ. 2558

ESP8266 Sample Http Server

ในบทความนี้จะกล่าวถึงการทำ web server อย่างง่าย ๆ ด้วย Lua Script กับ NodeMCU ซึ่ง web server จะทำงานอยู่บน TCP Transport Layer ฉนั้นเราจะต้องสร้าง Object Server ขึ้นมาก่อนโดยที่กำหนด Type เป็น TCP แล้วสั่งรับการ Connection จาก Client ที่ Port 80 srv:listen(80, func(conn)) เมื่อมีการร้องขอจาก Client (ในที่นี้หมายถึง Web Browser) ก็จะมาเข้าการทำงานที่ conn:on("receive", func(conn, payload))


ทีนี้สิ่งที่เราต้องใช้คือ payload ถามว่า payload คืออะไร? payload ก็คือ Request Header ที่ส่งมาจาก  Client (ในที่นี้หมายถึง Web Browser) ที่  Browser ถ้าเราพิมพ์ URL http://192.168.0.125 รูปแบบของ Request Header ก็จะได้ประมาณนี้ขึ้นอยู่กับ Browser แต่ละค่าย


แต่ถ้าเราพิมพ์ URL http://192.168.0.125/index.html  รูปแบบของ Request Header ก็จะได้ประมาณนี้


มาถึงตอนนีเราจะเห็นได้ว่าสิ่งที่เราสนใคอยู่ที่บรรทัดแรก ในตัวอย่างจะทำารสร้าง Page ขึ้นมา 2 Page

Index

About

ป้องกันการเรียน URL ผิดเราก็ต้อวมี Page Not Found

สิ่งที่สำคับของ web server คือการ Response Header เพื่อบอก Status ให้ Browser รู้ Status Code จะมีอยู่หลาย Code ในที่นี้จะยกมาให้ดู 2 Code

  • HTTP/1.1 200 OK
  • HTTP/1.1 404 Not Found
Response Status 200

Response Status 404

Lua Script


function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end
function urldecode(payload)
    result = {};
    list=split(payload,"\r\n")
    list=split(list[1]," ")
    list=split(list[2],"\/")
    table.insert(result, list[1]);
    table.insert(result, list[2]);
    table.insert(result, list[3]);
    return result;
end

function index(conn)
    conn:send('HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
     <!DOCTYPE HTML><html><head>\
     <meta content="text/html;charset=utf-8"><title>ESP8266</title>\
     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">\
     <body bgcolor="#ffe4c4">\
     <h2>Page Index</h2><hr>\
     </body></html>')
end
function about(conn)
    conn:send('HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
     <!DOCTYPE HTML><html><head>\
     <meta content="text/html;charset=utf-8"><title>ESP8266</title>\
     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">\
     <body bgcolor="#ffe4c4">\
     <h2>Page About</h2><hr>\
     </body></html>')
end
function notfound(conn)
     conn:send('HTTP/1.1 404 Not Found\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
          <!DOCTYPE HTML>\
         <html><head><meta content="text/html;charset=utf-8"><title>ESP8266</title></head>\
          <body bgcolor="#ffe4c4"><h2>Page Not Found</h2>\
          </body></html>') 
end

srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive",function(conn,payload)
      print("Http Request..\r\n")
      print (payload)
      list=urldecode(payload) 
      if ((list[2]=="") or (list[2]=="index.html")) then 
          index(conn)     
      elseif (list[2]=="about.html") then 
          about(conn)  
      else
          notfound(conn)   
      end      
      conn:close()
    end) 
end)

หวังเป็นอย่างยิ่งว่าคงจะมีประโยชน์ไม่มากก็น้อย บทความหน้าจะมาควบคุม GPIO กัน

Donate

วันจันทร์ที่ 23 กุมภาพันธ์ พ.ศ. 2558

NodeMCU Connect Access Point

ในบทความนี้เราจะมาทำการให้ NodeMCU ของเรา Connect กับ Access Point ก่อนอื่นต้อง Download File init.lua กันก่อน จากนั้นเปิดโปรแกรม ESPlorer กำหนด com port ให้ตรงกับที่ใช้งาน กดป่ม Open จากนั้นเปิด File init.lua ขึ้นมา

ถ้าหากเรายังไม่เคย upload file init.lua มาก่อนเวลาเปิดใช้งานครั้งแรก NodeMCU จะฟ้องว่าไม่พบ File init.lua เพราะ NodeMCU จะเรียกหา File init.lua ขึ้นมาทำงานครั้งแรกที่มีการ Startup ขึ้นมา



ให้เราทำการเปลี่ยน ssid กับ password ให้เป็นที่เราใช้งานอยู่จากนั้นกดปุ่ม save ที่ toolbar 


ถ้าเราเปิด com port ไว้โปรแกรมจะทำการ  Upload File ให้เราทุกครั้งที่มีการ Save File


หลังจาก Upload เสร็จโปรแกรมจะสั่งให้ Run File init.lua โดยอัตโนมัติ



เป็นอันว่ามาถึงตอนนี้ NodeMCU  ของเราก็สามารถใช้งาน WIFI ได้แล้วในบทความต่อไปเราจะมาสร้าง Application กัน



Donate

วันอาทิตย์ที่ 22 กุมภาพันธ์ พ.ศ. 2558

เครื่องมือที่ใช้ในการพัฒนา NodeMCU ด้วยภาษา Lua

สำหรับเครื่องมือที่ใช้พัฒนาผมเองได้ทดสอบมาหลายคัวแล้ว ในที่นี้จะมีอยู่สองตัวที่แนะนำ

โดยส่วนตัวผมชอบ ESPlorer มากกว่าเพราะมี Editor ที่มี Syntax Highlighter ทำให้เราเขียน Script แล้วดูง่ายขึ้น
LuaLoader 

ESPlorer


Donate