หน้าเว็บ

วันศุกร์ที่ 12 กันยายน พ.ศ. 2557

String Stack กับบอร์ด Arduino

โจทย์ปัญหา ข้อ 1
  1. เขียนโค้ดสำหรับบอร์ด Arduino โดยสร้างเป็น C++ Class ดังต่อไปนี้
  • Class StringStack เป็นโครงสร้างข้อมูลแบบ Stack (กองซ้อน) สำหรับเก็บ String objects (http://arduino.cc/en/Reference/StringObject) และกำหนด API สำหรับคลาสดังกล่าว เป็นดังนี้
#include <String.h>

class StringStack {  
    public:
        StringStack(int capacity = 10); // constructor method
        bool put(String s);                  // put a String object on stack
        bool get(String &s);                // get a String object from stack
        inline int size();                      // return the number of String object on the stack
        inline bool isEmpty();              // return true if stack is empty, otherwise false
        inline bool isFull();                  // return true if stack is Full, otherwise false
    private:
        int capacity; // the max capacity of the stack
        int count;     // used to count the number of string object stored
        String *buf; // used to store String object on stack
};
จงสร้างคลาส StringStack และทดสอบการทำงานโดยใช้โค้ดตัวอย่างต่อไปนี้ และทดสอบโดยใช้ฮาร์ดแวร์จริง (ใช้บอร์ด Arduino และแสดงผลผ่าน Serial Monitor ของ Arduino IDE)
#include "StringStack.h"

int num = 10;  //capacity
StringStack st(num);

void setup(){
    Serial.begin(115200);
}

char buf[20];
String str;

void loop(){
    Serial.print("\nPut strings: ");
    for(int i=0; i<num; i++){
        str = String((i+1)*10);
        if (!st.put(str)){
            Serial.println("\nPut 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.get(str)){
            str.toCharArray(buf, 20);
            Serial.print(buf);
            Serial.print(" ");
        }else{
            Serial.println("\nGet string error!");
            break;
        }
        delay(50);
    }
    delay(500);
}

ผลการทดลอง
        หลังจากทำการออกแบบการเขียนโค้ดเพื่อให้ทำงานตามโจทย์ที่ได้รับ  ได้ผลดังต่อไปนี้
  • ด้านล่างนี้เป็นโค้ดสำหรับไฟล์ StringStack.h ซึ่งเป็น Header File ตามโจทย์ที่ได้รับ
// class declaration
#ifndef StringStack_H
#define StringStack_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 StringStack {
    private:
        int capacity; // the max capacity of the stack
        int count;     // used to count the number of string object stored
        String *buf; // used to store String object on stack
  
    public:
        StringStack(int capacity = 10); // constructor method
        bool put(String s);                  // put a String object on stack
        bool get(String &s);                // get a String object from stack
        inline int size();                      // return the number of String object on the stack
        inline bool isEmpty();              // return true if stack is empty, otherwise false
        inline bool isFull();                  // return true if stack is Full, otherwise false
};
#endif;

  • ด้านล่างนี้เป็นโค้ดสำหรับไฟล์ StringStack.cpp ซึ่งเป็นโค้ดภาษา C++ ใช้สำหรับการเขียนโค้ดให้ทำงานที่ต้องการ ตามที่ได้ประกาศไว้ใน Header ไฟล์
#include "StringStack.h"

StringStack::StringStack(int capacity){
    this->capacity = capacity;
    count = 0;
    buf = new String[capacity];
}

bool StringStack::put(String s){ // put a String object on stack
    if (!isFull()){
        *(buf+count) = s;     // store s (input) value in stack
        count += 1;              // update number of String object store
        return true;
    }
    else{
        return false;             // if stack is full then return false
    }
}

bool StringStack::get(String &s){ // get a String object from stack
    if (!isEmpty()){
        count -= 1;              // update number of String object store
        s = *(buf+count);    // set value of s (output) is equal top value in stack
        return true;
    }
    else{
        return false;            // if stack if empty then return false
    }
}

inline int StringStack::size(){
    return count;               // return the number of String object on the stack
}

inline bool StringStack::isEmpty(){ // return true if stack is empty, otherwise false
    if (count <= 0){
        return true;
    }
    else{
        return false;
    }
}

inline bool StringStack::isFull(){ // return true if stack is Full, otherwise false
    if (count >= capacity){
        return true;
    }
    else{
        return false;
    }
}

การทำงานของโค้ด
  • ในบรรทัดที่ 6 ตัวแปร buf ซึ่งเป็นตัวแปรแบบ pointer ให้ชี้ไปที่ array แบบ String เพื่อใช้ในการเก็บข้อมูลของ String object
  • ฟังก์ชัน put ถ้า stack ยังไม่เต็มจะเป็นการเก็บข้อมูลลงใน stack โดยรับข้อมูลแบบ String ที่ต้องการเก็บลงใน stack  ในบรรทัดที่ 11 จะเป็นการนำข้อมูล String ที่รับเข้ามาไปเก็บไว้ใน array แบบ String ที่ตัวแปร buf กำลังชี้อยู่  ซึ่งใช้ buf + count ในการระบุ index ที่ต้องการเก็บข้อมูล  แล้วใช้คำสั่ง *(buf + count) = s; ในการกำหนดค่าของ array ตาม index ที่ระบุ ให้มีค่าเท่ากับค่าของ s เพื่อเก็บข้อมูลลง stack
  • ฟังก์ชัน get ถ้ามีข้อมูลอยู่ใน stack จะเป็นการนำข้อมูลบนสุดของ stack ออก และแสดงผลข้อมูลนั้น  โดยฟังก์ชันนี้จะรับข้อมูลเป็น Address ของ string ที่ต้องการให้นำข้อมูลไปแสดง  ดังนั้นในบรรทัดที่ 23 จึงใช้คำสั่ง s = *(buf + count) เพื่อกำหนดให้ค่าของ s มีค่าเท่ากับค่าที่บนสุดของ stack โดยใช้คำสั่ง buf + count ในการระบุ index บนสุดของ stack
  • ฟังก์ชัน size ใช้ในการดูว่ามีจำนวนข้อมูลอยู่ใน stack เท่าใด
  • ฟังก์ชัน isEmpty ใช้สำหรับการดูว่า stack นั้นว่างหรือไม่  ถ้าหาก stack ไม่มีข้อมูลอยู่เลยจะให้ค่าเป็น true แต่ถ้ามีข้อมูลอยู่ใน stack จะให้ค่าเป็น false
  • ฟังก์ชัน isFull ใช้ในการดูว่า stack นั้นเต็มหรือไม่  ถ้าหากมีข้อมูลอยู่ใน stack จนเต็ม จะให้ค่าเป็น true  แต่ถ้าหากยังไม่เต็มจะให้ค่าเป็น false

        เมื่อนำโค้ดที่ออกแบบไปใช้กับโค้ดเพื่อการทดสอบตามโจทย์ ได้ผลของเอาต์พุตใน Serail Monitor ดังภาพด้านล่าง
        จากภาพด้านบน มีการ put ข้อมูลเป็น string ของตัวเลขที่เรียงลำดับกันตั้งแต่ 0 ถึง 9  ดังนั้น เมื่อมีการ get ข้อมูลออกมา จึงเรียงตามลำดับจาก 9 จนถึง 0

โจทย์ปัญหา ข้อ 2
    2. ใช้คลาส StringStack ในข้อแรก  นำมาเขียนโค้ด Arduino เพื่อให้มีพฤติกรรมการทำงานดังนี้
  • บอร์ด Arduino มีวงจรปุ่มกด Get ทำงานแบบ Active-Low (ใช้ตัวต้านทานแบบ Pull-up 10k) 
  • ผู้ใช้สามารถส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่ 20 อักขระต่อบรรทัด) จากคอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino 
  • ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringStack (เก็บบนกองซ้อน) ถ้าไม่เต็มความจุ  แต่ถ้าเต็มความจุ ไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "FULL" กลับมา 
  • เมื่อมีการกดปุ่ม Get แล้วปล่อยหนึ่งครั้ง ข้อความบนสุด (ถ้ามี) ของ StringStack จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์  แต่ถ้าไม่มีข้อความใดๆ Arduino จะต้องส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย

ผลการทดลอง
        หลังจากการออกแบบและเขียนโค้ดเพื่อให้ทำงานได้ตามโจทย์ที่ได้รับ แล้วได้โค้ดสำหรับ Arduino ดังด้านล่าง 
#include "StringStack.h";

StringStack textarray(20);
String recieved_text = "";
String str = NULL;
void setup() {
    pinMode(INPUT,4);
    Serial.begin(9600);
    Serial.println("start"); 
}

void loop() {

    while (Serial.available()) {
        delay(10);
        char c = Serial.read();  //gets one byte from serial buffer
        recieved_text += c; 
    }
    if (recieved_text.length() > 0) {
        if(recieved_text.length() > 20){
            recieved_text = recieved_text.substring(0, 20);
        }
 
        if(!textarray.put(recieved_text)){
            Serial.println("FULL");
        } else {
            Serial.println("Add: \"" + recieved_text + "\" in Stack");
        }
        recieved_text = ""; //clears text for new text
    }

    if(!digitalRead(4)){
        delay(10);
        if(digitalRead(4)){
            if(!textarray.get(str)){
                Serial.println("Empty");
            } else {
                Serial.println("Get: \"" + str + "\" from Stack");
            }
        }
    }
}

การทำงานของโค้ด    
   จากโจทย์ที่รับข้อมูลจาก ผ่าน Serial Monitor จึงได้เปิด Serial port ตั้ง baud rate ที่ 9600 จากนั้นจึง Serial.available() ด้วย while() ให้รับข้อมูลที่ส่งมาทุกตัวเก็บไว้ในตัวแปร String ตัวนึง ใช้ substring() ตัดข้อมูลที่เกินโดยจำกัดไว้ที่ 20 อักขระ จากนั้นจึงใช้คำสั่ง put() ถ้า true จะปริ้นค่าที่ใส่ แต่เมื่อ false คือ stack เต็มจะปริ้น FULL คือข้อมูลเต็มแล้ว เมื่อกดปุ่มจะใช้คำสั่ง pop() เมื่อ true จะปริ้นข้อความที่ pop() ออกมา แต่ถ้า false จะปริ้น Empty 

ภาพด้านล่างสำหรับวงจรปุ่มกด

ภาพแผนผังสำหรับวงจรปุ่มกด
ภาพการต่อวงจรจริง


        เมื่อนำโค้ดที่ได้ไปใช้กับวงจรจริงได้ผลการทดลองดังภาพด้านล่าง
ภาพเอาต์พุต เมื่อกดปุ่มขณะที่ยังไม่มีข้อมูลใน StringStack
ภาพเอาต์พุต เมื่อพยายามเพิ่มข้อมูลมากกว่าความจุของ StringStack ในที่นี้คือ 20
ภาพเอาต์พุต เมื่อมีการ put และการ get ใน StringStack
ภาพเอาต์พุต เมื่อพยายามจะใส่ข้อมูลที่มีความยาวมากกว่า 20 อักขระ
ดาวโหลดโค้ด คลิกที่นี่

ไม่มีความคิดเห็น:

แสดงความคิดเห็น