"การทดลองใช้ Arduino ควบคุมอุณหภูมิด้วยระบบ PID"
นำเสนอโดย จักราวุธ บุญชู
ระบบ PID เป็นวิธีการควบคุมระบบแบบหนึ่ง ประกอบด้วยการคำนวณสมการทางคณิตศาสตร์ 3 ส่วน คือ Proportional, Integral และ Derivative control โดยทั้ง 3 ส่วนนี้จะทำหน้าที่หลักต่างกัน เพื่อช่วยกันส่งเสริมและชดเชยการควบคุม ให้มีเสถียรภาพที่สุด แต่อย่างไรก็ตาม PID control ก็อ้างอิงสมการทางคณิตศาสตร์ แต่ในการทดลองนี้ได้เรียกใช้ Library PID ที่มีสมการทางคณิตศาสตร์อยู่แล้วซึ่งสามารถเรียกใช้งานได้เลยเพียงป้อนค่าอินพุต ค่าที่ต้องการ ค่า Kp Ki Kd ให้ฟังก์ชัน ก็จะมีการคำนวณค่าเอาท์พุตที่จะทำค่าอินพุตเข้าหาค่า ที่ต้องการ
การทดลอง
1. เปิดโปรแกรมแล้วเลือก File > Examples > PID_Beta6 > Example > PIDSample เมื่อเปิดขึ้นมาแล้วจะได้ code ดังรูป
คำสั่งที่เกี่ยวข้องกับ Library PID
PID myPID(&Input, &Output, &Setpoint,2,5,1);คือ คำสั่งส่งและรับค่าให้กับฟังก์ชันใน Library ที่มีการรับค่า อินพุต เอาท์พุต ค่าทีเราต้องการ ค่า Kp , Ki ,Kd ตามลำดับ
Set point = xxxx; คือ การตั้งค่าที่ต้องการ
myPID.SetMode(AUTO); คือ คำสั่งเปิดลูปเปิด PID ให้มีการทำงานแบบอัตโนมัติ ซึ่งใน Library นี้มีให้เลือกอยู่ 2 โหมด คือ Auto และ Manual
myPID.Compute(); คือ คำสั่งเรียกใช้ฟังก์ชันคำนวณ
จากรูปที่ 2 ให้เพิ่มคำสั่งเพื่อให้โปรแกรมแสดง ค่า อินพุต เอาท์พุต และค่าที่เราต้องการ ด้วยคำสั่ง
Serial.print(" "); และทำการกำหนด Baud rate ด้วยคำสั่ง Serial.begin(9600);
ดังรูปที่ 3
จากนั้นทำการ Compiler เมื่อไม่มี error แล้วให้ตรวจสอบว่า Port com ที่ใช้ตรงกันหรือยัง และต้องดูด้วยว่าเบอร์ไอซีที่ให้นั้นถูกต้องหรือไม่ ดังรูปที่ 4 รูปที่ 5 และ รูปที่ 6
เมื่อตรวจสอบเรียบร้อยแล้วให้ทำการโหลดโปรแกรมเข้าไอซี จะนั้นก็ต่อวงจรเพื่อทดลอง ดังรูปที่ 7 และ รูปที่ 8
สามารถดูค่า อินพุต เอาท์พุต ได้โดยการเปิดหน้าต่าง Terminal ดังรูปที่ 9
จากเห็นได้ว่าการที่เราดูค่าจะ Terminal นั้นจะมองได้ยากว่าการลู่เข้าจะช้าหรือเร็ว ดังนั้นต้องมีเขียนกราฟเพื่อที่ให้มองได้ง่ายขึ้นโดยใช้โปรแกรม processing ต้องเพิ่ม code ดังนี้
#include
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint,2,5,1);
unsigned long serialTime;
void setup()
{
Serial.begin(9600);
Input = analogRead(0);
Setpoint = 100;
myPID.SetMode(AUTO);
}
void loop()
{
Input = analogRead(0);
myPID.Compute();
analogWrite(3,Output);
if(millis()>serialTime)
{
SerialReceive();
SerialSend();
serialTime+=5;
}
delay(500);
}
union {
byte asBytes[24];
float asFloat[6];
}
foo;
void SerialReceive()
{
int index=0;
byte Auto_Man = -1;
while(Serial.available()&&index<25)
{
if(index==0) Auto_Man = Serial.read();
else foo.asBytes[index-1] = Serial.read();
index++;
}
if(index==25 && (Auto_Man==0 || Auto_Man==1))
{
Setpoint=double(foo.asFloat[0]);
if(Auto_Man==0)
{
Output=double(foo.asFloat[2]);
}
double p, i, d;
p = double(foo.asFloat[3]);
i = double(foo.asFloat[4]);
d = double(foo.asFloat[5]);
myPID.SetTunings(p, i, d);
if(Auto_Man==0) myPID.SetMode(MANUAL);
else myPID.SetMode(AUTO);
}
Serial.flush();
}
void SerialSend()
{
Serial.print("PID ");
Serial.print(Setpoint);
Serial.print(" ");
Serial.print(Input);
Serial.print(" ");
Serial.print(Output);
Serial.print(" ");
Serial.print(myPID.GetP_Param());
Serial.print(" ");
Serial.print(myPID.GetI_Param());
Serial.print(" ");
Serial.print(myPID.GetD_Param());
Serial.print(" ");
if(myPID.GetMode()==AUTO) Serial.println("Automatic");
else Serial.println("Manual");
}
เมื่อเขียนโปรแกรมเรียบร้อยแล้วก็ทำการโหลดโปรแกรม และเปิดโปรแกรม Processing ไฟล์ชื่อ PID_Plot แล้วกดรันโปรแกรม ดังรูปที่ 10
Serial.print(myPID.GetP_Param());
ตอบลบอยากทราบว่า .GetP_Param คืออะไรครับและเอามาขากไหน