วันพฤหัสบดีที่ 21 กุมภาพันธ์ พ.ศ. 2562

ตัวอย่าง วิชา ไมโครคอนโทรนเลอร์ ครั้งที่ 5

การควบคุมหลอดแสดงผล LED 7-Segment ด้วย Micro controller PIC โดยใช้โปรแกรม PIC CCS Compiler

     หลอดแสดงผล LED 7-Segment เป็นอุปกรณ์อิเล็กทรอนิกส์ที่ใช้ในการแสดงผลเช่นเดียวกับหลอดแสดงผล LED ทั่วไป แต่ต่างตรงที่หลอดแสดงผล LED 7 ส่วน เป็นการนำเอาหลอดแสดงผล LED จำนวน 7 ตัวมาต่อกันเป็นรูปตัวเลข เพื่อนำมาแสดงผลเป็นตัวเลข 0 ถึง 9 โดยในบทความนี้จะพูดถึงการเขียนโปรแกรมควบคุมการทำงานของหลอดแสดงผล LED 7 ส่วน และ การประยุกต์ใช้งานไม่โครคอนโทรลเลอร์ PIC ควบคุมการทำงานของหลอดแสดงผล LED 7 ส่วน



1.  โครงสร้างและการทำงานของหลอดแสดงผล LED 7 ส่วน
    หลอดแสดงผล LED 7 ส่วน เป็นการนำเอาหลอด แสดงผล  LED จำนวน 7 ตัวมาต่อกันเป็นรูปตัวเลขโดยมีชื่อเรียกแต่ละส่วน คือ a,b,c,d,e,f,g และ dp แสดงดังรูปที่ 1.1


 









รูปที่ 1.1 โครงสร้างและขาของหลอดแสดงผล LED 7-Segment

     หลอดแสดงผล LED 7-Segment สามารถแบ่งตามลักษณะการต่อหลอดแสดงผล LED ทั้ง 7 หลอดได้ 2 ชนิด ดังนี้

     1. ชนิดต่อแบบแอโนดร่วม หรือ คอมมอนแอโนด (Common Anode)
     2. ชนิดต่อแบบแคโทดร่วม หรือ คอมมอนแคโทด (Common Cathode)

โดยโครงสร้างการต่อหลอดแสดงผล LED 7-Segment ทั้ง 2 ชนิด ดังรูปที่ 1.2



รูปที่ 1.2 โครงสร้างการต่อหลอดแสดงผล LED 7-Segment

     รูปที่ 1.2(ก) เป็นการต่อหลอดแสดงผล LED 7-Segment แบบแอโนดร่วม โดยต้องป้อนไฟบวกที่ขาร่วมที่หรือขาคอมมอน (Common) และถ้าต้องการให้หลอดแสดงผล LED 7-Segment แสดงผลหรือให้สว่าง ต้องป้อนไฟลบหรือส่งลอจิก "0" มาที่ขาแคโทด 
     ส่วนรูปที่ 1.2(ข) เป็นการต่อหลอดแสดงผล LED 7-Segment แบบแคโทดร่วม โดยต้องป้อนไฟลบหรือกราวด์ที่ขาร่วมหรือขาคอมมอน และถ้าต้องการให้หลอดแสดงผล LED 7-Segment แสดงผลหรือสว่างต้องป้อนไฟบวกหรือส่งลอจิก "1" มาที่ขาแอโนด


2. การเชื่อต่อ PIC กับหลอดแสดงผล LED 7-Segment
     สำหรับการต่อ PIC ร่วมกับหลอดแสดงผล LED 7-Segment ควรต่อไอซีบัฟเฟอร์ร่วมด้วย เพื่อขยายกระแสให้หลอดแสดงผล LED 7-Segment สว่างเท่ากันทุกหลอด และป้องกันการลัดวงจรของหลอดแสดงผล LED 7-Segment ซึ่งมีผลทำให้ Micro controller PIC เสียหายได้


รูปที่ 2.1 การเชื่อมต่อ PIC กับหลอดแสดงผล LED 7-Segment

     รูปที่ 2.1 เป็นการต่อหลอดแสดงผล LED 7-Segment เข้ากับพอร์ต B ของ PIC เบอร์ 16F877 ซึ่งระหว่างหลอดแสดงผล LED 7-Segment กับพอร์ต B นั้นก็จะมีไอซีบัฟเฟอร์ต่อร่วมอยู่ด้วย ซึ่งไอซีบัฟเฟอร์เบอร์ 74LS245 นอกจากจะทำหน้าที่ขยายกระแสเพื่อให้หลอดแสดงผล LED 7-Segment สว่างเท่ากันทั้ง 7 ตัวแล้ว ยังทำหน้าที่ป้องกันความเสียหายให้กับ PIC ในกรณีที่เกิดการลัดวงจรในส่วนหลอดแสดงผล LED 7-Segment ด้วย
     การต่อ PIC ร่วมกับหลอดแสดงผล LED 7-Segment เพื่อให้แสดงผลออกมาเป็นตัวเลขต่างๆ จะต้องมีการส่งข้อมูลออกพอร์ตของ PIC ที่ต่อร่วมอยู่กับหลอดแสดงผล LED 7-Segment และข้อมูลที่จะส่งออกพอร์ตนั้นก็ขึ้นอยู่กับชนิดของหลอดแสดงผล LED 7-Segment ซึ่งข้อมูลที่จะส่งออกพอร์ตของหลอดแสดงผล LED 7-Segment แบบต่อแอโนดร่วมและต่อแคโทดร่วม แสดงดังตาราง ที่ 2.1 และ 2.2

 

ตารางที่ 2.1 แสดงข้อมูลที่ส่งออกพอร์ตของหลอดแสดงผล LED 7-Segment 
แบบต่อแอโนดร่วม (Common Anode)


ตารางที่ 2.2 แสดงข้อมูลที่ส่งออกพอร์ตของหลอดแสดงผล LED 7-Segment 
แบบต่อแคโทดร่วม (Common Cathode)




3. การส่งข้อมูลออกหลอดแสดงผล LED 7-Segment

     การส่งข้อมูลออกพอร์ต เพื่อส่งออกหลอดแสดงผล LED 7-Segment จะเหมือนกับการส่งข้อมูลออกหลอดแสดงผล LED ทั่วไป แต่การแสดงผลออกหลอดแสดงผล LED 7-Segment จะเป็นลักษณะของตัวเลข ดังนั้นข้อมูลที่ส่งออกพอร์ตจึงเป็นเลขฐานสิบหกของตัว

     รูปแบบ     output_พอร์ต(ข้อมูลเลขฐานสิบหกของตัวเลขที่ต้องการแสดง);
     ตัวอย่าง    output_B(0x3F);

     หมายถึง  ส่งค่าข้อมูล 0x3F หรือส่ง 00111111B ออกที่พอร์ต B เพื่อให้หลอดแสดงผล LED 7-Segment แสดงผลเป็นตัวเลข 0


ตัวอย่างที่ 3.1 โปรแกรมแสดงผลออกที่หลอดแสดงผล LED 7-Segment ซึ่งต่ออยู่กับพอร์ต B ของ PIC และเป็นหลอดแสดงผล LED 7-Segment แบบต่อแคโทดร่วม โดยให้แสดงผลเป็นตัวเลข 0-9 ตามลำดับ


วิธีการคิด

     การเขียนโปรแกรมแสดงผลออกหลอดแสดงผล LED 7-Segment จะประกาศตัวแปรแบบอาร์เรย์ เพื่อใช้ในการเก็บข้อมูลตัวเลขที่ต้องการแสดงผล เนื่องจากง่ายต่อการเขียนโปรแกรมและสะดวกในการแก้ไขข้อมูลที่ส่งออกพอร์ตแสดงผล

เขียนโค๊ดที่ใช้งานจริง

#include <16F877.h>
#fuses   HS,NOPUT,NOWDT,NOPROTECT
#use    delay (clock=4Mhz)
void main()

 int num[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
 signed int i;                      
  while(1)
   {   
       for(i=0;i<10;i++)
          {  output_B(num[i]);  
             delay_ms(500);
          }                              
    }


อธิบายโปรแกรม

  บรรทัดที่ 5 ประกาศตัวแปร num[10] เพื่อเก็บข้อมูลตัวเลข 0-9 ที่ต้องการส่งออกพอร์ตจำนวน 10 ตัว
  บรรทัดที่ 7 ประกาศตัวแปรแบบ signed int i; คือประกาศตัวแปร i เป็นตัวเลขชนิดจำนวนเต็มมีค่าตั้งแต่ -127 ถึง 128
  บรรทัดที่ 8 ให้โปรแกรมทำงานวนรอบตลอดกาล
  บรรทัดที่ 10 กำหนดให้ฟังก์ชัน for ทำงานวนรอบจำนวน 10 รอบคือ 0-9 ตามค่า i
  บรรทัดที่ 11 แสดงผลตัวเลขในตัวแปรอาร์เรย์ออกพอร์ต B โดยค่าในอาร์เรย์จะเปลี่ยนตามค่าของ i

ตัวอย่าง วิชา ไมโครคอนโทรนเลอร์ ครั้งที่ 4

โปรแกรมสวิตซ์กดติด-ปล่อยดับ

  สำหรับการทดลองในบทความนี้จะเป็นการใช้งานพอร์ตอินพุตของ ไมโครคอนโทรลเลอร์ PIC โดยการต่อสวิตซ์เพิ่มเข้ามาเพื่อที่จะนำมาใช้ในการควบคุมพอร์ตเอาต์พุตของไมโครคอนโทรลเลอร์ PIC เอาล่ะครับทีนี้ มีสวิตซ์เพิ่มเข้ามาท้าทายความสามารถ ยิ่งทำให้อยากลองแล้วใช่มั๊ยครับ

ขั้นตอนที่ 1

 ประกอบวงจรตามรูปด้านล่าง ลงในโปรแกรม Proteus ครับ


คำสั่งที่ใช้ในการโปรแกรม

while()  เป็นคำสั่งทำงานซ้ำแบบมีเงื่อนไขครับ ซึ่งจะทำงานวนซ้ำไปเรื่อยๆจนกว่าเงื่อนไขจะเป็นเท็จ

output_x(...)   เป็นคำสั่งส่งข้อมูลออกทางเอาต์พุตในพอร์อตที่ต้องการตามค่าที่กำหนด เช่น output_b(0x01);

delay_ms(...)  เป็นคำสั่งหน่วงเวลา เช่น delay_ms(500); โปรแกรมจะหน่วงเวลา 500ms ซึ่งค่านี้เราสามารถเปลี่ยนแปลงได้ตามความต้องการครับ

set_tris_x()  เป็นคำสั่งกำหนดพอร์ตใช้งานให้พอร์ตอินพุต หรือเอาต์พุต โดยการกำหนดค่าให้กับฟังก์ชัน set_tris_x() เช่น set_tris_b(0x00); , set_tris_a(0xff);


value = input() เป็นคำสั่งอ่านข้อมูลจากพอร์ตอินพุตที่ต้องการ เช่น a=!input(pin_a0);

output_bit()  เป็นคำสั่งส่งข้อมูลออกทางเอาต์พุตในระดับบิต เช่น output_bit(pin_b0,a);
  

ขั้นตอนที่ 2

เริ่มเขียนโปรแกรมกันเลยครับ



#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,NOPROTECT
#use fast_io(A)
#use fast_io(B)


int1 a;                                      //  คำสั่งประกาศตัวแปร a เป็นเลขจำนวนเต็มขนาน 1 บิต

void main()

{
  set_tris_a(0xff);                        //  คำสั่งกำหนดพอร์ต A เป็นพอร์ตอินพุตทั้งหมด
  set_tris_b(0x00);                      //  คำสั่งกำหนดพอร์ต B ให้เป็นพอร์ตเอาต์พุตทั้งหมด

  output_b(0b00000000);            //  คำสั่งเคลียร์พอร์ต B ให้เป็น 0 ทุกบิต
  
  while(true)                              //  คำสั่งวนซ้ำแบบมีเงื่อนไข
        {
          a=!input(pin_a0);            //  คำสั่งอ่านข้อมูลจากพอร์ตอินพุต ขา a0
          output_bit(pin_b0,a);       //  คำสั่งส่งข้อมูลออกทางเอาต์พุตขนาด 1 บิต 
        }                                      //  โดยนำค่า a ส่งออกที่ขา b0
}

ตัวอย่าง วิชา ไมโครคอนโทรนเลอร์ ครั้งที่ 3

โปรแกรมไฟกระพริบ LED 2 ดวง


 โปรแกรมไฟกระพริบ LED 2 ดวง

       อย่างที่ได้กล่าวไว้ในบทความแรกครับ เราจะพาเพื่อนๆ เขียนโปรแกรมแบบพื้นฐานง่ายๆกันครับ โดยการใช้งานคำสั่งก็จะไม่มีอะไรซับซ้อนมาก ซึ่งผู้ที่ศึกษาไมโครคอนโทรลเลอร์มือใหม่ ก็สามารถที่จะทำได้เช่นกัน มาเริ่มกันเลยครับ



ขั้นตอนที่ 1

ประกอบวงจรตามรูปด้านล่าง ลงในโปรแกรม Proteus ครับ



คำสั่งที่ใช้ในการโปรแกรม

while()  เป็นคำสั่งทำงานซ้ำแบบมีเงื่อนไขครับ ซึ่งจะทำงานวนซ้ำไปเรื่อยๆจนกว่าเงื่อนไขจะเป็นเท็จ

output_x(...)   เป็นคำสั่งส่งข้อมูลออกทางเอาต์พุตในพอร์อตที่ต้องการตามค่าที่กำหนด เช่น output_b(0x01);

delay_ms(...)  เป็นคำสั่งหน่วงเวลา เช่น delay_ms(500); โปรแกรมจะหน่วงเวลา 500ms ซึ่งค่านี้เราสามารถเปลี่ยนแปลงได้ตามความต้องการครับ


ขั้นตอนที่ 2

  เมื่อเราต่อวงจรใน Proteus เสร็จแล้วก็มาเขียนโปรแกรม โดยใช้โปรแกรม CCS C Compiler กันครับแต่ต้องศึกษา
วิธี การใช้งาน ccs compiler ก่อนนะครับ

เริ่มกันเลยครับ


#include<16F84A.h>
#use delay(clock=4000000)
#fuses XT,NOWDT

void main()
{
  while(true)                      // คำสั่งวนซ้ำแบบมีเงื่อนไข
         {
           output_b(0x03);     // คำสั่งส่งข้อมูลออกทางเอาต์พุตพอร์ต b0 และ b1
           delay_ms(1000);    // คำสั่งหน่วงเวลา 1 วินาที
           output_b(0x00);     // คำสั่งให้เอาต์พุตพอร์ต b ทั้งหมดเป็นลอจิก 0
           delay_ms(1000);    // คำสั่งหน่วงเวลา 1 วินาที
         }
}

ตัวอย่าง วิชา ไมโครคอนโทรนเลอร์ ครั้งที่ 2

โปรแกรมไฟวิ่ง

     บทความนี้เราจะมาศึกษาโปรแกรมไฟวิ่งกันครับ หลังจากที่ได้ทดลองเขียน โปรแกรมไฟกระพริบ LED 2 ดวง กันไปแล้ว ทีนี้เรามาทดลองเขียนโปรแกรมไฟวิ่งกันบ้างครับ ซึ่งจะใช้ LED ทั้งหมด 8 ดวงต่อเข้ากับพอร์ตเอาต์พุต B ทั้งหมด เพื่อที่จะให้ท่านที่เขียนไมโครคอนโทรลเลอร์มือใหม่ ได้เข้าใจการใช้งานเอาต์พุตพอร์ตดิจิตอลทั้ง 8 บิตควบคุม LED 8 ดวง มาเริ่มกันเลยครับ

ขั้นตอนที่ 1

 ประกอบวงจรตามรูปด้านล่าง ลงในโปรแกรม Proteus ครับ


คำสั่งที่ใช้ในการโปรแกรม

while()  เป็นคำสั่งทำงานซ้ำแบบมีเงื่อนไขครับ ซึ่งจะทำงานวนซ้ำไปเรื่อยๆจนกว่าเงื่อนไขจะเป็นเท็จ


for() เป็นคำสั่งทำงานซ้ำที่มีจำนวนลูปที่แน่นอน และจะหยุดทำซ้ำเมื่อเงื่อนไขเป็นเท็จ เช่น
for(i=1;i<=9;i++)

output_x(...)   เป็นคำสั่งส่งข้อมูลออกทางเอาต์พุตในพอร์อตที่ต้องการตามค่าที่กำหนด เช่น output_b(0x01);

delay_ms(...)  เป็นคำสั่งหน่วงเวลา เช่น delay_ms(500); โปรแกรมจะหน่วงเวลา 500ms ซึ่งค่านี้เราสามารถเปลี่ยนแปลงได้ตามความต้องการครับ


set_tris_b()  เป็นคำสั่งกำหนดให้พอร์ต B เป็นเอาต์พุตทั้งหมดนั่นเอง โดยการกำหนดค่าให้กับฟังก์ชัน set_tris_b() เท่ากับ 0x00 เช่น set_tris_(0x00);


ขั้นตอนที่ 2

เริ่มเขียนโปรแกรมกันเลยครับ



#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,NOPROTECT
#use fast_io(A)
#use fast_io(B)

void main()
{
  char i,j;                                   //  กำหนดตัวแปร i,j
  set_tris_b(0x00);                      //  คำสั่งกำหนดพอร์ต B ให้เป็นพอร์ตเอาต์พุตทั้งหมด
  output_b(0b00000000);            //  คำสั่งเคลียร์พอร์ต B ให้เป็น 0 ทุกบิต
  
  while(true)                              //  คำสั่งวนซ้ำแบบมีเงื่อนไข
        {
           j=1;                               //  กำหนดตัวแปร j=1
           for(i=1;i<=8;i++)           //  คำสั่งทำซ้ำโดยกำหนดให้ i=1,i<=8,i=i+1
              {
                output_b(j);               //  กำหนดให้เอาต์พุตพอร์ต B = j
                j=j<<1;                    //  ให้ตัวแปร j เลื่อนบิตไปทางซ้าย 1 ตำแหน่ง
                delay_ms(1000);        //  คำสั่งหน่วงเวลา 1 วินาที
              }
         }
  } 
       

ตัวอย่าง วิชา ไมโครคอนโทรนเลอร์ ครั้งที่ 1

 ประกอบวงจรตามรูปด้านล่าง ลงในโปรแกรม Proteus ครับ




คำสั่งที่ใช้ในการโปรแกรม

while()  เป็นคำสั่งทำงานซ้ำแบบมีเงื่อนไขครับ ซึ่งจะทำงานวนซ้ำไปเรื่อยๆจนกว่าเงื่อนไขจะเป็นเท็จ

output_x(...)   เป็นคำสั่งส่งข้อมูลออกทางเอาต์พุตในพอร์อตที่ต้องการตามค่าที่กำหนด เช่น output_b(0x01);

delay_ms(...)  เป็นคำสั่งหน่วงเวลา เช่น delay_ms(500); โปรแกรมจะหน่วงเวลา 500ms ซึ่งค่านี้เราสามารถเปลี่ยนแปลงได้ตามความต้องการครับ

set_tris_x()  เป็นคำสั่งกำหนดพอร์ตใช้งานให้พอร์ตอินพุต หรือเอาต์พุต โดยการกำหนดค่าให้กับฟังก์ชัน set_tris_x() เช่น set_tris_b(0x00); , set_tris_a(0xff);


value = input() เป็นคำสั่งอ่านข้อมูลจากพอร์ตอินพุตที่ต้องการ เช่น a=!input(pin_a0);

output_bit()  เป็นคำสั่งส่งข้อมูลออกทางเอาต์พุตในระดับบิต เช่น output_bit(pin_b0,a); 


ขั้นตอนที่ 2

เริ่มเขียนโปรแกรมกันเลยครับ


#include <16F84A.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,NOPROTECT
#use fast_io(A)
#use fast_io(B)


int1 a;                                      //  คำสั่งประกาศตัวแปร a เป็นเลขจำนวนเต็มขนาน 1 บิต

void main()
{
  set_tris_a(0xff);                        //  คำสั่งกำหนดพอร์ต A เป็นพอร์ตอินพุตทั้งหมด
  set_tris_b(0x00);                      //  คำสั่งกำหนดพอร์ต B ให้เป็นพอร์ตเอาต์พุตทั้งหมด
  output_b(0b00000000);            //  คำสั่งเคลียร์พอร์ต B ให้เป็น 0 ทุกบิต

  a=0;                                       //  คำสั่งกำหนดค่า a=0
  
  while(true)                              //  คำสั่งวนซ้ำแบบมีเงื่อนไข
     {
        while(!input(pin_a0))         //  คำสั่งทำซ้ำ โดยรับค่าอินพุตจากพอร์ต a0
           { 
              a=~a;                        //  คำสั่งเปลี่ยนข้อมูล a เป็นตรงกันข้าม
              output_bit(pin_b0,a);   //  คำสั่งส่งข้อมูลออกทางเอาต์พุตขนาด 1 บิต

              while(!input(pin_a0))   //  คำสั่งทำซ้ำ โดยรับค่าอินพุตจากพอร์ต a0
                 {
                   delay_ms(100);     //  คำสั่งหน่วงเวลา 100 ms
                 }      
            }  

      }                                   
}

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

เสนองาน มินิโปรเจค

มินิโปรเจค วิชา เขียนโปรแกรม

แบบจำลองเปิดปิดประตูลานจอดรถ


https://www.youtube.com/watch?v=8KAKrLaRwfQ

วันศุกร์ที่ 8 กุมภาพันธ์ พ.ศ. 2562

ส่วนประกอบงานวิชา เขียนโปรแกรม ตัวอย่างงานที่ 20

ส่วนประกอบงานวิชา  เขียนโปรแกรม ตัวอย่างงานที่ 20

ใบรายงานผลการปฏิบัติงาน

โปรเจคเครื่องรดน้ำต้นไม้อัตโนมัติ ด้วย Arduino  พร้อม Code ตัวอย่าง

เมื่อ 1 สัปดาห์ที่ผ่านมา
โดย เจ้าของร้าน

โปรเจคเครื่องรดน้ำต้นไม้อัตโนมัติ ด้วย Arduino พร้อม Code ตัวอย่าง

ชุดรดน้ำอัตโนมัติด้วย Arduino เป็นต้นแบบให้น้องได้ศึกษาระบบ Smart Farm พื้นฐาน นำไปพัฒนาต่อในอนาคต โดยใช้ Arduino Uno R3 สามารถนำไปพัฒนาใน งาน IOT หรือจะพัฒนาใน แอพพลิเคชั่น Blynk ได้อีกด้วย (โปรเจคนี้จะอยู่ที่ประมาณ 500 บาท)
อุปกรณ์ที่ต้องใช้มีดังต่อไปนี้
สามารถซื้อชุด เซ็ต ได้ที่ 
ในส่วนของวงจรการต่อสายมีดังต่อไปนี้
วงจร รดน้ำต้นไม้อัตโนมัติ ด้วย Arduino
ในส่วนของโปรแกรมตัวอย่าง
const int analogInPin = A5;const int relay = 2;
int sensorValue = 0;        // ตัวแปรค่า Analogint outputValue = 0;        // ตัวแปรสำหรับ Map เพื่อคิด %
void setup() {  Serial.begin(9600);  pinMode(relay, OUTPUT);}
void loop() {  sensorValue = analogRead(analogInPin);
  Serial.print("Soil Moisture = ");  Serial.print(outputValue);  Serial.println(" %");
  if (outputValue <= 40) {  //ตั้งค่า % ที่ต้องการจะรดน้ำต้นไม้    digitalWrite(relay, HIGH);  }
  else {    digitalWrite(relay, LOW);  }  delay(1000);}

ส่วนประกอบงานวิชา เขียนโปรแกรม ตัวอย่างงานที่ 19

ส่วนประกอบงานวิชา  เขียนโปรแกรม ตัวอย่างงานที่ 19

ใบรายงานผลการปฏิบัติงาน

รถบังคับ Rc Car wifi ด้วย Nodemcu esp8266 Arduino IDE ควบคุมผ่านมือถือ android

เมื่อ 1 ปีที่ผ่านมา
โดย เจ้าของร้าน

รถบังคับ Rc Car Nodemcu esp8266 Arduino IDE ควบคุมผ่านมือถือ android
รถบังคับ Rc Car wifi ด้วย Nodemcu esp8266 Arduino IDE ควบคุมผ่านมือถือ android
วันก่อนมีน้องๆ เข้ามาขอคำปรึกษาที่ร้าน โดยเขาจะทำรถบังคับควบคุมผ่าน Wifi ซึ่งบทความส่วนใหญ่ จะเป็นบทความเกี่ยวกับ รถบังคับโดยใช้ Arduino + bluetooth HC06 เป็นหลัก ระบบเดิมที่น้องเขาได้พัฒนา เป็นการควบคุมผ่าน App โดยการเชื่อมต่อ TCP มักจะเจอปัญหา Nodemcu เอ๋อบ้าง ช้าบ้างไม่ทันใจวัยรุ่น เลยให้คำปรึกษาน้องไปว่าให้ใช้ UDP แทน เนื่องจากการส่งข้อมูลของ TCP จะเป็นลักษณะการสนทนา มีการตอบกลับ ทำให้การส่งข้อมูลทำได้ช้ากว่า UDP เนื่องจาก UDP จะส่งข้อมูลออกไปทิศทางเดียวไม่มีการติดต่อกลับมาจึงทำให้มีความเร็งสูงกว่า TCP จากที่ให้คำปรึกษาน้องๆไป เลยนำมาเขียนบทความเรื่องรถบังคับ ผ่าน Wifi ด้วย Nodemcu esp8266 Arduino IDE
มาเริ่มทำกันเลย !
เตรียมอุปกรณ์ 
เพื่อให้เป็นการไม่เสียเวลา ขี้เกียดเขียนเว็บด้วย จึงหา App android ที่ GUI ใช้งานได้ง่ายๆ แล้วมาดัก Packet การส่งเอาเพื่อเอามาใช้กับงานของเราจึงแนะนำ App ที่มีชื่อว่า RC Joystick
RC Joystick
หน้าตาของ App RC Joystick
RC Joystick
หลักการทำงานของรถบังคับดริฟ คันนี้ จะแบ่งออกเป็น 2 ชุดคือ
  1. ชุดบังคับเลี้ยวซ้าย ขวา
  2. ชุดมอเตอร์ขับเคลื่อน เดินหน้า ถอยหลัง 
ถอดวงจรที่มีอยู่ออกมาให้หมดแล้วทำการบัดกรีสายไฟ เลี้ยวซ้ายขวา และเดินหน้า ถอยหลัง 2 เส้นเตรียมไว้ครับ
การต่อวงจรของชุดรถบังคับของเราต่อได้ดังนี้

ส่วนของ Code ของ Nodemcu IDE เราจะใช้ Arduino IDE ในการพัฒนา Code มีดังนี้
/*
Arduino RC Car Drift 
By Pakorn  Rattanaying
https://www.9arduino.com
*/
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
int status = WL_IDLE_STATUS;
const char* ssid = "9arduino";  //  your network SSID (name)
const char* pass = "Pass wifi";       // your network password
unsigned int localPort = 2390;      // Port สำหรับการเชื่อมต่อ
byte packetBuffer[512]; //buffer to hold incoming and outgoing packets
// A UDP instance to let us send and receive packets over UDP
WiFiUDP Udp;
int a;
int b;
int c;
int d;
int pw1;
int pw2;
const int pin1 = D1;
const int pin2 = D2;
const int pin3 = D3;
const int pin4 = D4;
const int pwm1 = D5;
const int pwm2 = D6;
void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  pinMode(pwm1, OUTPUT);
  pinMode(pwm2, OUTPUT);
        digitalWrite(pin1, HIGH);
        digitalWrite(pin2, HIGH);
        digitalWrite(pin3, HIGH);
        digitalWrite(pin4, HIGH);
  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  // setting up Station AP
  WiFi.begin(ssid, pass);
  
  // Wait for connect to AP
  Serial.print("[Connecting]");
  Serial.print(ssid);
  int tries=0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    tries++;
    if (tries > 30){
      break;
    }
  }
  Serial.println();
printWifiStatus();
  Serial.println("Connected to wifi");
  Serial.print("Udp server started at port ");
  Serial.println(localPort);
  Udp.begin(localPort);
}
void loop()
{
  int noBytes = Udp.parsePacket();
  if ( noBytes ) {
    Serial.print(millis() / 1000);
    Serial.print(":Packet of ");
    Serial.print(noBytes);
    Serial.print(" received from ");
    Serial.print(Udp.remoteIP());
    Serial.print(":");
    Serial.println(Udp.remotePort());
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,noBytes); // read the packet into the buffer
      
      /* motor 1 */
      Serial.print("Motor 1 ");
      Serial.print(packetBuffer[2],DEC);
      Serial.print(" ");
      Serial.print(packetBuffer[3],DEC);
      Serial.print(" ");
      a = packetBuffer[2],DEC;
      b = packetBuffer[3],DEC;
      if (a == 255 and b >= 106){     //เลี้ยวซ้าย
        Serial.print(" Left ");
        pw1 = map(b, 255, 106, 0, 255);
        digitalWrite(pin1, LOW);
        digitalWrite(pin2, HIGH);
        }
      else if(a == 0 and b <= 150 and b >= 1){ //เลี้ยวขวา
        Serial.print(" Right ");
        pw1 = map(b, 1, 150, 0, 255);
        digitalWrite(pin2, LOW);
        digitalWrite(pin1, HIGH);
        }
      else{
        Serial.print(" Stop ");
        pw1 = 0;
        digitalWrite(pin1, HIGH);
        digitalWrite(pin2, HIGH);
        }
    Serial.println(pw1);
          /* motor 2 */
    Serial.print("Motor 2 ");
      Serial.print(packetBuffer[6],DEC);
      Serial.print(" ");
      Serial.print(packetBuffer[7],DEC);
      Serial.print(" ");
      c = packetBuffer[6],DEC;
      d = packetBuffer[7],DEC;
      if (c == 255 and d >= 106){     //ถอยหลัง
        Serial.print(" BACK ");
        pw2 = map(d, 255, 106, 0, 255);
        digitalWrite(pin4, LOW);
        digitalWrite(pin3, HIGH);
        }
      else if(c == 0 and d <= 150 and d >= 1){    //เดินหน้า
        Serial.print(" GO ");
        pw2 = map(d, 1, 150, 0, 255);
        digitalWrite(pin3, LOW);
        digitalWrite(pin4, HIGH);
        }
      else{
        Serial.print(" stop ");
        pw2 = 0;
        digitalWrite(pin3, HIGH);
        digitalWrite(pin4, HIGH);
        }
      Serial.print(pw2);
    Serial.println();
  } // end if
}
void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}