วันพฤหัสบดีที่ 11 กันยายน พ.ศ. 2557

สร้าง Class C++ ของ StringStack

การสร้าง Class C++ ที่ใช้เป็นโครงสร้างข้อมูลแบบ Stack (กองซ้อน) เพื่อใช้งานสำหรับ Arduino

โจทย์สำหรับการทดลอง

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
      boolean put( String s ); // put a String object on stack
      boolean get( String &s ); // get a String object from stack
      inline int size(); // return the number of String objects on the stack
      inline boolean isEmpty(); // return true if stack is empty, otherwise false
      inline boolean 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 objects stored
      String *buf; // used to store String objects on stack
};

      จงสร้างคลาส StringStack และทดสอบการทำงานโดยใช้โค้ดตัวอย่างต่อไปนี้และทดสอบโดย
ใช้ฮาร์ดแวร์จริง (ใช้บอร์ด Arduino และแสดงผลผ่าน Serial Monitor ของ Arduino IDE)


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);
}


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

อุปกรณ์ทดลอง (Apparatus) 


      อุปกรณ์     
         จำนวน         
LED 5mm.
2


ตัวต้านทาน 10 กิโลโอห์ม 


(น้ำตาล ดำ ส้ม ทอง)



BREADBOARD 


บอร์ดทดลองอิเล็กทรอนิกส์
1
Arduino Uno R3 
1
ปุ่มกด
3
สาย USB Cable
1
สายไฟต่อวงจร
-



Arduino Sketch (1)


ส่วนแรกเป็นการประกาศคลาสชื่อ StringStack มีเพียงเมธอดเดียวสำหรับใช้งานเป็น Constructor โดยรับอาร์มิวเมนต์ capacity ตามชนิดข้อมูลแบบ int ซึ่งจะใช้กำหนดหมายเลขสำหรับขาเอาต์พุตของ Arduino ที่ต้องใช้งานแบบ PWM ได้ และ inverse ที่มีชนิดข้อมูลเป็น boolean เพื่อกำหนดว่า จะกลับลอจิกของสัญญาณเอาต์พุต PWM หรือไม่ (กรณีที่ใช้กับ RGB LED แบบ Common Anode)

// class declaration ---------------------------------------------------------------------------------
#ifndef StringStack_h
#define StringStack_h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class StringStack {
  public:
    StringStack( int capacity=10 ); // constructor
    bool put( String s ); // put a String object on stack
    bool get( String &s ); // get a String object from stack
    int size_stack(); // return the number of String objects on the stack
    boolean isEmpty(); // return true if stack is empty, otherwise false
    boolean 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 objects stored
    String *buf; // used to store String objects on stack
    String array[10 ];
};
#endif
// end class delcaration ---------------------------------------------------------------------------

ส่วนที่สองเป็นการสร้างคลาสซึ่งเกี่ยวกับการสร้างเมธอดสมาชิกตามที่ได้ประกาศไว้ในส่วนแรก ให้สังเกตวิธีการอ้างอิงชื่อเมธอดสมาชิก


// class implementation----------------------------------------------------------------------------
#include "StringStack.h"

StringStack::StringStack( int capacity ) {
  capacity = capacity;
  count = 0;
}

bool StringStack::put( String s ) {
  if ( isEmpty() ) {
    array[count] = s;
    //*buf = array[count];
    count ++;
    return true;
  }
  else {
    return false;
  }
}

bool StringStack::get( String &s ) {
  if ( count <= 0 ) {
     return false;
  }
  else {
    String *buf = &s;
    count --;
    *buf = array[count];
    return true;
  }
}

int StringStack::size_stack() {
  return count;
}

boolean StringStack::isEmpty() {
  if(count >= 10){
    return false;
  }else{return true;}
}

boolean StringStack::isFull() {
  if(count < capacity){
    return false;
  }else{return true;}
}
// end class implementation----------------------------------------------------------------------

ส่วนที่สามเกี่ยวข้องกับการเขียนโค้ดทดสอบ (ไม่เกี่ยวข้องกับการนิยามและสร้างคลาส) โดยสร้างออปเจคจากคลาส StringStack เขียนได้ดังนี้


// test code Problem1 -----------------------------------------------------------------------------
#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 = "";
    delay(50);
  }
  delay(500);
  //Serial.print(st.get( str));
  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);
}
// end test code Problem1------------------------------------------------------------------------

เมื่อได้ทดลองการทำงานแล้ว ก็สามารถนำโค้ดดังกล่าว มาจัดแบ่งเป็นไฟล์ StringStack.h สำหรับส่วนที่ประกาศคลาส และ StringStack.cpp สำหรับส่วนที่สร้างคลาส และเก็บไฟล์ทั้งสองไว้ในไดเรคทรอรี่ชื่อเดียวกับคลาส ในการนำไปใช้งาน โค้ด Arduino Sketch ที่จะใช้คลาสดังกล่าว จะต้องประกาศการใช้งานดังนี้ #include<StringStack.h>


ไฟล์ StringStack.h , StringStack.cpp  สำหรับนำไปใช้งานในลักษณะที่เป็นไลบรารี่สำหรับ Arduino
ใส่ไว้ภายใต้ไดเรคทรอรี่ชื่อ
 libraries ของ Arduino IDE)

ผลการทดลองการทำงาน (1)


แสดงข้อมูลที่ใส่ stack และข้อมูลที่นำออกมาจาก stack



Arduino Sketch (2)


การเขียนโค้ดทดสอบ โดยสร้างออปเจคจากคลาส StringStack ให้มีคุณสมบัติตรงกับโจทย์สำหรับ
การทดลองข้อ 2 เขียนได้ดังนี้
// Test code Problem2 -------------------------------------------------------------------------
#include <StringStack.h>
int num = 10; // capacity
StringStack st( num );

int check=0; 
char count1;
int nub =0;
String count;
char buf[20];
String str,str1;

//button
int empty_ledPin = 9;   // กำหนด pin สำหรับ LED เมื่อ stack ว่าง         
int full_ledPin = 6;    // กำหนด pin สำหรับ LED เมื่อ stack เต็ม
int button_Pin = 2;     // กำหนด 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 ปุ่ม
}

void loop(){
  button = digitalRead(button_Pin);  //ให้ตัวแปร button มีค่าเปลี่ยนแปลง
                                                        //เมื่อมีการกดปุ่ม

  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,19);
    check=0;
    count ="";
    nub=0;
    
    if ( !st.put( str ) ) {
      Serial.print( "\nFull" );
      digitalWrite(full_ledPin,HIGH);
     }
    else {
      digitalWrite(empty_ledPin, LOW);
      Serial.print( "\nPut strings: " );
      Serial.print( str );
      delay(1000);
      }
    delay(50);
  }
  //BUTTON
  if (button == LOW) { //Active LOW
    state=1;
  }

  if(state==1 && button==HIGH){
    state=0;
    digitalWrite(full_ledPin, LOW); 
    
    if ( !st.get( str ) ) {
      Serial.print( "\nEMPTY" );
      digitalWrite(empty_ledPin,HIGH);
      delay(2000);  
    }
    else {
      str.toCharArray( buf, 20 );
      Serial.print( "\nGet strings: " );
      Serial.print( buf );
    }
    delay(50);
  }
}
// end test code Problem2 --------------------------------------------------------------------


ผังวงจร (Breadboard Layout)

ผังวงจร


ภาพแสดงตัวอย่างการต่อวงจรทดลอง

ผลการทดลองการทำงาน (2)

ส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่เกิน 20 ตัวอักขระต่อบรรทัด)
จากคอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino



ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringStack (เก็บบนกองซ้อน)
ถ้าเต็มความจุที่กำหนดไว้ จะไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "Full" กลับมา


กดปุ่ม Get แล้วปล่อยหนึ่งครั้ง ข้อความบนสุด (ถ้ามี) ของ StringStack
จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์


ถ้าไม่มีข้อความใดๆ Arduino จะต้องส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย


ผลแสดงการทดลอง



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

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