การสร้าง Class C++ ที่ใช้เป็นโครงสร้างข้อมูลแบบ Queue (คิว) ลักษณะการทำงานแบบ เข้าก่อนออกก่อน หรือ First In First Out (FIFO)เพื่อใช้งานสำหรับ Arduino
1) เขียนโค้ดสำหรับบอร์ด Arduino โดยสร้างเป็น C++ Class ดังต่อไปนี้
=> Class StringQueue เป็นโครงสร้างข้อมูลแบบ Queue สำหรับเก็บ String objects สร้างคลาส StringQueue และทดสอบการทำงานโดยใช้โค้ดตัวอย่างต่อไปนี้ และทดสอบโดยใช้ฮาร์ดแวร์จริง (ใช้บอร์ด Arduino และแสดงผลผ่าน Serial Monitor ของ Arduino IDE)
=> Class StringQueue เป็นโครงสร้างข้อมูลแบบ Queue สำหรับเก็บ String objects สร้างคลาส StringQueue และทดสอบการทำงานโดยใช้โค้ดตัวอย่างต่อไปนี้ และทดสอบโดยใช้ฮาร์ดแวร์จริง (ใช้บอร์ด Arduino และแสดงผลผ่าน Serial Monitor ของ Arduino IDE)
2) ใช้คลาส StringQueue ในข้อแรก นำมาเขียนโค้ด Arduino เพื่อให้มีพฤติกรรมการทำงานดังนี้ กำหนดให้มีความจุเช่น 10 ข้อความ
2.1) บอร์ด Arduino มีวงจรปุ่มกด Get ทำงานแบบ Active-Low (ใช้ตัวต้านทานแบบ Pull-up, 10k)
2.2) ผู้ใช้สามารถส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่เกิน 16 ตัวอักขระต่อบรรทัด) จากคอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino ใช้ baudrate 115200
2.3) ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringQueue ถ้าไม่เต็มความจุ แต่ถ้าเต็มความจุ ไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "Full" กลับมา และมี LED "Full" ติด
2.4) เมื่อมีการกดปุ่ม Get แล้วปล่อยหนึ่งครั้ง ข้อความแรก (ถ้ามี) ของ StringQueue จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์ และนำไปแสดงผลบนจอ 16x2 LCD ที่ต่อกับบอร์ด Arduino ด้วย แต่ถ้าไม่ข้อความใดๆ Arduino จะต้องส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย และให้มี LED "Empty" ติด
2.5) บรรทัดแรกของ LCD แสดงข้อความที่ถูกอ่านออกมาล่าสุดจาก StringQueue บรรทัดที่สอง ให้แสดงจำนวนข้อความที่มีอยู่ใน StackQueue ในขณะนั้น
2.6) 16x2 LCD module สามารถยืมได้จากห้อง ESL และการเขียนโค้ดเพื่อใช้งาน LCD สามารถใช้ไลบรารี่ของ Arduino ได้ และการเขียนโค้ดเพื่อใช้งาน LCD สามารถใช้ไลบรารี่ของ Arduino ได้
2.2) ผู้ใช้สามารถส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่เกิน 16 ตัวอักขระต่อบรรทัด) จากคอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino ใช้ baudrate 115200
2.3) ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringQueue ถ้าไม่เต็มความจุ แต่ถ้าเต็มความจุ ไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "Full" กลับมา และมี LED "Full" ติด
2.4) เมื่อมีการกดปุ่ม Get แล้วปล่อยหนึ่งครั้ง ข้อความแรก (ถ้ามี) ของ StringQueue จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์ และนำไปแสดงผลบนจอ 16x2 LCD ที่ต่อกับบอร์ด Arduino ด้วย แต่ถ้าไม่ข้อความใดๆ Arduino จะต้องส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย และให้มี LED "Empty" ติด
2.5) บรรทัดแรกของ LCD แสดงข้อความที่ถูกอ่านออกมาล่าสุดจาก StringQueue บรรทัดที่สอง ให้แสดงจำนวนข้อความที่มีอยู่ใน StackQueue ในขณะนั้น
2.6) 16x2 LCD module สามารถยืมได้จากห้อง ESL และการเขียนโค้ดเพื่อใช้งาน LCD สามารถใช้ไลบรารี่ของ Arduino ได้ และการเขียนโค้ดเพื่อใช้งาน LCD สามารถใช้ไลบรารี่ของ Arduino ได้
อุปกรณ์ทดลอง (Apparatus)
อุปกรณ์
|
จำนวน
| |
|
LED 5mm.
|
2
|
|
ตัวต้านทาน 10 กิโลโอห์ม
(น้ำตาล ดำ ส้ม ทอง)
|
1
|
BREADBOARD
บอร์ดทดลองอิเล็กทรอนิกส์
|
1
| |
Arduino Uno R3
|
1
| |
ปุ่มกด
|
1
| |
สาย USB Cable
|
1
| |
สายไฟต่อวงจร
|
-
| |
ตัวต้านทานแบบปรับค่าได้
|
1
| |
16x2 LCD Module
|
1
|
Arduino Sketch (1)
ส่วนแรกเป็นการประกาศคลาสชื่อ StringQueueมีเพียงเมธอดเดียวสำหรับใช้งานเป็น Constructor โดยรับอาร์มิวเมนต์ capacity ตามชนิดข้อมูลแบบ int มีชนิดข้อมูลเป็น boolean เพื่อตรวจสอบความจุของ Queue
// class declaration ---------------------------------------------------------------------------------
#ifndef StringQueue_h #define StringQueue_h #if ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif class StringQueue { public: StringStack( int capacity=10 ); // constructor bool enqueue( String s ); // put a String object on Queue bool dequeue( String &s ); // get a String object from Queue int size_Queue(); // return the number of String objects on the Queue boolean isEmpty(); // return true if Queue is empty, otherwise false boolean isFull(); // return true if Queue is full, otherwise false private: int capacity; // the max. capacity of the Queue int rear; // used to count the number of string objects stored int front; String *buf; // used to store String objects on Queue String array[10 ]; }; #endif
// end class delcaration ---------------------------------------------------------------------------
|
ส่วนที่สองเป็นการสร้างคลาสซึ่งเกี่ยวกับการสร้างเมธอดสมาชิกตามที่ได้ประกาศไว้ในส่วนแรก ให้สังเกตวิธีการอ้างอิงชื่อเมธอดสมาชิก
// class implementation----------------------------------------------------------------------------
#include "StringQueue.h" StringQueue::StringQueue( int capacity ) { capacity = capacity; rear = 0; front = 0; } //constructor ของ class bool StringQueue::enqueue( String s ) { if(rear >= 10 && front >= 10){ rear =0; front =0; } if ( isEmpty() ) { array[rear] = s; rear ++; return true; } else { return false; } } bool StringQueue::dequeue( String &s ) { if ( front < 10 && front < rear) { String *buf = &s; *buf = array[front]; front ++; return true; } else { return false; } } int StringQueue::size_queue() { return rear-front; } boolean StringQueue::isEmpty() { if(rear < 10){ return true; }else{return false;} } boolean StringQueue::isFull() { if(rear == capacity){ return true; }else{return false;} } // end class implementation---------------------------------------------------------------------- |
ในส่วนนี้ จะอธิบายโค้ดได้ดังนี้
StringQueue(
int capacity ) คือ constructor ของ class
enqueue(
String s ) : เป็นการใส่ข้อความ ลงใน Queue โดย rear คือ ตำแหน่งที่จะใส่ โดย rear จะเพิ่มค่าไปเรื่อยๆ ถ้ามีการใส่ข้อความ โดยที่ถ้า rear >=10 และ front >=10 จะทำการรีเซตค่าของทั้งสองตัวเป็นค่าเริ่มต้น
dequeue( String &s ) : เป็นการ
นำค่าของตำแหน่ง front ออก
โดยต่ำแหน่งแรกคือตำแหน่ง 0 และจะเพิ่มค่าไปเรื่อยๆ
ถ้ามีการ dequeue โดยที่ค่า front ต้องน้อยกว่า rear เสมอ ถึงจะทำการ dequeue ได้ Dequeue คือการเอาข้อความที่เข้าก่อน ออก
size_queue()
: เป็นการหาขนาดของ queue
isEmpty()
: ตรวจสอบ queue ไม่มีความจุหรือไม่
isFull()
: ตรวจสอบ queue มีความจุเต็มหรือไม่
ส่วนที่สามเกี่ยวข้องกับการเขียนโค้ดทดสอบ (ไม่เกี่ยวข้องกับการนิยามและสร้างคลาส) โดยสร้างออปเจคจากคลาส StringQueue เขียนได้ดังนี้
// test code Problem1 -----------------------------------------------------------------------------
#include <StringQueue.h> int num = 10; // capacity StringQueue st( num ); void setup() { Serial.begin(115200); //ตั้งค่า Baudrate } char buf[20]; String str; void loop() { Serial.print( "\nEnqueue strings: " ); for ( int i = 0; i < num; i++ ) { str = String( (i + 1) * 10 ); if ( !st.enqueue( str ) ) { Serial.println( "\nEnqueue string error!" ); break; } else { Serial.print( str ); Serial.print( " " ); } str = ""; delay(50); } delay(500); Serial.print( "\nDequeue strings: " ); for ( int i = 0; i < num; i++ ) { if ( st.dequeue( str ) ) { str.toCharArray( buf, 20 ); Serial.print( buf ); Serial.print( " " ); } else { Serial.println( "\nDequeue string error!" ); break; } delay(50); } delay(500); } // end test code Problem1------------------------------------------------------------------------ |
เมื่อได้ทดลองการทำงานแล้ว ก็สามารถนำโค้ดดังกล่าว มาจัดแบ่งเป็นไฟล์ StringQueue.h สำหรับส่วนที่ประกาศคลาส และ StringQueue.cpp สำหรับส่วนที่สร้างคลาส และเก็บไฟล์ทั้งสองไว้ในไดเรคทรอรี่ชื่อเดียวกับคลาส ในการนำไปใช้งาน โค้ด Arduino Sketch ที่จะใช้คลาสดังกล่าว จะต้องประกาศการใช้งานดังนี้ #include<StringQueue.h>
ไฟล์ StringQueue.h , StringQueue.cpp สำหรับนำไปใช้งานในลักษณะที่เป็นไลบรารี่สำหรับ Arduino ใส่ไว้ภายใต้ไดเรคทรอรี่ชื่อ libraries ของ Arduino IDE)
โค้ดนี้ เป็นการทดสอบการทำงานของ queue โดยให้ queue เก็บค่า 10,20,30 บวกเพิ่มไปทีละ 10 จนกระทั่งครบ 100 เสร็จแล้วจะทำการ dequeue ออกมา
คือนำข้อความตัวแรกสุดที่เข้าไปก่อน ออกมาก่อน จนกระทั่งถึงตัวสุดท้าย
และทำอย่างนี้ไปเรื่อยๆ
ผลการทดลองการทำงาน (1)
Arduino Sketch (2)
การเขียนโค้ดทดสอบ โดยสร้างออปเจคจากคลาส StringQueue ให้มีคุณสมบัติตรงกับโจทย์สำหรับการทดลองข้อ 2 เขียนได้ดังนี้
// test code Problem2 -----------------------------------------------------------------------------
#include <StringQueue.h> #include <LiquidCrystal.h> int num = 10; // capacity StringQueue st( num ); LiquidCrystal lcd(12,11,5,4,3,2); int check=0; char count1; int nub =0; String count; char buf[16]; String buff; String str,str1; //button int empty_ledPin = 7; // กำหนด pin สำหรับ LED เมื่อ Queue ว่าง int full_ledPin = 8; // กำหนด pin สำหรับ LED เมื่อ Queueเต็ม int button_Pin = 6; // กำหนด pin สำหรับปุ่ม int button = 0; //กำหนดตัวแปรรับค่าจากปุ่ม ค่าเป็น 0 int state=0; void setup() { Serial.begin(115200); pinMode(empty_ledPin, OUTPUT); // กำหนดหน้าที่ของ pin led pinMode(full_ledPin, OUTPUT); pinMode(button_Pin, INPUT); // กำหนดหน้าที่ของ pin ปุ่ม lcd.begin(16,2); } void loop(){ button = digitalRead(button_Pin); while(Serial.available()>0){ count1 = (char)Serial.read(); count = count + count1; if(count1 == '\n'){ check=1; } } if(check==1){ str = count; str = str.substring(0,count.length()-1); str = str.substring(0,15); check=0; count =""; nub=0; if ( !st.enqueue( str ) ) { Serial.print( "\nFull" ); Serial.println(' '); lcd.setCursor(0,0); lcd.clear(); lcd.write("FULL"); digitalWrite(full_ledPin,HIGH); } else { digitalWrite(empty_ledPin, LOW); Serial.print( "\nEnqueue strings: " ); Serial.print( str ); delay(100); } delay(50); } //BUTTON if (button == LOW) { //Active LOW state=1; } if(state==1 && button==HIGH){ state=0; digitalWrite(full_ledPin, LOW); if ( !st.dequeue( str ) ) { Serial.print( "\nEMPTY" ); lcd.setCursor(0,0); lcd.clear(); lcd.write("EMPTY"); digitalWrite(empty_ledPin,HIGH); delay(100); } else { str.toCharArray( buf, 16 ); Serial.print( "\nDuqueue strings: " ); Serial.print( buf ); buff=buf; lcd.setCursor(0,0); lcd.clear(); lcd.print(buff); } delay(50); } lcd.setCursor(0,1); lcd.print(st.size_queue()); } // end test code Problem2------------------------------------------------------------------------ |
ผลการทดลองการทำงาน (2)
ในส่วนนี้ จะอธิบายโค้ดได้ดังนี้
ในคำสั่ง
void
loop(); ส่วนนี้ เป็นส่วนที่ดูว่ามีการส่งค่ามาจาก Serial port มายังบอร์ด หรือไม่โดยจะรับมาเป็น char คือทีละตัว จนครบข้อความที่ส่งมา โดยข้อความสุดท้ายที่ส่ง จะลงท้ายด้วย \n เสมอ เพราะมีการกด enter แล้วจึงให้ไปทำขั้นตอนต่อไป
ในเงื่อนไขการตรวจเช็ค Check() ใน state นี้ จะทำการตรวจเช็คว่า
ข้อความที่รับมานั้น เกิน 16 ตัวอักษรหรือไม่
ถ้าเกินจะทำการตัดออกให้เหลือแค่ 16 ตัวอักษร แล้วจะนำไปใส่ queue และมีการ แสดงข้อความที่ Serial monitor ซึ่งถ้า queue เต็ม จะมีคำว่า Full ปรากฏ บนหน้าจอ Serial
monitor และหน้าจอ LCD แล้วไฟก็จะเป็น HIGH
button() ปุ่มกด คือเมื่อกดเป็น low จะไปยังstate ต่อไป เมื่อมายังstate ถัดมา คือกดแล้วปล่อย จะมีการทำงานโดยปุ่มกดนี้ จะเป็นการ dequeue คือ นำข้อความที่ใส่เข้าไปแรกสุดออกมาจากqueue มาแสดงบนหน้าจอ Serial monitor และ LCD โดยจะทำไป เรื่อยๆ ถ้ามีการกดและปล่อยอีก แต่ถ้า ในqueue ว่าง ก็จะ มีคำว่า “EMPTY” แสดงบนหน้าจอ Serial monitor และ LCD และไฟอีกดวงก็จะเป็น High และในทุกครั้งที่มีการทำงาน
จะมีการแสดง ขนาดของ queue บนหน้าจอ LCD เสมอไป
การทำงานของโค้ดทดสอบ
ส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่เกิน 16 ตัวอักขระต่อบรรทัด) จากคอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringQueue (เก็บไว้ในคิว)
ถ้าเต็มความจุที่กำหนดไว้ จะไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "Full" กลับมายังคอมพิวเตอร์ และนำไปแสดงผลบนจอ 16x2 LCD ที่ต่อกับบอร์ด Arduino
กดปุ่มแล้วปล่อยหนึ่งครั้ง ข้อความแรก (ถ้ามี) ของ StringQueue จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์ และนำไปแสดงผลบนจอ 16x2 LCD ที่ต่อกับบอร์ด Arduino ด้วย แต่ถ้าไม่มีข้อความใดๆ Arduino จะส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย และให้มี LED "Empty" ติด บรรทัดแรกของ LCD แสดงข้อความที่ถูกอ่านออกมาล่าสุดจาก StringQueue บรรทัดที่สอง ให้แสดงจำนวนข้อความที่มีอยู่ใน StackQueue ในขณะนั้น