- เขียนโค้ดสำหรับบอร์ด Arduino โดยสร้างเป็น C++ Class ดังต่อไปนี้ => Class StringQueue เป็นโครงสร้างข้อมูลแบบ Queue สำหรับเก็บ String objects สร้างคลาส StringQueue และทดสอบการทำงานโดยใช้โค้ดตัวอย่างต่อไปนี้ และทดสอบโดยใช้ฮาร์ดแวร์จริง (ใช้บอร์ด Arduino และแสดงผลผ่าน Serial Monitor ของ Arduino IDE)
- ใช้คลาส StringQueue ในข้อแรก นำมาเขียนโค้ด Arduino เพื่อให้มีพฤติกรรมการทำงานดังนี้ กำหนดให้มีความจุเช่น 10 ข้อความ
- บอร์ด Arduino มีวงจรปุ่มกด Get ทำงานแบบ Active-Low (ใช้ตัวต้านทานแบบ Pull-up, 10k)
- ผู้ใช้สามารถส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่เกิน 16 ตัวอักขระต่อบรรทัด) จาก คอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino ใช้ baudrate 115200
- ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringQueue ถ้าไม่เต็มความจุ แต่ถ้าเต็มความจุ ไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "Full" กลับมา และมี LED "Full" ติด
- เมื่อมีการกดปุ่ม Get แล้วปล่อยหนึ่งครั้ง ข้อความแรก (ถ้ามี) ของ StringQueue จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์ และนำไปแสดงผลบนจอ 16x2 LCD ที่ต่อกับบอร์ด Arduino ด้วย แต่ถ้าไม่ข้อความใดๆ Arduino จะต้องส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย และให้มี LED "Empty" ติด
- บรรทัดแรกของ LCD แสดงข้อความที่ถูกอ่านออกมาล่าสุดจาก StringQueue บรรทัดที่สอง ให้แสดงจำนวนข้อความที่มีอยู่ใน StackQueue ในขณะนั้น
- การเขียนโค้ดเพื่อใช้งาน LCD สามารถใช้ไลบรารี่ของ Arduino ได้
ผลการทดลอง
หลังจากได้ทำการออกแบบการทำงานของวงจรแล้ว จึงดำเนินการแบ่งโค้ดสำหรับ class StringQueue ออกเป็น 2 ไฟล์ คือ StringQueue.h และ StringQueue.cpp ซึ่งมีรายละเอียดดังต่อไปนี้
- ไฟล์ StringQueue.h ใช้สำหรับการประกาศคลาส, ฟังก์ชัน และตัวแปรต่างๆ ที่ต้องการใช้งาน
// class declaration #ifndef StringQueue_H #define StringQueue_H #include <String.h> using namespace std; #include <stdbool.h> #include <inttypes.h> #if ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif class StringQueue { private: int capacity; // the max capacity of the queue int count; // used to count the number of string object stored int in; // used to count index for add String object int out; // used to count index for get String object String *buf; // used to store String object in queue public: StringQueue(int capacity = 10); // constructor method bool enqueue(String s); // add a String object in queue bool dequeue(String &s); // get a String object from queue int size(); // return the number of String object in the queue bool isEmpty(); // return true if stack is empty, otherwise false bool isFull(); // return true if stack is Full, otherwise false }; #endif;
การทำงานของโค้ด
- ในส่วน private
- ประกาศตัวแปรแบบ int ชื่อ capacity ใช้สำหรับระบุขนาดของ queue
- ประกาศตัวแปรแบบ int ชื่อ count ใช้สำหรับนับจำนวน String object ที่มีอยู่ใน queue
- ประกาศตัวแปรแบบ int ชื่อ in ใช้สำหรับระบุ index ในการเพิ่ม String object ลงใน queue
- ประกาศตัวแปรแบบ int ชื่อ out ใช้สำหรับระบุ index ในการนำ String object ออกจาก queue
- ประกาศตัวแปร pointer แบบ String ชื่อ buf ใช้สำหรับเก็บข้อมูล String object ใน queue
- ในส่วน public
- ประกาศฟังก์ชันชื่อ StringQueue เป็น constructor method สำหรับสร้าง object และรับค่าเป็น int ใช้สำหรับกำหนดขนาดของ queue
- ประกาศฟังก์ชันชื่อ enqueue แล้วรับค่าเป็น String ใช้สำหรับการเพิ่ม String object ลงใน queue ถ้าเพิ่มได้สำเร็จจะ return ค่าเป็น true แต่ถ้าไม่สามารถเพิ่มได้จะ return ค่าเป็น false
- ประกาศฟังก์ชันชื่อ dequeue แล้วรับค่าเป็นที่อยู่ของ String ใช้สำหรับการนำ String object ออกจาก queue แล้วนำค่าที่ได้ไปเป็นข้อมูลของ String ตามที่อยู่ที่รับเข้ามา ถ้าสามารถนำค่าออกจาก queue ได้สำเร็จจะ return ค่าเป็น true แต่ถ้าไม่สามารถนำค่าออกจาก queue ได้จะ return ค่าเป็น false
- ประกาศฟังก์ชันชื่อ size ใช้สำหรับบอกจำนวน String object ที่มีอยู่ใน queue
- ประกาศฟังก์ชันชื่อ isEmpty ใช้สำหรับบอกว่า queue นั้นว่างอยู่หรือไม่ ถ้าหากว่า queue ไม่มีข้อมูลอยู่เลยจะ return ค่าเป็น true แต่ถ้าหากใน queue มีข้อมูลอยู่ก็จะ retuen ค่าเป็น false
- ประกาศฟังก์ชันชื่อ isFull ใช้สำหรับบอกว่า queue นั้นเต็มหรือไม่ ถ้าหากว่า queue มีข้อมูลอยู่จนเต็มจะ return ค่าเป็น true แต่ถ้าหาก queue ยังมีที่ว่างอยู่จะ return ค่าเป็น false
- ไฟล์ StringQueue.cpp สำหรับการนำฟังก์ชันต่างๆ ที่ประกาศไว้ในไฟล์ StringQueue.h มาสร้างให้ฟังก์ชันเหล่านั้นสามารถทำงานตามฟังก์ชันการทำงานที่กำหนดไว้
#include "StringQueue.h" StringQueue::StringQueue(int capacity){ this->capacity = capacity; count, in, out = 0; buf = new String[capacity]; } bool StringQueue::enqueue(String s){ if (!isFull()){ *(buf + in) = s; count += 1; in += 1; if (in == capacity){ in = 0; } return true; } else { return false; } } bool StringQueue::dequeue(String &s){ if (!isEmpty()){ s = *(buf + out); count -= 1; out += 1; if (out == capacity){ out = 0; } return true; } else { return false; } } int StringQueue::size(){ return count; } bool StringQueue::isEmpty(){ if (in == out && count <= 0){ return true; } else { return false; } } bool StringQueue::isFull(){ if (in == out && count >= capacity){ return true; } else { return false; } }
สำหรับในไฟล์ StringQueue.cpp เราจะเขียนโค้ดของแต่ละฟังก์ชันเพื่อให้สามารถทำงานได้ตามที่กำหนดไว้ในไฟล์ StringQueue.h
หลังจากที่สร้างไฟล์ StringQueue.h และไฟล์ StringQueue.cpp แล้ว จึงใช้โค้ดสำหรับ Arduino ดังต่อไปนี้เพื่อทดสอบการทำงานของ class StringQueue ที่สร้างขึ้น
โค้ด Arduino สำหรับการทดสอบ class StringQueue
#include "StringQueue.h" int num = 10; //capacity StringQueue st(num); void setup(){ Serial.begin(115200); } char buf[20]; String str; void loop(){ Serial.print("\nAdd strings: "); for(int i=0; i<num; i++){ str = String((i+1)*10); if (!st.enqueue(str)){ Serial.println("\nAdd string error!"); break; }else{ Serial.print(str); Serial.print(" "); } str = NULL; delay(50); } delay(500); Serial.print("\nGet strings: "); for(int i=0; i<num; i++){ if(st.dequeue(str)){ str.toCharArray(buf, 20); Serial.print(buf); Serial.print(" "); }else{ Serial.println("\nGet string error!"); break; } delay(50); } delay(500); }
สำหรับโค้ดทดสอบ class StringQueue นี้จะสร้าง queue ที่มีขนาด 10 แล้วทำการเพิ่มข้อมูลลงใน queue เป็นข้อความตัวเลขคือ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 แล้วค่อยนำข้อมูลใน queue ออกมาทีละตัวเพื่อดูว่าลำดับในการนำข้อมูลออกถูกต้องหรือไม่ ซึ่งเอาต์พุตที่ได้จากการทดสอบได้ดังภาพด้านล่าง
ภาพเอาต์พุตจาก Serial Monitor สำหรับการทดสอบ class StringQueue |
จากภาพเอาต์พุตที่ได้แสดงให้เห็นลำดับของการนำข้อมูลใส่ลงใน queue และลำดับของการนำข้อมูลออกจาก queue ซึ่งมีความสอดคล้องกัน โดยข้อมูลที่ถูกเพิ่มลงไปก่อนจะถูกนำออกมากจาก queue ก่อน และข้อมูลที่ถูกเพิ่มไปทีหลังจะถูกนำออกมาจาก queue ทีหลัง
หลังจากที่ได้ทำการทดสอบ class StringQueue แล้วพบว่ามีการเพิ่มข้อมูลใน queue และนำข้อมูลออกจาก queue ได้อย่างถูกต้องแล้ว เราจึงดำเนินการสร้างโค้ดสำหรับ Arduino เพื่อให้ทำงานได้ตามฟังก์ชันต่อไปนี้
- มีวงจรปุ่มกด Get ทำงานแบบ Active-Low (ใช้ตัวต้านทานแบบ Pull-up, 10k)
- ผู้ใช้สามารถส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่เกิน 16 ตัวอักขระต่อบรรทัด) จาก คอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino ใช้ baudrate 115200
- ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringQueue ถ้าไม่เต็มความจุ แต่ถ้าเต็มความจุ ไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "Full" กลับมา และมี LED "Full" ติด
- เมื่อมีการกดปุ่ม Get แล้วปล่อยหนึ่งครั้ง ข้อความแรก (ถ้ามี) ของ StringQueue จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์ และนำไปแสดงผลบนจอ 16x2 LCD ที่ต่อกับบอร์ด Arduino ด้วย แต่ถ้าไม่ข้อความใดๆ Arduino จะต้องส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย และให้มี LED "Empty" ติด
- บรรทัดแรกของ LCD แสดงข้อความที่ถูกอ่านออกมาล่าสุดจาก StringQueue บรรทัดที่สอง ให้แสดงจำนวนข้อความที่มีอยู่ใน StackQueue ในขณะนั้น
#include <StringQueue.h> #include "Wire.h" #include "LiquidCrystal_I2C.h" LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display StringQueue textarray(5); String recieved_text = ""; String str = NULL; int Full = 8; int Empty = 9; int buttonState = HIGH; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin // the following variables are long's because the time, measured in miliseconds, // will quickly become a bigger number than can be stored in an int. long lastDebounceTime = 0; // the last time the output pin was toggled long debounceDelay = 100; // the debounce time; increase if the output flickers void setup() { Serial.begin(115200); lcd.init(); lcd.backlight(); pinMode(INPUT,4); pinMode(OUTPUT,5); pinMode(OUTPUT,7); delay(5); Serial.println("start"); } void loop() { while (Serial.available()) { delay(30); char c = Serial.read(); //gets one byte from serial buffer recieved_text += c; } if (recieved_text.length() > 0) { if(recieved_text.length() > 16){ recieved_text = recieved_text.substring(0,16); } if(!textarray.enqueue(recieved_text)){ Serial.println("FULL"); str = "FULL"; digitalWrite(Full,HIGH); } else { Serial.println("recieve " + recieved_text); str = ""; digitalWrite(Full,LOW); digitalWrite(Empty,LOW); } recieved_text = ""; //clears text for new text } int get_button = digitalRead(4); // If the switch changed, due to noise or pressing: if (get_button != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } // *************debouce state************** if ((millis() - lastDebounceTime) > debounceDelay) { // if the button state has changed: if (get_button != buttonState) { buttonState = get_button; //if the new button state is HIGH if (buttonState == HIGH) { if(!textarray.dequeue(str)){ Serial.println("Empty"); digitalWrite(Empty,HIGH); str = "Empty"; } else { Serial.println("get " + str); digitalWrite(Empty,LOW); digitalWrite(Full,LOW); } } } } lastButtonState = get_button; lcd.clear(); lcd.print(str); lcd.setCursor(0, 1); lcd.print(textarray.size()); delay(10); }
หลังจากเขียนโค้ดสำหรับ Arduino แล้ว จึงทำการต่อวงจรดังต่อไปนี้เพื่อทำการทดสอบการทำงานของโค้ด Arduino
ภาพสำหรับวงจร Arduino
ภาพแผงผังวงจร |
ภาพสำหรับการต่อวงจรจริง |
หลังจากต่อวงจรและทดสอบโค้ดสำหรับ Arduino ได้ผลการทดลองดังภาพด้านล่าง
- เมื่อให้ queue มีขนาด 5 แล้วทดลองกดปุ่มเพื่อนำข้อมูลออกพบว่าใน Serial Monitor จะขึ้นข้อความ “Empty” จากนั้นทดลองใส่ข้อมูลเรื่อยจนเต็ม queue จะขึ้นข้อความ “FULL” และทดลองนำข้อมูลออกจาก queue จนหมด
ภาพเอาต์พุตจาก Serial Monitor |
- เมื่อทดลองกดปุ่มในขณะที่ queue ยังไม่มีข้อมูลอยู่เลย
ภาพเอาต์พุตจาก Serial Monitor |
- เมื่อทดลองใส่ข้อมูลจนเต็ม queue ขนาด 5
ภาพเอาต์พุตจาก Serial Monitor |
- เมื่อทดลองใส่ข้อความที่มีขนาดเกิน 16 ตัวอักษรลงใน queue แล้วทดลองกดปุ่มเพื่อนำข้อมูลออกมาจาก queue พบว่าข้อความที่แสดงออกมามีขนาดเท่ากับ 16 ตัวอักษร ดังนั้นแสดงว่าใน queue จะเก็บข้อมูลที่มีขนาดตัวอักษรไม่เกิน 16 ตัวอักษร
ภาพจาก Serial Monitor แสดงการใส่ข้อความยาวเกิน 16 ตัวอักษร |
ภาพจาก Serial Monitor เมื่อนำข้อมูลออกจาก queue |
ไม่มีความคิดเห็น:
แสดงความคิดเห็น