Wednesday, September 24, 2014

Warm-Up 3


โจทย์ฝึกปฏิบัติสำหรับสัปดาห์นี้
1) เขียนโค้ดสำหรับบอร์ด Arduino โดยสร้างเป็น C++ Class ดังต่อไปนี้
=> 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 ได้

ผลการทดสอบคลาสจากโค้ดทดสอบ

  จากผลการทดสอบจะเห็นได้ว่า ข้อความ ได้เพิ่มเข้าไปก่อนจะถูกเรียกออกมาก่อนตามลำดับเสมอ

Class StringQueue

  StringQueue.h

  StringQueue.cpp


โครงสร้างคลาส
class StringQueue {
  public:
    StringQueue( int capacity ); // constructor
    boolean put( String s ); // ใช้สำหรับส่งค่า String Object เข้าไปเก็บใน StringQueue
    boolean get( String &s ); // คืนค่าออกจาก StringQueue
    int size(); // คืนค่าจำนวนข้อมูลใน StringQueue
    inline boolean isEmpty(); // ตรวจสอบว่า StringQueue ว่างหรือไม่
    inline boolean isFull(); // ตรวจสอบว่า StringQueue เต็มหรือไม่
  private:
    int capacity; // จำนวนข้อมูลสูงสุดใน StringQueue
    int count; // ใช้นับจำนวน String Object ที่เก็บใน StringQueue
    String *buf; // ใช้ในการเก็บ String Object บน StingQueue
};

หลักการทำงานของเมธอดต่างๆ
boolean StringQueue::put( String s ) {
  if(!isFull()){                        //เช็คว่า StringQueue เต็มหรือไม่
    buf[count] = s;                //ให้ buf ช่องที่ปัจจุบันเก็บค่า ข้อความที่รับเข้ามา
    if(count<10){                  //บวกค่า count เพื่อเพิ่มเลื่อนช่องสำหรับเก็บข้อความ
      count++;
    }
    return true;                    //return true เพื่อส่งไปบอกว่าทำการเพิ่มสำเร็จ
  }
  else{
    return false;                             //return false ในกรณีที่ StringQueue เต็ม
  }
}

boolean StringQueue::get( String &s ) {
  if(!isEmpty()){                     //เช็คว่า StringQueue ว่างหรือไม่
      if(count>0){                  //เลื่อนช่องสำหรับคืนค่าข้อความ
      count--;
    }
    String temp = buf[0];       
    *&s = temp;                             //คืนค่าข้อความผ่านทางแอดเดรสที่รับเข้ามา
    for(int i = 0;i<9;i++){         //เลื่อนช่องของทุกข้อความ 1 ช่อง
    buf[i] = buf[i+1];
}
   return true;                     //return true ในกรณีที่คืนค่าสำเร็จ
  }
  else{
    return false;                             //return false ในกรณีที่ StringQueue ว่างหรือไม่มีข้อความ
  }
}

int StringQueue::size() {       // ใช้บอกจำนวน String Object ใน StringQueue
  return count;
}

inline boolean StringQueue::isEmpty()                //ใช้สำหรับเช็คว่า StringQueue ว่างหรือไม่
inline boolean StringQueue::isFull()                    //ใช้สำหรับเช็คว่า StringQueue เต็มหรือไม่

Work with Arduino

  Wiring Diagram / Breadboard View

  Arduino Code

Arduino Code
รับค่าจาก Serial Monitor
while(Serial.available() > 0){
    str = Serial.readStringUntil('\n');                                    //รับค่าจาก Serial Monitor
  }
  if(str.length()> 20 ){                                           //ตัดข้อความให้เหลือ 20 ตัวอักษร
    str = str.substring(0,20);
  }
  if(str.length()<=20 && str.length() > 0){                //ถ้าข้อความไม่เกิน 20 ตัวอักษรส่งไปเก็บใน StringQueue
    if(!st.put(str)){
      Serial.println("\nQueue is Full!!!");                   //แสดงข้อความในกรณีที่ StringQueue
      Serial.println("Press Button to get words from Queue!!!");
    }
    else{
      Serial.println("add : >>>" + str + "<<< to Queue\n");    //แสดงข้อความว่าเพิ่มข้อความเข้า StringQueue แล้ว
      Serial.println("Put String into Queue or Press Button For Get String : ");
      lcd.clear();                                                               //เคลียร์จอ LCD
      lcd.setCursor(0,1);                                                     //เซ็ตบรรทัดสำหรับแสดงผล
      lcd.print(st.size());                                                     //แสดงผลจำนวนข้อมูลใน StringQueue
    }
  }

คืนค่าจาก StringQueue มาแสดงผลบน Serial Monitor และ LCD
  if(digitalRead(button) == 0){
    delay(100);
    if(digitalRead(button) == 1){
      if (st.get( temp )){                 //รับค่าคืนจาก String Queue
        temp.toCharArray(buffer,20);          
        Serial.println("\nGet : [" + (String)buffer + " ] Queue");
        Serial.println("Typing words to Queue or Press Button to get word from Queue");
        lcd.clear();                         //สั่ง LCD แสดงค่าที่ได้จาก StringQueue
        lcd.setCursor(0,0);
        lcd.print(buffer);
        lcd.setCursor(0,1);
        lcd.print(st.size());
      }
      else if(!st.get(temp)){
        Serial.println("\nQueue is Empty !!!");
        Serial.println("Please !!! Typing words to Queue : ");
      }
      else{
        Serial.println("\nGet String error!");
      }
      delay(50);
    }
  }

แสดงผลไฟ
if(st.size() == 10){                                               //แสดงไฟสีแดงในกรณีที่ StringQueue เต็ม
    digitalWrite(red_led,HIGH);
    lcd.setCursor(3,1);
    lcd.print("Queue is Full !!!");
  }
  else if(st.size() == 0){                            //แสดงไฟสีเขียวในกรณีที่ StringQueue ว่าง
    digitalWrite(green_led,HIGH);
    lcd.setCursor(3,1);
    lcd.print("Queue is Empty !!!");
  }
  else{                                                   //ดับไฟทุกสีในกรณีที่ StringQueue ไม่เต็มและไม่ว่าง
    digitalWrite(red_led,LOW);
    digitalWrite(green_led,LOW);
  }

ผลการทดลอง



Thursday, September 11, 2014

Warm-Up 2

  โจทย์กำหนดให้สร้าง class StringStack เป็นคลาสที่เก็บตัวแปร String แบบ Stack โดยรับค่าจาก Serial และนำค่าออกจาก Stack โดยการกดปุ่มที่ต่อกับ Arduino แบบ Active Low

Button With Arduino

Fritzing

โดยกำหนด API  ของ class StringStack ดังนี้

/////////////////////////////////////////////////////////////////////////
‪#‎include‬ 
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
};
/////////////////////////////////////////////////////////////////////////

Method ต่างๆใน Class

  • StringStack( int capacity=10 ); ใช้ในการสร้างตัวแปร Class
  • boolean put( String s ); ใช้ในการรับ String เข้ามาเก็บใน Class แบบ Stack
  • boolean get( String &s ); ใช้ในการส่ง String ออกไปโดยส่งผ่านทาง Address ของตัวแปรที่รับเข้ามา
  • inline int size(); ใช้ในการส่งค่าของจำนวนของ String ใน Stack
  • inline boolean isEmpty(); ใช้ในการตรวจสอบว่า StringStack ว่างหรือไม่
  • inline boolean isFull(); ใช้ในการตรวจสอบว่า StringStack เต็มหรือไม่

Variable ต่างๆใน Class

  • int capacity; ตัวแปรสำหรับเก็บ ค่าความจุ ของ StringStack
 • int count; ตัวแปรสำหรับนับจำนวนของข้อมูลใน StringStack  • String *buf; ตัวแปรสำหรับเก็บ String ในรูปแบบของ Stack

Class StringStack <StringStack.h>

//StringStack Libraly
#ifndef StringStack_h
#define StringStack_h

#include "Arduino.h"
#include "string.h"

class StringStack {
  public:
    StringStack( int capacity ); // 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
    String* getStack();
  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
};

#endif

Class StringStack <StringStack.cpp>

#include "StringStack.h"

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

boolean StringStack::put( String s ) {
  if(!isFull()){
    buf[count] = s;
    if(count<9){
      count++;
    }
    return true;
  }
  else{
    return false;
  }
}

boolean StringStack::get( String &s ) {
  if(!isEmpty()){
     if(count>0){
      count--;
    }
    *&s = buf[count];
    buf[count] = "";
   return true;
  }
  else{
    return false;
  }
}

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

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

inline boolean StringStack::isFull(){
  if(count == 9){
    return true;
  }
  else{
    return false;
  }
}

String* StringStack::getStack(){
  return buf;
}

Arduino Code

#include "StringStack.h"
int num = 10; // capacity
StringStack st( num );
String str;
int state;
void setup(){
  pinMode(2,INPUT);
  Serial.begin(115200);
  Serial.print("Put String into Stack(stack keep 20 character) : ");
}
void loop(){
  str = "";
  String temp;
  char buffer[20];
  if(digitalRead(2) == 0){
    delay(100);
    if(digitalRead(2) == 1){
      if ( st.get( temp ) ) {
        temp.toCharArray( buffer, 20 );
        Serial.print("Get : [ ");
        Serial.print( buffer );
        Serial.println(" ] From Stack");
        Serial.println();
        Serial.println("Typing words to stack or Press Button to get words from stack : ");
      } 
      else if(!st.get( temp )){
        Serial.println("");
        Serial.println("Stack is Emtry !!!");
        Serial.println("Please !!! Typing words to stack : ");
      }
      else {
        Serial.println( "\nGet string error!" );
      }
      delay(50);
    }
  }
  while(Serial.available() > 0)
  {
    str = Serial.readStringUntil('\n');
  }
  if(str.length()>20){
    str = str.substring(0, 20);
  }
  if(str.length()<=20 && str.length()>0){
    if ( !st.put( str ) ) {
      Serial.println("");
      Serial.println( "Stack is Full" );
      Serial.println("Press Button to get words from stack : ");
    }
    else {
      Serial.print( "add : >> " );
      Serial.print( str );
      Serial.println( " << to Stack" );
      Serial.print("Stack Have : [ ");
      for(int i = 0 ; i < num ; i++){        
        if(st.getStack()[i] != ""){
          Serial.print(st.getStack()[i]);
          if(st.getStack()[i+1] != ""){
            Serial.print(" , ");
          }
        }
      }  
      Serial.println(" ]");
      Serial.println("");
      Serial.println("Put String into Stack or Press Button For get String : ");
    }
  }
}
เงื่อนไขการทำงาน
• ใส่อักขระได้ไม่เกิน 20 ตัว หากเกินจะตัดให้เหลือ 20 ตัว
• เมื่อกดปุ่มจะนำค่าออกจาก Stack มาแสดง
• เมื่อ Stack เต็มไม่สามารถเพิ่มข้อมูลได้แล้วจะแสดงคำเตือนว่า Stack is Full
• เมื่อ Queue ว่างไม่สามารถดึงข้อมูลได้แล้วจะแสดงคำเตือนว่า Stack is Empty 

ผลการทดลอง

Extra >> StringQueue

  ใช้ API แบบ StringStack แต่เก็บข้อมูลในรูปแบบ Queue (เข้าก่อนออกก่อน)

Class StringQueue <StringQueue.h>

//StringQueue Libraly
#ifndef StringQueue_h
#define StringQueue_h

#include "Arduino.h"
#include "String.h"

class StringQueue {
  public:
    StringQueue( int capacity ); // 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
    String* getQueue();
  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
};

#endif

Class StringQueue <StringQueue.cpp>

#include "StringQueue.h"

StringQueue::StringQueue( int capacity=10 ) {
  this->capacity = capacity; // constructor
  count = 0;
  buf = new String[capacity];
}

boolean StringQueue::put( String s ) {
  if(!isFull()){
    buf[count] = s;
    if(count<9){
      count++;
    }
    return true;
  }
  else{
    return false;
  }
}

boolean StringQueue::get( String &s ) {
  if(!isEmpty()){
      if(count>0){
      count--;
    }
    String temp = buf[0];
    *&s = temp;
    for(int i = 0;i<9;i++){
    buf[i] = buf[i+1];
}
  
   return true;
  }
  else{
    return false;
  }
}

inline int StringQueue::size() { // return the number of String objects on the Queue
  return count;
}

inline boolean StringQueue::isEmpty() {
  if(count == 0){
    return true;
  }
  else{
    return false;
  }
}

inline boolean StringQueue::isFull(){
  if(count == 9){
    return true;
  }
  else{
    return false;
  }
}

String* StringQueue::getQueue(){
  return buf;
}

Arduino Code

#include "StringQueue.h"
int num = 10; // capacity
StringQueue st( num );
String str;
void setup(){
  pinMode(2,INPUT);
  Serial.begin(115200);
  Serial.print("Put String into Queue(Queue keep 20 character) : ");
}
void loop(){
  str = "";
  String temp;
  char buffer[20];
  if(digitalRead(2) == 0){
    delay(100);
    if(digitalRead(2) == 1){
      if ( st.get( temp ) ) {
        temp.toCharArray( buffer, 20 );
        Serial.print("Get : [ ");
        Serial.print( buffer );
        Serial.println(" ] From Queue");
        Serial.println();
        Serial.println("Typing words to Queue or Press Button to get words from Queue : ");
      } 
      else if(!st.get( temp )){
        Serial.println("");
        Serial.println("Queue is Emtry !!!");
        Serial.println("Please !!! Typing words to Queue : ");
      }
      else {
        Serial.println( "\nGet string error!" );
      }
      delay(50);
    }
  }
  while(Serial.available() > 0)
  {
    str = Serial.readStringUntil('\n');
  }
  if(str.length()>20){
    str = str.substring(0, 20);
  }
  if(str.length()<=20 && str.length()>0){


    if ( !st.put( str ) ) {
      Serial.println("");
      Serial.println( "Queue is Full" );
      Serial.println("Press Button to get words from Queue : ");
    }
    else {
      Serial.print( "add : >> " );
      Serial.print( str );
      Serial.println( " << to Queue" );
      Serial.print("Queue Have : [ ");
      for(int i = 0 ; i < num ; i++){        
        if(st.getQueue()[i] != ""){
          Serial.print(st.getQueue()[i]);
          if(st.getQueue()[i+1] != ""){
            Serial.print(" , ");
          }
        }
      }  
      Serial.println(" ]");
      Serial.println("");
      Serial.println("Put String into Queue or Press Button For get String : ");
    }
  }
}

ผลการทดลอง

Source Code >> Download <<