Arduino Tutorial 2 : สื่อสารด้วย Serial

Posted by | February 1, 2011 | Tutorial | 12 Comments

มารอบนี้ ขอเริ่มด้วยพูดเรื่องการสื่อสารระหว่างคอมพิวเตอร์กับ arduino กันบ้าง ที่ทางผมเอาเรื่องนี้มาพูดก่อน เพราะว่าการข้อความ หรือ Text message มันนำจะทำให้ไมโครส่งค่าภายในออกมาแสดงผลได้ เข้าใจง่าย และการสื่อสารจะเป็นการสื่อสารสองทาง จะส่งจาก arduino ไปยังคอมพิวเตอร์ หรือ จะส่งจากคอมพิวตอร์ เข้าไปสั่งงาน arduino ก้อทำได้ครับ

สำหรับในไมโครคอนโทรลเลอร์ เรายังใช้ Serial ในการเชื่อมต่ออุปกรณ์อื่นอีกด้วย ไม่ว่าจะเป็นข้อมูลพิกัดอย่าง GPS ,อ่านบัตร RFID และอุปกรณ์ออกแบบเฉพาะงานอย่างเช่น Serial LCD character สำหรับแสดงผล และ Serial Servo Control สำหรับงานควบคุมมอเตอร์ servo จำนวนมากๆ

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

การสื่อสารแบบอนุกรม หรือ Serial เป็นส่งข้อมูล โดยใช้เทคนิคการเลื่อนข้อมูล (Shift Bit) ส่งไปที่ล่ะบิต บนสายสัญญาณเส้นเดียว โดยการส่งข้อมูลแบบ Serial จะไม่มีการ sync สัญญาณนาฬิการะหว่างตัวรับและตัวส่ง แต่จะอาศัยวิธีตั้งค่าความเร็วในการรับส่งสัญญาณให้เท่ากั น หรือ เรียกว่าตั้งค่า baud rate และส่งสัญญาณ start และ stop เพื่อบอกว่า เป็นส่วนต้นของข้อมูล (start bit) หรือ ส่วนท้ายของข้อมูล (stop bit) ดังรูป

รูปแบบของ ข้อมูลจากที่ส่งผ่าน Serial จะมีการเพิ่ม Start bit และ Stop bit เข้าไปเพิ่มจากข้อมูลเดิม

  1. บิตเริ่มต้น (Start bit) จะมีขนาด 1 บิต จะเป็นลอจิก LOW
  2. บิตข้อมูล (Data bit) 8 บิต ข้อมูลที่จะส่ง
  3. บิตภาวะคู่หรือคี่ (Parity bit) มีขนาด 1 บิต ใช้ตรวจสอบข้อมูล ถ้าข้อมูลที่ได้รับไม่สมบูรณ์ นำเข้าค่ามา check กับ Parity bit จะได้ค่าไม่ตรงกัน
  4. บิตหยุด (Stop bit) เป็นการระบุถึงขอบเขตของการสิ้นสุดข้อมูล จะเป็นลอจิก HIGH

เอาล่ะครับ ผมเล่าเรื่องทฤษฏี ไม่รู้หลับไปหรือยังที่กล่าวมา ก้อเพื่อให้เข้าใจหลักการเบื้องต้นครับ สำหรับการสื่อสารกับคอมพิวเตอร์ Arduino จะมีโมดุล hardware และมี library ภายใน ที่จัดการเรื่อง Serial อยู่แล้ว เราไม่ต้องสนใจสิ่งที่ทำในส่วนระดับล่าง หรือ ระดับ Hardware  แต่เรามาสนใจสิ่งที่ทำบนระดับสูงเลยว่า เราจะต้องส่ง รับค่าอะไร และต้องตั้งค่าอัตราเร็วในการส่งให้เท่ากัน หรือ ตั้งค่า baud rate เท่าไร แค่นี้เราก้อรับส่งข้อมูลกับคอมพิวเตอร์ได้แล้ว

รู้จักคำสั่งของ Arudino ที่ใช้ใน serial

  1. void serial.begin(rate) กำหนดอัตราบอดของการรับส่งข้อมูล หน่วยเป็นบิตต่อวินาที่ (bits per second :bps baud rate)
  2. int serial.available() ใช้ตรวจสอบว่า buffer รับข้อมูลไว้หรือไม่ โดยจะคืนค่าจำนวนไบต์ที่อยู่ในบัฟเฟอร์
  3. int serial.read() ส่งค่าที่รับจากพอร์ตอนุกรมออกมา (Serial)
  4. void Serial.flush() เคลียร์บัฟเฟอร์ของพอร์ตอนุกรม(Serial) ให้ว่าง
  5. void Setial.print() พิมพ์ข้อมูล ออกทางพอร์ตอนุกรม
  6. void Setial.println() พิมพ์ข้อมูล ออกทางพอร์ตอนุกรม แต่ขั้นบรรทัดใหม่ด้วย

<Lab-4> คุยกับคอมพิวเตอร์

เรามาลองเอาง่ายๆกัน ครับ โดยตัวอย่างแรกให้ทดลองส่งข้อมูลดูก่อนครับ ไม่กี่บรรทัด ก็เสร็จแล้วพิมพ์ตามกันไปเลย ตามตัวอย่างข้างล่างนี้

int counter = 0;

void setup() {
 Serial.begin(9600);
 Serial.println("Hello Serial");
 delay(100);
}

void loop() {
 counter++;

 Serial.println(counter);

 if (counter == 25)  {
 counter = 0;
 }

 delay(100);
}

หลังจาก Upload sketch นี้ ให้เปิด Serial Monitor นะครับ แล้วเลือกจะเห็นข้อความขึ้นมาเป็น คำทักทาย “Hello Serial “ และ ตามด้วยตัวเลข 1 ถึง 25 แต่ถ้ามันขึ้นมาเป็นภาษาแปลกๆ ก้อแสดงว่า ความเร็วในการรับส่งข้อมูลของ arduino กับ computer อาจจะไม่ตรงกัน ควรจะตั้งค่าควรตั้งค่า baud rate กันใหม่ครับ

ถ้าใครรู้สึกว่า ตั้งค่า BaudRate แก้ไขที่นี้ครับ ในช่อง Serial Monitor ทางขวาจะมีช่องค่า Baudrate เลือกค่าที่ถูกต้องในตามโปรแกรม ค่าความเร็วกับรับส่งจะเป็นตัวเลขลงตัว 600, 1200, 4800, 9600, 19200, 38400, 57600, 1115200 ปกติเราจะใช้ค่า 9600


 

สิ่งที่อยากให้ลองคือ ภายในฟังก์ชั่น Serial.println( value ,format)  สามารถจะส่งค่า ออกมาในรูปแบบอื่นได้ ไม่ว่าจะเป็น แบบตัวอักษร(BYTE), เลขฐานสอง(BIN), เลขฐานแปด(OCT), เลขฐานสิบ(DEC), เลขฐานสิบหก(HEX), ข้อความ ลองเปลี่ยน Serial.println(counter); เป็น Serial.println(counter, BYTE) และอื่นๆ ดูตามตัวอย่างข้างล่าง

Serial.println (78, BYTE)                                  “N”

Serial.println (78, BIN)                                    “1001110”

Serial.println (78, OCT)                                   “116″

Serial.println (78, DEC)                                   “78”

Serial.println (78, HEX)                                   “4E”

Serial.println(1.23456, 0)                                 “1”

Serial.println(1.23456, 2)                                 “1.23”

Serial.println(1.23456, 4)                                 “1.2346”

<Lab-5> ส่งกลับจากคอมพิวเตอร์ไป Arduino บ้าง

หลังจากที่เราส่งออกไปได้แล้ว มาทดลองรับค่าจากคอมพิวเตอร์บ้าง วิธีการรับข้อมูลเข้าจากคอมพิวเตอร์ arduino จะใช้ฟังก์ชั่น Serial.Read() ซึ่งในตัวอย่างนี้ช่วยให้เข้าใจมากขึ้น หลังจาก upload อย่าลืม เปิด Serial Monitor แล้วทดลองตามล่ะ

int incomingByte = 0;
void setup() {
    Serial.begin(9600);
    Serial.println("Hello ,type something");
}

void loop() {
     if (Serial.available() > 0) {
         incomingByte = Serial.read();
         Serial.print ("> ");
         Serial.println (incomingByte,BYTE);
     }
}

serial.read() จะเป็นฟังก์ชั่น ที่คืนค่ารับมาจาก serial ซึ่งในที่นี้เป็นตัวอักษร จะนำมาใช้งานเราจึงต้องประกาศตัวแปร มารับค่า และนำค่าไปประมวลผลต่อไป สำหรับในโปรแกรมนี้ เราได้รับค่า และพิมพ์ค่าออก Serial Monitor โดยเพิ่ม “>” เข้าไปข้างหน้าด้วย

<Lab-6> ควบคุมไฟกระพริบด้วย Serial

หลังจากที่เราควบคุมไฟกระพริบเบื้องต้นไปได้แล้ว ในตอนที่ 1 มาตอนนี้เราจะให้ลองทำ ไฟกระพริบควบคุมจากคอมพิวเตอร์ได้อย่างง่ายครับ โดยการส่งตัวอักษร “a” เพื่อทำให้ LED มันกระพริบ

int incomingByte = 0;
int ledPin = 13;

void setup() {
   Serial.begin(9600);
   Serial.println ("Type 'a' for blinky");
}

void loop() {
    if (Serial.available() > 0)     {
          incomingByte = Serial.read();
          Serial.print ("> ");
          Serial.println (incomingByte,BYTE);

          if (incomingByte == 'a') {
              Blinky();
          }
    }
} 

void Blinky(void) {
     digitalWrite(ledPin, HIGH);  // set the LED on
     delay(250);                  // wait for a second
     digitalWrite(ledPin, LOW);   // set the LED off
     delay(250);                  // wait for a second
}

วิธีการใช้งาน หลังจากเขียนโปรแกรมเสร็จ เปิด serial monitor แล้วใส่ค่าตัวอักษร ‘a’ ลงไป จะเห็นว่าไฟกระพริบทำงานได้ และพิมพ์ข้อความกลับมาว่า “test blinky” ดูภาพประกอบไปด้วย

น่าจะเป็นตัวอย่างให้กับเพื่อนๆที่กำลังอยากทำอุปกรณ์ ควบคุมผ่านคอมได้นะครับ ถ้าเปลี่ยนจาก LED เป็น Relay สามารถเปิดปิดอุปกรณ์ที่ใหญ่กว่านี้ได้แล้ว สำหรับการใช้งานจริงเราอาจจะออกแบบการรับคำสั่งที่เป็นรูปแบบ protocol ซึ่งจะเอาไว้กล่าวต่อไปครับ

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

About chang

ชื่อ “ช้าง” ส่วนมากเขาจะเรียกว่า “พี่ช้าง” แล้ว มีความสนใจทางเทคโนโลยีทางคอมพิวเตอร์ อิเล็กทรอนิกส์ และ หุ่นยนต์ เป็นทั้งนักคิด นักประดิษฐ์ ชอบทดลองเล่น จนเดี่ยวนี้รู้สึกว่าจะเล่นมากกว่ามืออาชีพไปสักแล้ว

  • Ohm_pamong

    ควบคุมไฟกระพริบด้วย serial run ไม่ติดครับ โปรแกรมบอกว่า stray ” in program

    • อันนี้ตั้งแต่คอมไพล์ หรือว่าใช้โปรแกรมครับ

  • Bobswm

    พี่ช้างครับ ตอนที่ 3 ต่อจากนี้มีอีกไหนครับ
    ช่วงปิดเทอมนี้ผมขอติดตาม จะลุยจริงจังๆอ่ะครับ
    ขอฉบับแปลของ jeremy ตอนที่สองได้ไหมครับ อิๆ

    • ภายในอาทิตย์นี้ล่ะครับ ช่วงนี้ไปฝึกภาษาปะกิตกับ ตานู่ Jeremy กันไปก่อนนะครับ

  • Karoct_70_kittipong007

    ^^

  • suriya chaisiri

    รบกวนนะครับ ตอน Compile  ขึ้นว่า ” The Byte is no longer support ”
    ผมควรแก้ไขยังไงครับ ขอบคุณครับ

  • Kaek Prompong

    ขอ like แรงๆๆ

  • Nut Rmutp

    มันขึ้น error ตรง บรรทัดนี้นะครับ Serial.println (incomingByte,BYTE); เหมือนมันไม่รู้จัก sketch_oct20a.ino: In function ‘void loop()’:
    sketch_oct20a:13: error: ‘BYTE’ was not declared in this scope

    • ตั้งแต่ arduino v1.0 ขึ้นไป ได้เอาตัวแปรแบบ BYTE ออกไปครับ

  • Nut Rmutp

    สัหรับคนที่errorหรือcompile ไม่ได้ให้เปรี่ยน BYTEเป็นBIN มันจะสามารถcompileได้และใช้งานได้ปกติ

  • ART

    ตอน Compile ขึ้นว่า ” The Byte is no longer support ”
    ขอวิธีแก้ไขเพื่อน ๆ ใครแก้ไขได้ช่วยแจ้งหน่วยครับ ของคุณครับ

  • Vichagorn Lupponglung

    สอบถามหน่อยครับทำไม “void Serial.flush() เคลียร์บัฟเฟอร์ของพอร์ตอนุกรม(Serial) ให้ว่าง” ไม่ได้ผลครับ
    ผมใช้ Arduino Uno เท่าที่ลองใช้คำสั่ง flush() ดูเหมือนมันไม่ส่งผลอะไรเลยครับตัว Serial.available() ก็ยังคืนค่าเท่าเดิมอยู่ครับ