วันศุกร์ที่ 4 กันยายน พ.ศ. 2558

Arduino Sketch ที่ทำงานเป็นเครื่องคำนวณอย่างง่าย (Simple Calculator)



วัตถุประสงค์
          1)  ความเข้าใจและฝึกทักษะในการเขียนโค้ดคำสั่งการทำงานของ arduino มากยิ่งขึ้น
2)  ความเข้าใจกลไกการแปลงข้อมูลจาก infix เป็น postfix และสามารถนำมาประยุกต์ใช้งานได้
3)  การใช้นำความรู้ด้านอัลกอริทึมในการเก็บข้อมูลแบบ stack มาประยุกต์
วัสดุ อุปกรณ์และเครื่องมือ (Materials and Equipment)
1)      คอมพิวเตอร์ PC หรือ Notebook  ที่มีโปรแกรม Arduino
2)      บอร์ด Arduino UNO R3
3)      สาย USB ใช้เชื่อมต่อระหว่าง Arduino กับ Notebook
Block diagram



หลักการทำงาน
        จะรับข้อมูลชนิด char ผ่านทาง Arduino serial แล้วมาเก็บเป็น String  ซึ่งข้อมูลที่รับมานั้นจะคือนิพจน์ที่เป็น infix เมื่อได้รับนิพจน์ที่เป็น  infix  มาเรียบร้อยแล้วก็จะเป็นกลไกการแปลงนิพจน์จาก  infix  เป็น  postfix  ที่ต้องนำ stack มาใช้ในการเก็บ Operator  ตามลำดับการดำเนินการทางคอมพิวเตอร์ ดังนี้

Operator
Operator Precedence & Association
Precedence
          Associativity
^
3
Right
%
2
Left
/
2
Left
*
2
Left
-
1
Left
+
1
Left









1. 1 ตารางเปรียบเทียบการดำเนินการของ Operator


Algorithm ในการแปลง infix เป็น postfix ได้ศึกษาแนวทางการดำเนินการมาจาก http://www.engineersgarage.com/contribution/expert/calculator-using-postfix-notification

โดยศึกษาจาก Flowchart มีดังนี้



1.   อ่านค่าอินพุตที่ได้รับถ้าเป็น number ให้นำไปเก็บเป็น String (output)
2.   อ่านค่าอินพุตถ้าเป็น operand ให้ทำดังนี้
2.1     นำ operand เก็บลงใน Stack ถ้า Stack Empty (ว่าง)
2.2      ถ้า Stack ไม่ว่างให้เปรียบเทียบค่า Precedence ของ operator ที่อินพุตกับ operator ใน Stack โดยเทียบค่าในตาราง 
3.   อ่านค่าอินพุตถ้าเป็นเครื่องหมายวงเล็บเปิด ‘(’ ก็ให้ทำการ pop Stack
4.   อ่านค่าอินพุตถ้าเป็นเครื่องหมายวงเล็บปิด ‘)’ ก็ให้ทำการ pop Stack  ออกไปเก็บที่ String (output) จนกว่าจะเจอเครื่องหมายวงเล็บเปิดใหม่แล้วทิ้งเครื่องหมายวงเล็บปิดไป
5.   ถ้าอ่านค่าอินพุตหมดแล้วให้ตรวจใน Stack ว่าว่างหรือไม่ถ้าไม่ว่างให้ pop Stack ออกไปเก็บไว้ที่ String (output) จน Stack ว่างมีดังนี้
1.   อ่านค่าอินพุตที่ได้รับถ้าเป็น number ให้นำไปเก็บเป็น String (output)
2.   อ่านค่าอินพุตถ้าเป็น operand ให้ทำดังนี้
      2.1     นำ operand เก็บลงใน Stack ถ้า Stack Empty (ว่าง)
      2.2      ถ้า Stack ไม่ว่างให้เปรียบเทียบค่า Precedence ของ operator ที่อินพุตกับ operator ใน Stack โดยเทียบค่าในตาราง 
3.   อ่านค่าอินพุตถ้าเป็นเครื่องหมายวงเล็บเปิด ‘(’ ก็ให้ทำการ pop Stack
4.   อ่านค่าอินพุตถ้าเป็นเครื่องหมายวงเล็บปิด ‘)’ ก็ให้ทำการ pop Stack  ออกไปเก็บที่ String (output) จนกว่าจะเจอเครื่องหมายวงเล็บเปิดใหม่แล้วทิ้งเครื่องหมายวงเล็บปิดไป
5.   ถ้าอ่านค่าอินพุตหมดแล้วให้ตรวจใน Stack ว่าว่างหรือไม่ถ้าไม่ว่างให้ pop Stack ออกไปเก็บไว้ที่ String (output) จน Stack ว่าง
Step การแปลง Infix เป็น Postfix
Token
Action
Output String
opStack
1
Add to string(output)
1

5
Add to string(output)
15

-
Push to Stack
15
-
(
Push to Stack
15
-  (
(
Push to Stack
15
-  (  (
1
Add to string(output)
15  1
-  (  (
0
Add to string(output)
15  10
-  (  (
-
Push to Stack
15  10
-  (  (  -
5
Add to string(output)
15  10  5
-  (  (  -
)
Pop Stack to string(output)
15  10  5  -
-  (  (
Pop Stack
15  10  5  -
-  (
-
Push to Stack
15  10  5  -
-  (  -
3
Add to string(output)
15  10  5  -  3
-  (  -
)
Pop Stack to string(output)
15  10  5  -  3  -
-  (
Pop Stack
15  10  5  -  3  -
-
=
Pop Stack to string(output)
15  10  5  -  3  -  -



         





















            เมื่อนำค่าที่รับมาแปลงเป็น postfix เรียบร้อย แล้ว  เราก็จะนำ postfix ที่ได้ไปคำนวณค่าทางคณิตศาสตร์ โดยเราจะใช้ Stack ในการเก็บค่าของตัวเลข (Number) ที่ได้จากการวน loop ตาม index ของ postfix ที่ได้รับมา แต่ถ้าวนไปแล้วไปเจอ Operator ก็จะทำการ Pop Number ที่อยู่ใน Stack ออกมาจำนวนสองค่า เพื่อนำมาดำเนินการตาม Operator ที่พบ เมื่อคำนวณเสร็จแล้วก็จะเก็บค่าคำตอบนั้นลงไปใน Stack เพื่อนำไปคำนวณต่อไป  เมื่อคำนวณเสร็จเรียบร้อยแล้วก็จะส่งคำตอบออกจากฟังก์ชัน และนำไปแสดงผลที่หน้าจอ

จากPostfix       15  10  5  -  3  -  -

Step การคำนวณ Postfix
Token
Action
String
Stack
1
Add to string(number)
1

5
Add to string(number)
15


Push string(number) to Stack
15
15
Clear string

15
1
Add to string(number)
1
15
0
Add to string(number)
10
15

Push string(number) to Stack
10
15 10
Clear string

15 10
5
Add to string(number)
5
15 10

Push string(number) to Stack
5
15 10 5
Clear string

15 10 5
-
Pop two times form stack and calculate  (10-5)

15
Push answer to stack

15 5
3
Add to string(number)
3
15 5

Push string(number) to Stack
3
15 5 3
Clear string

15 5 3
-
Pop two times form stack and calculate  (5-3)

15
Push answer to stack

15 2
-
Pop two times form stack and calculate  (15-2)


Push answer to stack

13

Return pop stack  (=13)













  
















Code for calculator


สาธิตการทำงาน
 

ส่งข้อความที่เป็นนิพจน์ (10-3/2+5)*2= ผ่านทาง Arduino serial monitor (รูปซ้าย) ส่งไปคำนวณและนำกลับมาแสดงคำตอบ (รูปขวา)
 
ส่งข้อความที่เป็นนิพจน์ ((100+1)*50)/100= ผ่านทาง Arduino serial monitor (รูปซ้าย) ส่งไปคำนวณและนำกลับมาแสดงคำตอบ (รูปขวา) โดยยังสามารถมองเห็นผลลัพธ์ที่ได้จากการส่งข้อความไปก่อนหน้านี้ด้วย
 
 
ส่งข้อความที่เป็นนิพจน์ 15-((10-5)-3)= ผ่านทาง Arduino serial monitor (รูปซ้าย) ส่งไปคำนวณและนำกลับมาแสดงคำตอบ (รูปขวา) โดยยังสามารถมองเห็นผลลัพธ์ที่ได้จากการส่งข้อความไปก่อนหน้านี้ด้วย

ส่งข้อความที่เป็นนิพจน์ (10^2+2^10)%(100^2)= ผ่านทาง Arduino serial monitor (รูปซ้าย) ส่งไปคำนวณและนำกลับมาแสดงคำตอบ (รูปขวา) โดยยังสามารถมองเห็นผลลัพธ์ที่ได้จากการส่งข้อความไปก่อนหน้านี้ด้วย



ส่งข้อความที่เป็นนิพจน์ 2^3-5*2^2-3*2+10= ผ่านทาง Arduino serial monitor (รูปซ้าย) ส่งไปคำนวณและนำกลับมาแสดงคำตอบ (รูปขวา) โดยยังสามารถมองเห็นผลลัพธ์ที่ได้จากการส่งข้อความไปก่อนหน้านี้ด้วย

วิดีโอสาธิตการทดลอง : https://www.youtube.com/watch?v=6PO4MGXeEQk&feature=youtu.be