แสดงบทความที่มีป้ายกำกับ NodeMCU แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ NodeMCU แสดงบทความทั้งหมด

วันอังคารที่ 1 กันยายน พ.ศ. 2558

NodeMCU V2 ESP8266 ตอนที่ 1: ทำความรู้จัก NodeMCU และติดตั้งเครื่องมือพัฒนา

ที่มาที่ไป 

ชาวบ้านเค้าอาจจะเกาะกระแส IoT (Internet Of Thing) กันเพราะตัว ESP8266 เป็นที่รู้จักกันในวงการนี้ แต่ของเราไม่ใช่ แรงบันดาลใจคนเรามันต่างกัน... ^_^

       เริ่มจากที่อยากซื้อชุด Lego MindStroms [ Link ]ให้ลูกมาต่อหุ่นยนต์เล่น แต่พอไปดูราคาและแบบที่จะต่อ กับวิธีการควบคุมแล้วเลยเปลี่ยนใจ มาลองมองหาบอร์ด Androno ต่อเองน่าจะเร้าใจกว่า แต่ต้องแก้ปัญหาการควบคุมให้สามารถบังคับหุ่นแบบไร้สายให้ได้ด้วย เพราะอยากให้คุมผ่านมือถือจะได้สะดวกเวลาเล่น ยังไม่ทันข้ามวันด้วยอานุภาพของ อากู๋ (Google) ค้นไปค้นมาก็เจอรักแรกพบกับ Module ESP8266 ผ่านตัวบอร์ด NodeMCU Devkit ที่มี WiFi ในตัวแถมทำตัวเป็น AP (Access Point) ได้ด้วย และ ... เฮ้ยราคาน่าคบ (ตอนสั่งซื้อประมาณสามร้อยกว่าๆ คาดว่าราคาน่าจะลงเรื่อยๆ) โปรแกรมอัดได้เลย ไม่ต้องผ่าน Arduino Uno ที่ซื้อมาด้วย (แอบร้องไห้หนักมาก... จะปา Uno ทิ้งก็กะไรอยู่ T_T )

ตัว NodeMCU ที่ผมใช้คือตัวนี้ครับ [ Link ] (ตัวบอร์ดแท้จะมีรูปก้อนเมฆ ถ้าเป็นตัวอื่นจะเป็นของเลียนแบบ) จริงๆมีหลายเจ้า แต่เจ้านี้สั่งวันนี้ ได้ของพรุ่งนี้เร็วดี (ไม่ได้ค่าโฆษณา แต่ชอบเป็นการส่วนตัว) ^_^

ปล. ที่มานั่งเขียนเพราะกลัวจะลืม จะฝากความหวังไว้กับบทความคนอื่นก็กลัวเค้าลบทิ้ง เดี๋ยวไม่มีดู เลยเขียนเก็บไว้ดูเองดีกว่า คุณพ่อ ท่านไหนมาเจอบทความชุดนี้เอาไปทำ Robot ให้ลูกเล่น ก็ขอให้สนุกนะครับ ไว้วันหลังมานัดแข่งกัน อิอิ


เข้าเรื่อง

      ตัว ESP8266 เป็นโมดูล ในกลุ่มพวก Micro Controller ที่มีความสามารถครบครัน จุดเด่นคือการเป็น WiFi ในตัว กินไฟแค่ 3.3V ทั้งยังสามารถทำตัวเองเป็น Access Point ได้ด้วย ใครอยากได้รายละเอียดเพิ่มเติม แนะนำให้ค้นใน Google  สรุปคือ มันดี เวอร์ ตรงตามความต้องการในการเอามาคุม Robot ... จัดไป   Ref: บทความที่พูดถึง ESP8266 [Link]

     ด้านขนาด NodeMCU ถือว่าเล็กมาก ประมาณเท่ากับ Thumb Drive ประมาณเอาเหรียญห้าบาท 2 เหรียญมาวางต่อกัน แถมสามารถ flash โปรแกรมผ่านสาย USB ได้เลยอัตโนมัติ ไม่ต้องต่อวงจรเพิ่มเติม เห็นคนในกลุ่มเค้าเอาไปควบคุมนู่นนี่นั่น ปั้มน้ำ รับค่าอุณหภูมิส่งขึ้น Server คุมรถ คุมเครื่องบิน (อีกหน่อยคงขึ้นเอาคุมยานอวกาศ)

           
ผังขาแสดงการทำงาน (ขา GPIO สำคัญมากเวลาต่อวงจร)

อันนี้อีกแบบ น่าจะดูง่ายขึ้น

     จากที่ลองเล่นมาสองสามวงจร พบว่าต่อวงจรทีไร ก็ต้องกลับมาดูรูปตลอดเวลาเขียนโปรแกรม เราจะอ้างหมายเลขของ GPIO  แต่บนแผ่นวงจรมันดันมีแต่ขื่อ D0-D12 ซะงั้น คิดว่าแรกๆหลายคงเป็นเหมือนกัน ใครจำเก่งก็เชิญ แต่ถ้าเป็นผม Bookmark Page นี้ไว้ดูจะง่ายกว่า ^_^

การติดตั้งเครื่องมือและการเขียนโปรแกรม

    ด้วย Node MCU แรกๆ ออกมาเค้าทำรองรับภาษา Lua  ซึ่งเป็นภาษา Script ที่ทำงานในลักษณะบรรทัดต่อบรรทัด คล้ายๆ Java Script ไม่ต้องคอมไพล์ จากการหาข้อมูลพบว่า เหล่า Maker เค้าเอาไปใช้งานจริงจะบอกว่ามันง่ายก็จริง แต่ขนาดของ Code มันใหญ่เวลาใช้กับงานพวกนี้ (Micro Controller) เลยมีคนปรับแต่งตัว Arduino IDE ให้รองรับบอร์ดของ ESP8266 พร้อมทำ Library มาให้ด้วย โดยเค้าใช้ภาษา C ในการเขียน แถมใจดีมีโค้ด Example ให้อีกเพียบ ผมเลยเลือกใช้ C บน Arduino IDE แทน Lua ด้วยประการฉะนี้ 

ขั้นตอนการติดตั้ง

1. ดาวน์โหลด Arduino IDE [ Link ] (ใครเห็นว่าดี ก็กลับมาบริจากเค้าได้นะครับ) แล้วติดตั้ง


2. เพิ่ม Board ของ ESP8266 โดยการ เปิดโปรแกรม เลือก File-> Preferences แล้วใส่ URL นี้
 http://arduino.esp8266.com/package_esp8266com_index.json ลงไปในช่องกรอบสีแดงตามรูป

3. กด OK แล้วกลับมาที่หน้าหลัก เลือก Tool -> Boards Manager

  แล้วเลื่อนลงมาล่างๆ หาคำว่า esp8266 by ESP8266 Community คลิ๊กตรงชื่อหรือพื้นที่ว่าง แล้วจะเห็นปุ่ม [ Install ] ตรงมุมล่างขวา ให้กดแล้วรอมันโหลดจนเสร็จ
   เมือเสร็จแล้ว กลับไปหน้าหลักแล้วไปเลือกบอร์ดของเรากัน (ของผมใช้ NodMCU 1.0 ESP8266-12E)



4. ลองเสียบตัว NodeMCU กับสาย USB ถ้าตัว window มองไม่เห็นให้ลง USB Driver เพิ่มเพื่อให้เห็น COM Port เวลาต่อกับ NodeMCU ลองดูตาม [ Link ] นี้ครับ

5. เมื่อทุกอย่างพร้อมแล้วก็แล้วลองเขียนโปรแกรมตัวอย่าง (Blink) เพื่อทดสอบ ว่าสามารถเขียนลงได้ โดยไปที่ File -> Example -> esp8266 -> Blink (บอกแล้วของเค้าดีจริง ตัวอย่างเพียบ)
6. ตรวจสอบให้แน่ใจว่า USB เสียบระหว่าคอมพ์ กับ NodeMCU แล้ว และมองเห็น Port COM แล้ว (ดูว่าไฟสีฟ้าที่ตัว Module ติดค้างไว้)

7. กดที่เครื่องหมาย ถูก เพื่อตรวจสอบ Code (Verify) เมื่อผ่านไม่มีปัญหา ก็สามารถกด ที่รูปลูกศรชี้ด้านขวา เพื่ออัดโปรแกรมลงตัว NodeMCU ได้เลย (ตอนกำลังอัดโปรแกรมสังเกตุ ไฟสีฟ้าจะกระพริบถี่ๆ)

8. เมื่อโปรแกรมเขียนลงบน NodeMCU สำหร็จจะขึ้นแบบนี้ด้านล่างครับ ^_^

9. ลองถอดสาย USB ที่เสียบกับเครื่อง แล้วเอาไปเสียบกับ Power Bank ก็จะได้ผลเดียวกัน (ผมชอบใช้ Power Bank เป็นแหล่งจ่าย เพราะสะดวกดี แถมใช้ได้นาน จะชาร์ตใหม่กี่รอบก็ได้)


ส่งท้าย

    น่าจะพอเอาไปเล่นเองต่อได้แล้วนะครับ หลักๆก็ลองเปิด Example มาลองเล่นดู ที่เค้าเล่นๆกันคือใช้เป็น Web Server สั่งเปิดปิดไฟ ผ่านเว็ป (ต่อกับ Module Relay) หรือจะคุมการทำงานผ่าน UDP Server หรือจะทำแบบของผมคือทำให้ ESP8266 เป็น Access Point แล้วสั่งงานผ่าน HTTP เพื่อคุม Smart Robot Car ดูตัวอย่างด้านล่าง อันนี้ผมเอาไว้เล่นกับเด็กๆครับ ^_^




ตอนต่อไป:  
**ไม่รับประกันว่าจะมีเวลาเขียนครบทุกตอนนะครับ หมั่นแวะมาดูละกันนะ ^_^
ตอนที่ 2 :  ควบคุม เปิด-ปิด LED ผ่าน GPIO เตรียมตัวก่อนทำ Robot
ตอนที่ 3 :  ควบคุม Robot Car ผ่าน UDP  
ตอนที่ 4 :  ควบคุม Robot Car ผ่าน HTTP โดยให้ NodeMCU เป็น Access Point (AP)
ตอนที่ 5 :  เพิ่ม Motor ทำหุ่น ForkLift กัน
ตอนที่ 6 :  ทำหุ่นชู๊ตห่วงกัน
ตอนที่ 7 :  เข้า Mode ต่อสู้ มาทำหุ่นยนต์นักรบกัน
ตอนที่ 8 :  บนดินเบื่อแล้ว มาบินกัน














วันพฤหัสบดีที่ 27 สิงหาคม พ.ศ. 2558

ESP8266 Web Server On-Of Toggle LED

ตัวอย่่างโปรแกรม NodeMCU V2 สั่งเปิดปิดไฟผ่าน GPIO โดยให้ ESP8266 เป็น Web Server


#include <ESP8266WiFi.h>

const char* ssid = "Wifi SSID";
const char* password = "Wifi Password";

int led1=1;
int led2=2;
int led3=3;
int led4=4;
int led5=5;
int led6=16;

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

void setup() {
  Serial.begin(115200);
  delay(10);

  // prepare GPIO2
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
 
  digitalWrite(led1, 0);
  digitalWrite(led2, 0);
  digitalWrite(led3, 0);
  digitalWrite(led4, 0);
  digitalWrite(led5, 0);
  digitalWrite(led6, 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() {
  // Check if a client has connected
  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');
  Serial.println(req);
  client.flush();
 
  // Match the request
  int val;


if (req.indexOf("/gpio/") != -1){
  int start = req.indexOf("/gpio/");
  int eidx = req.indexOf(" HTTP");
  String nval = req.substring(start+6,eidx);
 
  val = nval.toInt();
 
} else {
  val = 0;
//    Serial.println("invalid request");
//    client.stop();
//    return;
  }

  // Set GPIO2 according to the request
  digitalWrite(led1, (((val == 1) !=0))?!digitalRead(led1):digitalRead(led1));
  digitalWrite(led2, (((val == 2) !=0))?!digitalRead(led2):digitalRead(led2));
  digitalWrite(led3, (((val == 3) !=0))?!digitalRead(led3):digitalRead(led3));
  digitalWrite(led4, (((val == 4) !=0))?!digitalRead(led4):digitalRead(led4));
  digitalWrite(led5, (((val == 5) !=0))?!digitalRead(led5):digitalRead(led5));
  digitalWrite(led6, (((val == 6) !=0))?!digitalRead(led6):digitalRead(led6));
  client.flush();

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\n";
  s += "Access-Control-Allow-Origin:*\r\nAccess-Control-Allow-Methods:POST, GET\r\nAccess-Control-Allow-Headers:AUTHORISED\r\n";
  s += "Content-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>";
  s += "\r\n<head>";
  s += "<style>";
  s += "a{";
  s += "   display:inline-block;text-align:center;height:60px; width:60px; border: black solid 4px;";
  s += "   font-size:2em; padding:0.6em; border-radius:1.2em;";
  s += "   magin:0.5em;";
  s += "}\r\n";
  s += ".on{ background-color:red; }\r\n";
  s += ".off{ background-color:white;}\r\n";
  s += "</style>";
  s+= "\r\n</head>";
  s+= "<body>";
  s += "<h1>";
  s += "<a href=\"/gpio/1\" class=\"" ;
  s +=  digitalRead(led1)?"on":"off";
  s += "\">1</a> ";

   s += "<a href=\"/gpio/2\" class=\"" ;
  s +=  digitalRead(led2)?"on":"off";
  s += "\">2</a> ";

   s += "<a href=\"/gpio/3\" class=\"" ;
  s +=  digitalRead(led3)?"on":"off";
  s += "\">3</a> ";

   s += "<a href=\"/gpio/4\" class=\"" ;
  s +=  digitalRead(led4)?"on":"off";
  s += "\">4</a> ";

   s += "<a href=\"/gpio/5\" class=\"" ;
  s +=  digitalRead(led5)?"on":"off";
  s += "\">5</a> ";

   s += "<a href=\"/gpio/6\" class=\"" ;
  s +=  digitalRead(led6)?"on":"off";
  s += "\">6</a> ";
 

  s += "</h1>";
  s += "\r\nGPIO is now ";
  s += (val)?"high":"low";
  s += "<br/><br/>[" + req +"]<br/>" + val;
  s += "</body>";
  s += "</html>\n";

  // Send the response to the client
  client.print(s);
  delay(1);
  Serial.println("Client disonnected");

  // The client will actually be disconnected
  // when the function returns and 'client' object is detroyed
}

วันพุธที่ 26 สิงหาคม พ.ศ. 2558

ทำหุนยนต์ ให้เด็กๆเล่นกัน NodMCU คุมผ่าน WiFi ^_^

// เผื่อใครใจร้อนอยากลองก่อนครับ ^_^
//Code by AndronoIDE
// I will explain in detail later ^_^


#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

 const char* ssid = "Your WiFi SSID";
 const char* password = "Your WiFi Password";
 const char* host = "IP your computer";

 char message[255];

 unsigned int localPort = 8080;
 WiFiUDP Udp;
// Pin layout is NodeMCU V.2
 int pin1_motor_R = 1;   //gpio01 --> IN1 motor controller Right Motor
 int pin2_motor_R = 2;   //gpio02 --> IN2 motor controller Right Motor

 int pin1_motor_L = 3;   //gpio03 --> IN3 motor controller Left Motor
 int pin2_motor_L = 4;   //gpio04 --> IN4 motor controller Left Motor

// Direction
int FW=0,BK=1,ST=2;
int dir=FW;
// Turn Status
int t=0;
int TL=0, TR=1;
int tdir=0;
int tcount=0;


 void setup() {
   Serial.begin(115200);
   pinMode(pin1_motor_R , OUTPUT);
   pinMode(pin2_motor_R, OUTPUT);
   pinMode(pin1_motor_L, OUTPUT);
   pinMode(pin2_motor_L, OUTPUT);
   WiFi.begin(ssid, password);
   while (WiFi.status() != WL_CONNECTED) {
      delay(500);
Serial.print(",");
   }
   Serial.println("");
   Serial.println("WiFi connected");
   Serial.println("IP address: ");
   Serial.println(WiFi.localIP());
   Udp.begin(localPort);
 
   Stop();
   Serial.println("Setup done");
    delay(2000);

 }

 void loop(){
   int packetSize = Udp.parsePacket();
   if (packetSize)
   {
     IPAddress remoteIp = Udp.remoteIP();
     int len = Udp.read(message, 255);
     Serial.println(message);
     checkcommand();
     delay(5);
   }
}


 void forward()
 {
   Serial.println("forward");

   dir=FW;
   digitalWrite(pin1_motor_R, HIGH);
   digitalWrite(pin2_motor_R, LOW);
 
   digitalWrite(pin1_motor_L, HIGH);
   digitalWrite(pin2_motor_L, LOW);
 
 }


 void back()
 {
   Serial.println("back");
   dir=BK;
   digitalWrite(pin1_motor_R, LOW);
   digitalWrite(pin2_motor_R, HIGH);
 
   digitalWrite(pin1_motor_L, LOW);
   digitalWrite(pin2_motor_L, HIGH);
 }

 void left()
 {
  Serial.println("left");
  digitalWrite(pin1_motor_R, LOW);
  digitalWrite(pin2_motor_R, LOW);
 
   digitalWrite(pin1_motor_L, HIGH);
   digitalWrite(pin2_motor_L, LOW);
 }
 void right()
 {
  Serial.println("Right");
   digitalWrite(pin1_motor_R, HIGH);
  digitalWrite(pin2_motor_R, LOW);
 
   digitalWrite(pin1_motor_L, LOW);
   digitalWrite(pin2_motor_L, LOW);
 }


void turnR()
 {
  Serial.println("Turn0");
   digitalWrite(pin1_motor_R, HIGH);
  digitalWrite(pin2_motor_R, LOW);
 
   digitalWrite(pin1_motor_L, LOW);
   digitalWrite(pin2_motor_L, HIGH);
 }
 void turnL()
 {
  Serial.println("Turn1");
   digitalWrite(pin1_motor_R, LOW);
  digitalWrite(pin2_motor_R, HIGH);
 
   digitalWrite(pin1_motor_L, HIGH);
   digitalWrite(pin2_motor_L, LOW);
 }

 void Stop()
 {
  Serial.println("Stop");

  digitalWrite(pin1_motor_R, LOW);
  digitalWrite(pin2_motor_R, LOW);
 
   digitalWrite(pin1_motor_L, LOW);
   digitalWrite(pin2_motor_L, LOW);

 }

 void checkcommand()
 {
   if (*message=='f')
     {
   
        forward();

     }else if (*message=='t')
     {
        if(tdir==TL){
          turnR();
       
        }else{
          turnL();
     
        }
         delay(50);
        Stop();
     }
 
   else if (*message=='b')
     {
         back();
     
     }
   else if (*message=='r')
     {
         tdir=TR;
         right();
         delay(200);
         if(dir==FW){
            forward();
          }else if(dir==BK){
           back();
         }else{
            tcount++;
           if(tcount!=5){
             Stop();
           }else{
            turnR();
            tcount=0;
           }
         }
     
     }
   else if (*message=='l')
     {
         tdir=TL;
         left();
         delay(200);
         if(dir==FW){
            forward();
         }else if(dir==BK){
           back();
         }else{
           tcount++;
           if(tcount!=5){
             Stop();
           }else{
            turnL();
            tcount=0;
           }
         
         }
     }
 
   else
     {
       dir=ST;
       tcount=0;
       Stop();
     }
 }