ให้ Arduino รับข้อความทาง Serial Monitor เป็นลักษณะของนิพจน์ทางคณิตศาสตร์
ประกอบด้วย "+"บวก, "-"ลบ, "*"คูณ, "/"หาร, "%"หารเอาเศษ, "^"ยกกำลัง, "( )"วงเล็บสำหรับจัดกลุ่มการคำนวณ, ตัวเลขจำนวนเต็มบวก (Integer) และ "="เครื่องหมายเท่ากับเพื่อบอกให้แสดงผลลัพธ์
จากนั้นไปคำนวณบนชิปไมโครคอนโทรเลอร์ของบอร์ด Arduino แล้วส่งผลลัพธ์กลับมาแสดงบน Serial Monitor โดยให้ขึ้นต้นด้วยเครื่องหมาย "="เท่ากับ
ออกแบบระบบการทำงาน
ส่วนที่ 1 การอ่านค่าจาก Serial Monitor
- กำหนด datarate เท่ากับ 9600 bps (bits/sec) ด้วยฟังก์ชัน Serial.begin(9600);
void setup() {
Serial.begin(9600);
//...
}
- ตรวจสอบว่ามีข้อมูลให้อ่านโดยใช้ฟังก์ชัน Serial.available() แล้วใช้ฟังก์ชัน Serial.read() อ่านจาก Serial ทีละ 1 byte (เท่ากับ 1 ตัวอักษร(char)) ได้ข้อมูลชนิด byte
void loop() {
while (Serial.available()) {
byteRead = Serial.read();
//...
}
}
- การรวมตัวเลขจากตัวเลขที่แยกเป็น byte ให้เป็นจำนวนเต็มบวกหลายๆหลักเช่น 1,234 ใช้วิธีดังนี้
อ่าน byte แรกได้ 49 คือ '1' ได้เป็น (49-48) = 1
อ่าน byte สองได้ 50 คือ '2' ได้เป็น (1x10)+(50-48) = 12
อ่าน byte สามได้ 51 คือ '3' ได้เป็น (12x10)+(51-48) = 123
อ่าน byte สี่ ได้ 52 คือ '4' ได้เป็น (123x10)+(52-48) = 1234โดย 48,49,50,51,52 นั้นคือรหัส ASCII ในฐานสิบ (DEC) ของตัวอักษร '0','1','2','3' และ '4' ตามลำดับซึ่งมีขนาด 1 byte โดยสามารถดูได้จาก ตาราง ASCII
if(byteRead>47 && byteRead< 58) {
num = (num*10)+(byteRead-48);
//...
}
ที่มา http://arduinobasics.blogspot.com/2012/07/arduino-basics-simple-arduino-serial.html
ส่วนที่ 2 การคำนวณนิพจน์ทางคณิตศาสตร์ด้วยกองซ้อน (Stack)
โดยประกอบด้วย 2 Stack คือ Stackของตัวเลข (Operand) และ Stackของตัวดำเนินการ (Operator)
และมีการคำนวณตามเงื่อนไขดังต่อไปนี้
- อ่านนิพจน์จากซ้ายไปขวา
- อ่านตัวเลข (Operand) ให้ใส่ (Push) ลงไปใน Stackของตัวเลข (Operand)
- อ่านตัวดำเนินการ (Operator) ยกเว้นวงเล็บปิดและเครื่องหมาย"="เท่ากับ ให้ใส่ (Push) ลงไปใน Stackของตัวดำเนินการ (Operator)
- อ่านวงเล็บปิด หรือ เครื่องหมาย"="เท่ากับ
- ให้ดึง (Pop) ตัวดำเนินการ (Operator) หนึ่งตัว
- หากไม่ใช่วงเล็บเปิด (สมมติเป็น "+"บวก) ให้ดึง (Pop) ตัวเลขออกมาสองตัว (สมมติดึงออกมาตัวแรกคือ 2 ตัวที่สองคือ 1) แล้วนำมาดำเนินการกันโดยตัวแรกอยู่ด้านหลังตัวดำเนินการและตัวที่สองอยู่หน้าตัวดำเนินการ (ตามตัวสมมติจะได้เป็น "1+2") แล้วนำผลลัพธ์ใส่ลงไปใน Stackของตัวเลข (Operand)
- หากเป็นวงเล็บเปิด ไม่ต้องทำอะไร
- วนซ้ำข้อ 4 ไปเรื่อยๆจนกว่า Stackของตัวดำเนินการ (Operator) จะว่างเปล่า (Empty)
สามารถดาวน์โหลด Library สำหรับ StackArray ได้จาก http://playground.arduino.cc/Code/StackArray
ผลการออกแบบ
โค้ด Arduino
ผลการทดลองการทำงาน
ผลการออกแบบ
โค้ด Arduino
#include <StackArray.h> byte byteRead; int num, num1, num2, answer; byte op; boolean haveNum = false; //ไว้กันสำหรับเครื่องหมายกับวงเล็บต่อกัน ห้ามใส่ num ลงไปใน stack StackArraynumber_stack; StackArray operator_stack; void setup() { Serial.begin(9600); num=0; num1=0; num2=0; op = 43; } void loop() { while (Serial.available()) { byteRead = Serial.read(); //listen for numbers between 0-9 if(byteRead>47 && byteRead<58){ num=(num*10)+(byteRead-48); haveNum = true; } if(byteRead==61){ if(number_stack.count() == 1 && operator_stack.isEmpty()){ }else{ /********************************************************/ if(haveNum == true){ number_stack.push(num); //push เลขล่าสุดลง stack num=0; //resetค่า } while(!operator_stack.isEmpty()){ op = operator_stack.pop(); //ถ้ามี op ดึง op ออกมา if(op != 40){ //ถ้าไม่ใช่เครื่องหมายวงเล็บเปิดก็คำนวน ถ้าใช่ก็แค่ pop วงเล็บทิ้ง num2 = number_stack.pop(); //ใส่ทีหลังเป็น B num1 = number_stack.pop(); //ใส่ก่อนเป็น A answer = cal(num1,num2,op); //คำนวนพื้นฐาน number_stack.push(answer); //เอาผลกลับใส่ stack } } /********************************************************/ } answer = number_stack.pop(); //ตัวเลขที่เหลือออกมา Serial.print("="); Serial.println(answer); /* Reset the variables for the next round */ while(!operator_stack.isEmpty()){ op = operator_stack.pop(); } while(!number_stack.isEmpty()){ num = number_stack.pop(); } answer=0; num1=0; num2=0; num=0; op=43; }else{ if (byteRead==43||byteRead==45||byteRead==42||byteRead==47||byteRead==37||byteRead==94||byteRead==40){ // + - * / % ^ ( operator_stack.push(byteRead); if(haveNum == true){//byteRead!=40 && number_stack.push(num); num=0; } haveNum = false; } if (byteRead==41){//วงเล็บปิด if(!operator_stack.isEmpty()){ //ถ้าemptyคือเป็นวงเล็บซ้อนตอนจบ /********************************************************/ if(haveNum == true){ number_stack.push(num); //push เลขล่าสุดลง stack num=0; //resetค่า haveNum = false; } while(!operator_stack.isEmpty()){ op = operator_stack.pop(); //ถ้ามี op ดึง op ออกมา if(op != 40){ //ถ้าไม่ใช่เครื่องหมายวงเล็บเปิดก็คำนวน ถ้าใช่ก็แค่ pop วงเล็บทิ้ง num2 = number_stack.pop(); //ใส่ทีหลังเป็น B num1 = number_stack.pop(); //ใส่ก่อนเป็น A answer = cal(num1,num2,op); //คำนวนพื้นฐาน number_stack.push(answer); //เอาผลกลับใส่ stack } } /********************************************************/ } } } } } int cal(int num1,int num2,byte op){ //ฟังก์ชันคำนวนพื้นฐาน if (op==43){answer=num1+num2;} if (op==45){answer=num1-num2;} if (op==42){answer=num1*num2;} if (op==47){answer=num1/num2;} if (op==37){answer=num1%num2;} if (op==94){answer=powint(num1,num2);} return answer; } int powint(int x, int y){ /*ref: http://forum.arduino.cc/index.php?topic=3056.0*/ int val=x; for(int z=0;z<=y;z++){ if(z==0){ val=1; }else{ val=val*x; } } return val; }
ผลการทดลองการทำงาน
ไม่มีความคิดเห็น:
แสดงความคิดเห็น