Tuesday, September 23, 2014

Arduino - StringQueue

สวัสดีครับ สำหรับวันนี้จะมาฝึกการสร้างและใช้งานคลาส string queue บนบอร์ด Arduino กันครับ โดยโจทย์มีดังนี้

โจทย์ข้อที่ 1 
เขียนโค้ดสำหรับบอร์ด Arduino โดยสร้างเป็น C++ Class ดังต่อไปนี้ => Class StringQueue เป็นโครงสร้างข้อมูลแบบ Queue สำหรับเก็บ String objects สร้างคลาส StringQueue และทดสอบ
การทำงานโดยใช้โค้ดตัวอย่างต่อไปนี้ และทดสอบโดยใช้ฮาร์ดแวร์จริง 

(ใช้บอร์ด Arduino และแสดงผลผ่าน Serial Monitor ของ Arduino IDE)

StringQueue.h
#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 to queue
    boolean get(String &s); // get a string from queue
    int size(); // return number of string in queue
    inline boolean isEmpty(); // return ture if queue is empty
    inline boolean isFull(); // return true if queue is full
  private:
    int _capacity; // max capacity of queue
    int count; // used to count the number of string in queue
    String buf[100]; // used to store string object in queue
};

#endif


StringQueue.cpp
#include "Arduino.h"
#include "StringQueue.h"

StringQueue::StringQueue(int capacity=10)
{
  _capacity = capacity;
  count = 0;
}

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

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

int StringQueue::size()
{
  return count;
}

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

inline boolean StringQueue::isFull()
{
  return (count == _capacity)? true : false;
}


StringQueue_task01.ino
#include "StringQueue.h"

int num = 10; // capacity
StringQueue squ(num);
char buf[16];
String str;

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

void loop() {

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


สำหรับอุปกรณ์ที่ใช้มีดังนี้
  • บอร์ด Arduino Uno (สามารถใช้รุ่นอื่นแทนได้)
  • สาย USB
  • ปุ่มกด
  • LCD Display

ซอฟต์แวร์ที่ใช้
  • Arduino IDE
  • Text Editor หรือ IDE สำหรับเขียนภาษา C/C++
  • Fritzing (สำหรับวาดผังวงจร)


ผลการรันโปรแกรม





โจทย์ข้อที่ 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 ในขณะนั้น

โค้ดสำหรับข้อสอง
StringQueue_task02.ino
#include "StringQueue.h"
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int num = 10; // capacity
StringQueue squ(num);

const int button = 6;
int buttonState = 0;
int lastButtonState = HIGH;

const int emptyLed = 7;
const int fullLed = 8;

char buf[16];
String str;

void setup() {
  pinMode(button,INPUT);
  pinMode(emptyLed, OUTPUT);
  pinMode(fullLed, OUTPUT);
  Serial.begin(115200);
  lcd.begin(16, 2);
  
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("queue size: " + String(squ.size()));
  lcd.setCursor(0, 0);
  lcd.print("status: Empty");
  
  digitalWrite(emptyLed,HIGH);
  digitalWrite(fullLed,LOW);
}

void loop(){
  
  if (Serial.available() > 0){
    str = Serial.readString();
    if (str.length() > 16){
      str = str.substring(0, 16);
    }
    if (!squ.put(str)){
      Serial.println("Full");
      
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("queue size: " + String(squ.size()));
      lcd.setCursor(0, 0);
      lcd.print("status: Full");
      
      digitalWrite(fullLed,HIGH);
      
    }else {
      Serial.print("Put string: ");
      Serial.println(str);
      
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("queue size: " + String(squ.size()));
      
      digitalWrite(emptyLed,LOW);
    }
  }
  
  str = NULL;
  
  buttonState = digitalRead(button);
  
  // check button released
  if (buttonState == HIGH && lastButtonState == LOW) { 
    if(squ.get(str)){
      str.toCharArray(buf, 16);
      Serial.print("Get string: ");
      Serial.println(buf);
     
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("queue size: " + String(squ.size()));
      lcd.setCursor(0, 0);
      lcd.print(buf);
      
      digitalWrite(fullLed,LOW);
      
    }else {
      Serial.println("Empty");
      
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("queue size: " + String(squ.size()));
      lcd.setCursor(0, 0);
      lcd.print("status: Empty");
      
      digitalWrite(emptyLed,HIGH);   
    }
  }
  lastButtonState = buttonState;
     
}


ผลการทดลอง


ผังวงจร

ขณะที่ไม่มีข้อความอยู่ใน queue จะแสดงข้อความ Empty และ led green ติด

วงจรขณะที่ข้อความใน queue เต็ม จะแสดงค่า Full และ led Red ติด

ดาวน์โหล Source code ทั้งหมดได้ ที่นี่

No comments:

Post a Comment