คำอธิบาย
นำเสนอ ชุดเรียนรู้+ชุดทดลอง ชุดเรียนรู้+ชุดทดลอง ตัวควบคุมพีไอดีแกนใบพัด Arduino PID Control Vertical Take-Off PID-V2 (2 ใบพัด) เรียนรู้หลักการควบคุม PID และการปรับแต่ง ผ่านชุดทดลอง PID motor control พื้นฐานสู่การควบคุมอัตโนมัติ
ตัวอย่างการใช้ Arduino
- การควบคุมแบบ P Control
- การควบคุมแบบ PI Control
- การควบคุมแบบ PID Control
Download
- คู่มือชุดทดลอง PID เวอร์ชั่น 2 รุ่น 2 ใบพัด https://docs.google.com/document/d/14CfWwO3UU7WUvbsn-z-fpM8w0dl1KMf2feZlcDq1WH0/edit?usp=sharing
- Source Code พร้อมทดลอง Code PID V2 และ PID Libraly https://drive.google.com/drive/folders/1qzyScbnFE_NOqYWezxroHtxDYTzlHSnE?usp=sharing
ในชุดประกอบด้วย
- 1 เซต x เรียนรู้ชุดทดลอง ตัวควบคุม PID รุ่น 2 ใบพัด
- *ในชุดไม่รวมบอร์ด Arduino และ สาย USB
Schematics PCB
คู่มือการทดลองชุดทดลอง PID เวอร์ชั่น2 รุ่น 2 ใบพัด
เพื่อให้แน่ใจว่าถูกต้อง และผลลัพธ์การควบคุมจะเป็นไปตามตัวอย่างที่นำเสนอ โปรดตรวจสอบการต่อสายไฟที่เชื่อมโยงระหว่างบอร์ดทดลองและบอร์ด Arduino ที่นำมาต่อด้วยความรอบคอบ
- จ่ายไฟบวก 5 โวลท์เข้าที่พอร์ต USB ของชุดทดลอง PID-V2 สามารถใช้ไฟจาก USB หรือที่ชาร์จโทรศัพท์หรือพาวเวอร์แบงค์ก็ได้
- เชื่อมต่อสายสัญญาณเข้ากับบอร์ด Arduino UNO ดังต่อไปนี้
- เชื่อมต่อขา ดิจิตอล 9 และ 10 ของ Arduino UNO กับ IN1+ IN1- ของชุดทดลอง PID V2 เพื่อควบคุมมอเตอร์ตัวที่ 1 หรือ ฝั่งซ้ายมือ
- เชื่อมต่อขาดิจิตอล 11 และ 12 ของ Arduino UNO กับ IN2+ IN2- ของชุดทดลอง PID-V2 เพื่อควบคุมมอเตอร์ตัวที่ 2 หรือฝั่งขวามือ
- เชื่อมต่อขา analog ของ ตัวต้านทานปรับค่าได้ซึ่งในชุดทดลองเขียนว่า FB ให้ต่อเข้ากับขา analog 4 (A4)ของ Arduino UNO
- เชื่อมต่อขา +Vin ของชุดทดลอง PID V2 เข้ากับ +5V ของ Arduino UNO
- เชื่อมต่อขา GND ของชุดทดลอง PID V2 เข้ากับ GND ของ Arduino UNO
มาเริ่มกันด้วยบล็อกไดอะแกรมการควบคุมชุดแกนใบพัดแบบมอเตอร์ 2 ตัวเป็นดังรูปที่ 1
รูปที่ 1 บล็อกไดอะแกรมการควบคุมชุดแกนใบพัด รุ่น 2 มอเตอร์
การทำงานจะเริ่มจาก ค่า setpoint หรือค่าที่เราต้องการ จะถูกกำหนดไว้ในโปรแกรม ในตัวอย่างโค้ดคือบรรทัดที่ 35 ในที่นี้ค่าคือ 500 ซึ่งที่ค่านี้ตัวควบคุม PID จะทำให้แกนใบพัดเคลื่อนที่มาอยู่ในตำแหน่งที่ขนานกับพื้น
1 |
void loop() { Setpoint = 500; //เซตให้อยู่ตรงกลาง หากไม่ใช้ให้ใส่ // ข้างหน้า |
สัญญาณป้อนกลับของระบบจะได้มาจากตัวต้านทานปรับค่าได้ ซึ่งมีแกนใบพัดติดอยู่ แรงดันเอาต์พุตของตัวต้านทานปรับค่าได้จะอยู่ในช่วง 0 ถึง 5 โวลต์ จากนั้นจะถูกแปลงเป็นสัญญาณดิจิตอลขนาด 10 บิต ด้วยโมดูลแปลงค่าอนาลอกเป็นดิจิตอลภายในตัวไมโครคอนโทรลเลอร์ ที่อยู่บนบอร์ด Arduino สัญญาณดิจิตอลที่แปลงได้นี้จะมีค่า 0 ถึง 1023
ค่า setpoint จะถูกนำมาลบด้วยค่าสัญญาณป้อนกลับ ได้เป็นสัญญาณ Error ก่อนที่จะป้อนเข้าสู่ตัวควบคุม PID เอาต์พุตของ PID จะเป็นสัญญาณ PWM ส่งไปยัง Driver motor เพื่อขับให้มอเตอร์หมุนใบพัดสร้างแรงยก หรือแรงผลักลง ให้แกนใบพัดเข้าสู่ตำแหน่งเป้าหมายที่ต้องการ
การควบคุม PID ในปัจจุบันสามารถทำได้ง่ายขึ้นมาก เพียงแค่การเรียกใช้ไลเบอรี่ที่มีโปรแกรมเมอร์ใจดีสร้างมาให้ใช้ เรามาเรียนรู้การประยุกต์ใช้ ไลเบอรี่ตัวนี้กันสักเล็กน้อย เริ่มจากการใช้งานจำเป็นต้องมีการ เรียกฟังชั่นมาใช้ด้วยวิธีในบรรทัดที่1 คือ คำสั่ง include ตามด้วยชื่อไลเบอรี่ ดังรูปด้านล่าง
1 |
#include <PID_v1.h>// เรียกใช้งาน Arduino-PID-Library https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h |
ต่อมาเป็นการประกาศตัวแปรในการควบคุมไอซีขับมอเตอร์ ซึ่งต่อกับขาต่างๆ ดังนี้
1 2 3 4 |
const int AIA = 9; // (pwm) pin connected to pin IN2- const int AIB = 10; // (pwm) pin connected to pin IN2+ const int BIA = 11; // (pwm) pin connected to pin IN1- const int BIB = 12; // (pwm) pin connected to pin IN1+ |
การประกาศตัวแปร ที่ใช้ในโปรแกรม
การประกาศตัวแปร พร้อมกับกำหนดค่าที่ต้องการ ในที่นี้คือตัวแปรเกี่ยวกับค่า PID พารามิเตอร์ ที่ประกอบด้วย ค่า Kp Ki และ Kd
1 2 3 4 5 6 7 |
double Setpoint, Feedback, Output; int count_time; //จูนระบบด้วยการปรับค่าเกน Kp และ Ki double Kp=50, Ki=30, Kd=0.8; // กำหนดค่าเกนทั้งสามตัว // เปิดการใช้งาน Arduino-PID-Library PID myPID(&Feedback, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); |
ส่วนการเปิดใช้งานฟังชั่น PID สร้างฟังชั่นPID ขึ้นมาที่ชื่อ myPID โดยมีการรับสัญญาณป้อนกลับที่ตัวแปรชื่อ Feedback และ สัญญาณเอาต์พุตที่คำนวณเสร็จแล้วจะถูกใส่ไว้ในตัวแปรที่ชื่อ Output และค่าที่ต้องการจะต้องใส่ค่าในตัวแปรชื่อ Setpoint สุดท้ายตามด้วย พารามิเตอร์ Kp Ki และ Kd ตามลำดับ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void setup(){ pinMode(AIA, OUTPUT); // set pins to output pinMode(AIB, OUTPUT); pinMode(BIA, OUTPUT); pinMode(BIB, OUTPUT); Setpoint = 500;//อ่านค่าทั้งต้องการ Feedback = analogRead(A4); //อ่านค่าจากตัวตรวจจับตำแหน่ง //turn the PID on myPID.SetMode(AUTOMATIC); myPID.SetSampleTime(1); myPID.SetOutputLimits(-255, 255); // ถ้าใช้ไฟจ่าย USB คอมพิวเตอร์ ลิมิตที่ +/-128 เพื่อไม่ให้คอมพอร์ตรีเซต // แต่ถ้าใช้พาวเวอร์แบงค์ ค่าสูงสุดคือ +/-255 Serial.begin(19200); } |
ในส่วนการ setup เป็นการกำหนดขาที่ใช้ควบคุมชิปขับมอเตอร์ให้เป็นเอาต์พุต ทำการเซตค่า Setpoint เริ่มต้น เป็น 500
1 2 3 4 |
pinMode(AIA, OUTPUT); // set pins to output pinMode(AIB, OUTPUT); pinMode(BIA, OUTPUT); pinMode(BIB, OUTPUT); |
ในส่วนการอ่านค่าสัญญาณอนาลอกที่ขา A4 ค่าที่อ่านได้จะถูกเก็บไว้ในตัวแปรชื่อ Feedback
1 |
Setpoint = 500;//อ่านค่าทั้งต้องการ |
การตั้งค่าการทำงานของโมดูล PID กำหนดโหมดการทำงานเป็น Automatic ถัดมาเป็นการกำหนดค่าเวลาแซมปลิ้ง ในที่นี้กำหนดเป็นทุกๆ 1 msec (ถ้าไม่กำหนดจะมีค่าเริ่มต้นที่ 100 มิลลิเซค)
1 2 |
myPID.SetMode(AUTOMATIC); myPID.SetSampleTime(1); |
ในส่วนการกำหนดค่าสูงสุดต่ำสุดของเอาต์พุต ในที่นี้กำหนดให้เป็น +/-255 ที่กำหนดให้มีเครื่องหมายบวกลบเนื่องจากการควบคุมมอเตอร์ในชุดทดลองนี้ต้องมีการหมุนกลับทางด้วยเราจึงใช้เครื่องหมายเป็นตัวบอกทิศทางว่าจะให้หมุนทวนเข็มหรือหมุนตามเข็ม ส่วนการหมุนช้าหรือหมุนเร็วจะมีค่า 0 ถึง 255 โดย 0 หมายถึงหยุดหมุน และ 255 หมายถึง หมุนเต็มกำลังสูงสุด
1 2 3 |
myPID.SetOutputLimits(-255, 255); // ถ้าใช้ไฟจ่าย USB คอมพิวเตอร์ ลิมิตที่ +/-128 เพื่อไม่ให้คอมพอร์ตรีเซต // แต่ถ้าใช้พาวเวอร์แบงค์ ค่าสูงสุดคือ +/-255 Serial.begin(19200); |
ในการทำงานปกติ ในฟังชัน loop การควบคุมตำแหน่งของแกนใบพัดจะวนลูปเพื่อทำงานที่เป็นขั้นตอนซ้ำๆ กัน ดังนี้คือ อันดับแรกอ่านค่า Setpoint ต่อมา อ่าน Feedback ที่ขา A4 ต่อมาทำการคำนวณ PID และสุดท้ายส่งค่าเอาต์พุตไปยังไอซีขับมอเตอร์
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Feedback = analogRead(A4); // อ่านค่าจากเซนเซอร์ตรวจจับตำแหน่ง myPID.Compute(); // สั่งให้ตัวPID เริ่มคำนวณ //ค่าoutput จะอยู่ในช่วง +255 -255 if(Output>0) //1 ถึง 255 { analogWrite(AIA, Output); analogWrite(AIB, 0); analogWrite(BIA, 0); analogWrite(BIB, Output); } if(Output==0) // สัญญาณป้อนกลับเท่ากับค่าที่ต้องการ สั่งมอเตอร์หยุด { analogWrite(AIA, 0); analogWrite(AIB, 0); analogWrite(BIA, 0); analogWrite(BIB, 0); } if(Output<0) //-1 ถึง -255 { Output = Output *-1; analogWrite(AIA, 0); analogWrite(AIB, Output); analogWrite(BIA, Output); analogWrite(BIB, 0); } |
เงื่อนไข ค่าเอาต์พุตที่ออกจาก PID จะอยู่ในช่วง 1 ถึง 255 (ค่าบวก) จะสั่งให้มอเตอร์ M1 หมุนตามเข็มเกิดแรงกดลง และมอเตอร์ M2 หมุนทวนเข็มเกิดแรงยก
1 2 3 4 5 6 7 |
if(Output>0) //1 ถึง 255 { analogWrite(AIA, Output); analogWrite(AIB, 0); analogWrite(BIA, 0); analogWrite(BIB, Output); } |
เงื่อนไข ค่าเอาต์พุตจะเป็น 0 คือสั่งให้มอเตอร์หยุดหมุน
1 2 3 4 5 6 7 |
if(Output==0) // สัญญาณป้อนกลับเท่ากับค่าที่ต้องการ สั่งมอเตอร์หยุด { analogWrite(AIA, 0); analogWrite(AIB, 0); analogWrite(BIA, 0); analogWrite(BIB, 0); } |
เงื่อนไข ค่าเอาต์พุตที่ออกจาก PID จะอยู่ในช่วง -1 ถึง -255 (ค่าลบ) จะสั่งให้มอเตอร์ M2 หมุนตามเข็มเกิดแรงกดลง และมอเตอร์ M1 หมุนทวนเข็มเกิดแรงยก
1 2 3 4 5 6 7 |
if(Output>0) //1 ถึง 255 { analogWrite(AIA, Output); analogWrite(AIB, 0); analogWrite(BIA, 0); analogWrite(BIB, Output); } |
การควบคุมแบบ P control
การควบคุมลักษณะนี้ เราจะกำหนดให้เทอม Ki และ Kd มีค่าเท่ากับ 0 ค่าพารามิเตอร์จะมีเฉพาะค่า Kp อย่างเดียวเท่านั้น ตัวอย่างการปรับค่าพารามิเตอร์ เป็นดังรูปด้านล่าง เสร็จแล้วอัปโหลดโค้ดไปยังบอร์ด Arduino ดูผลตอบสนอง
รูปที่ 10 ลักษณะสัญญาณป้อนกลับ (เส้นสีแดง) เมื่อควบคุมด้วย P control เพียงอย่างเดียว จะมีปัญหาออฟเซต
รูปที่ 11 หากเพิ่มค่า Kp มากขึ้น เพื่ออยากจะกำจัดออฟเซต ก็จะเกิดการแกว่งกลับไปมาระหว่าง setpoint
อธิบายการทำงานของ P control
การควบคุมแบบ P control เรียกอีกอย่างว่า การควบคุมแบบสัดส่วน กล่าวคือ สัญญาณเอาต์พุตจะมีค่ามากทีสุด เมื่อสัญญาณป้อนกลับ(feed back signal) อยู่ห่างจากค่าที่ต้องการ (setpoint) มากๆ จากนั้นสัญญาณเอาต์พุตจะค่อยๆ ลดลง จนเข้าใกล้ศูนย์ เมื่อสัญญาณ feed back เข้าใกล้ setpoint แต่ ก็ยังไม่สามารถเข้ายังตำแหน่ง setpoint ได้สักที เนื่องจากสัญญาณเอาต์พุต มีค่าน้อยมาก เข้าใกล้ศูนย์ จึงไม่มีแรงพอที่จะดันให้กลไก(ในกรณีนี้คือแกนใบพัด) เข้าถึงตำแหน่ง setpoint ที่ต้องการได้ ทำได้แค่เข้าใกล้ แต่ยังไม่ใช่ตำแหน่งที่ต้องการจริงๆ เมื่อซูมเข้าไปใกล้ๆ ลักษณะจะเป็นดังรูปที่ 10
จุด A คือการใช้มือผลักแกนใบพัดให้ออกจากตำแหน่งกลาง (ค่าsetpoint = 500 เพราะค่า ADC จะอยู่ในช่วง 0-1023) จะเห็นว่าทันทีที่สัญญาณ feed back (เส้นสีแดง) ออกห่างจากค่า setpoint (เส้นสีน้ำเงิน) ให้สังเกตที่
จุด B สัญญาณเอาต์พุตที่จะไปขับมอเตอร์จะเพิ่มขึ้นทันทีเป็น 100 % (เส้นสีเขียว) (ค่า 100% มีค่าเท่ากับ 255 และ 0% มีค่าเท่ากับ 0 ซึ่งจะส่งไปยังไอซีขับมอเตอร์ ) เมื่อเวลาผ่านไป สังเกตที่
จุด C จะเห็นเส้นขนานที่เกิดจากเส้นสีน้ำเงินและเส้นสีแดง เนื่องจากแรงดันเอาต์พุตที่ไปขับมอเตอร์มีค่าน้อยเกินกว่าจะผลักให้แกนใบพัดเข้าสู่ค่า setpoint สังเกตที่
จุด D จะเห็นเส้นสีเขียว ที่ไม่ใช่ศูนย์ คือมีแรงดันจ่ายให้มอเตอร์ มอเตอร์จะหมุนได้เล็กน้อยแต่ไม่แรงพอให้แกนเคลื่อนเข้าสู่ set point สุดท้ายจึงทำให้แกนใบพัดค้างอยู่ที่ตำแหน่งดังกล่าวตลอดไปจนกว่าจะมีแรงภายนอกมากระทำหรือ เปลี่ยนแปลงค่า setpoint อีกครั้ง ภาวะที่เกิดช่องว่างระหว่างค่า setpoint และสัญญาณ feed back เรียกว่าการเกิดค่าออฟเซต ซึ่งเป็นพฤติกรรมที่เป็นธรรมชาตติของการควบคุมแบบ P control อยู่แล้วแต่ถ้าเราหากต้องการกำจัดออฟเซตที่ว่านี้ ด้วยการใช้วิธีการควบคุมแบบ P control สิ่งที่เราต้องทำก็คือ การเพิ่มค่า Kp ให้มากขึ้นกว่าเดิม ไปเรื่อยๆ จนค่าออฟเซตนี้แคบลงเรื่อยๆ แต่เมื่อเพิ่มถึงค่าหนึ่ง จะระบบจะไม่ขยับเข้าใกล้ setpoint แล้ว แต่จะเกิดการแกว่งไปมารอบๆ ค่า setpoint แทน เป็นดังรูปที่ 11 ค่าแรงดันที่จ่ายไปยังมอเตอร์มีค่าสูงสุดทันทีทำให้เกิดแรงในทิศทางตรงกันข้ามผลักให้แกนใบพัดเข้าสู่ setpoint แต่เนื่องจากมอเตอร์หมุนแรงเกินไป ทำให้เกิดแรงเฉื่อย แม้ว่าจะหยุดหมุนมอเตอร์แล้วก็ตาม ส่งผลให้แกนใบพัดเคลื่อนที่เลยค่า setpoint ไปทำให้ตัวควบคุม P สั่งให้มอเตอร์หมุนกลับในทิศทางตรงกันข้ามด้วยความแรงสูงสุดอีกครั้ง เป็นแบบนี้เรื่อยไป เป็นผลให้เมื่อสังเกตที่แกนใบพัด จะเห็นว่ามันเคลื่อนที่ขึ้นและลง กลับไปกลับมาการเคลื่อนที่แบบนี้เป็นสิ่งที่เราไม่ต้องการ วิธีแก้ไขก็คือ ต้องลดค่า Kp จนแกนใบพัดหยุดแกว่งไปมา อย่างไรก็ตามเราก็ยังคือเผชิญกับปัญหาออฟเซตเช่นเดิม
การควบคุมแบบ PI control
เมื่อแก้ปัญหาออฟเซตที่เกิดขึ้นกับ P control เราจึงต้องใช้ การควบคุมแบบอินทิกรัล เพิ่มเข้ามา เป็น PI control จุดประสงค์ก็เพื่อกำจัดค่าออฟเซต ที่เกิดขึ้นเมื่อระบบเข้าสู่ภาวะคงตัว (steady state) เมื่อเวลาผ่านไปตัวอินทิกรัลจะนำค่า error ที่เกิดมาสะสมจนมากขึ้นเรื่อยๆ และส่งเอาต์พุตไปขับมอเตอร์ให้ค่อยๆ หมุนแรงขึ้น และผลักแกนใบพัดเคลื่อนเข้าสู่ setpoint อย่างนิ่มนวล ดังรูปที่ 12
รูปที่12 กราฟการควบคุมด้วย PI control
อธิบายการทำงานของ PI control
จากรูปที่12 จุด A เราใช้มือไปผลักให้แกนใบพัด(เส้นสีแดง)เคลื่อนจากตำแหน่ง setpoint (เส้นสีน้ำเงิน) ด้วยการควบคุมที่มีเทอม P และเทอม I ร่วมกันทำงาน จะเห็นว่าตำแหน่งของแกนใบพัดเคลื่อนเข้าสู่ setpoint ได้อย่างสมบูรณ์
ที่ตำแหน่ง B จะเห็นว่าระหว่างทางจากจุด A ไปยังจุดB มีการแกว่งขึ้นลงเล็กน้อย และสังเกตที่จุด C จะเห็นว่า เมื่อแม้ว่าจะเข้าสู่ setpoint แล้ว ก็ยังมีเอาต์พุต(เส้นสีเขียว)ส่งออกไปยังไอซีขับมอเตอร์เพื่อรักษาให้แกนอยู่ในตำแหน่ง
การเพิ่มค่า Ki นี้จากประสบการณ์แล้ว จะค่อยๆ เพิ่มและดูผลตอบสนองของระบบ การทำลักษณะนี้เรียกว่าการจูน ด้วยเทคนิคลองผิดลองถูก (Trial and error) จนกว่าจะได้การตอบสนองของระบบที่ผู้ควบคุมพึงพอใจ ซึ่งตรงจุดนี้จะขึ้นอยู่กับความต้องการของระบบว่า 1.ต้องการเวลาที่เข้าสู่ setpoint มากน้อยเพียง 2.ยอมให้มีโอเวอร์ชู๊ตหรือไม่ 3.ค่าความผิดพลาดยอมรับได้เท่าไร เมื่อระบบเข้าสู่สภาวะคงตัวแล้ว ทั้งหมดนี้จะเป็นตัวตัดสินว่าจะหยุดจูนได้เมื่อใด
การควบคุม PID control
จากการควบคุม PI control ที่ผ่านมาจะเห็นว่า ระหว่างทางตั้งแต่ระบบถูกรบกวนด้วยการใช้มือผลักแกนใบพัดให้เคลื่อนออกจากตำแหน่งที่เป็นอยู่เดิม จะยังมีการแกว่งขึ้นลงรอบเส้น setpoint อยู่ ไปจนถึงกลับมาอยู่ที่ตำแหน่งเดิมนั้น หากความต้องการของระบบ ไม่ยอมให้มีโอเวอร์ชู๊ต เราจำเป็นต้องเพิ่มเทอม D เข้ามา ตัวอย่างผลการทดลองเมื่อเพิ่มเทอม D เข้ามาเป็นดังรูปที่ 13
รูปที่13 ผลตอบสนองการควบคุมแกนใบพัดด้วย PID control
เทอม D ที่เพิ่มเข้านี้ จะทำหน้าที่ต้านทานการเปลี่ยนแปลงแบบฉับพลัน ซึ่ง D ย่อมาจาก Differeial สังเกตที่ตำแหน่ง A คือจุดที่ใช้มือผลักแกนใบพัด หลังจากนั้นตัวควบคุม PID จะควบคุมให้แกนใบพัดค่อยๆ เคลื่อนเข้าสู่ Setpoint ได้ โดยไม่มีโอเวอร์ชู๊ต ที่บริเวณจุด B เมื่อเทียบกับรูปที่ 12 อย่างไรก็ตาม ผู้ทดลองสามารถเปลี่ยนแปลงค่า Kp, Ki, Kd ได้ตามความเหมาะสม และเรียนรู้พฤติกรรมของระบบควบคุมที่เกิดขึ้น เมื่อค่า PID พารามิเตอร์ ทั้งสามตัวเปลี่ยนแปลงไป และอย่างลืมว่าค่า PID พารามิเตอร์นี้ก็จะเหมาะสมกับระบบที่จูนนั้นๆ การนำไปประยุกตใช้ควบคุมระบบอื่นๆ เช่น ความร้อน ความเย็น ความดันอากาศ ความเร็วรอบมอเตอร์ ก็ต้องมีการจูนค่า PID พารามิเตอร์เหล่านี้ใหม่ แต่หลักการ จูนค่า ก็ยังคงใช้เหมือนเดิม
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
#include <PID_v1.h>// เรียกใช้งาน Arduino-PID-Library https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h const int AIA = 9; // (pwm) pin connected to pin IN2- const int AIB = 10; // (pwm) pin connected to pin IN2+ const int BIA = 11; // (pwm) pin connected to pin IN1- const int BIB = 12; // (pwm) pin connected to pin IN1+ double Setpoint, Feedback, Output; int count_time; //จูนระบบด้วยการปรับค่าเกน Kp และ Ki double Kp=50, Ki=30, Kd=0.8; // กำหนดค่าเกนทั้งสามตัว // เปิดการใช้งาน Arduino-PID-Library PID myPID(&Feedback, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); void setup(){ pinMode(AIA, OUTPUT); // set pins to output pinMode(AIB, OUTPUT); pinMode(BIA, OUTPUT); pinMode(BIB, OUTPUT); Setpoint = 500;//อ่านค่าทั้งต้องการ Feedback = analogRead(A4); //อ่านค่าจากตัวตรวจจับตำแหน่ง //turn the PID on myPID.SetMode(AUTOMATIC); myPID.SetSampleTime(1); myPID.SetOutputLimits(-255, 255); // ถ้าใช้ไฟจ่าย USB คอมพิวเตอร์ ลิมิตที่ +/-128 เพื่อไม่ให้คอมพอร์ตรีเซต // แต่ถ้าใช้พาวเวอร์แบงค์ ค่าสูงสุดคือ +/-255 Serial.begin(19200); } void loop() { Setpoint = 500; //เซตให้อยู่ตรงกลาง หากไม่ใช้ให้ใส่ // ข้างหน้า //count_time++; //หากต้องการดูผลตอบสนองจะต้องมีการเปลี่ยน setpoint //if(count_time<=400)Setpoint = 450; // กลับไปมา ในที่นี้คือค่า 450 กับ 650 //if(count_time>400)Setpoint = 650; // แกนใบพัดก็จะเปลี่ยนตำแหน่งไปมา //if(count_time>800)count_time = 0; // ให้เอาเครื่องหมาย // หน้าบรรทัดที่ 37 ถึง 40 ออก Feedback = analogRead(A4); // อ่านค่าจากเซนเซอร์ตรวจจับตำแหน่ง myPID.Compute(); // สั่งให้ตัวPID เริ่มคำนวณ //ค่าoutput จะอยู่ในช่วง +255 -255 if(Output>0) //1 ถึง 255 { analogWrite(AIA, Output); analogWrite(AIB, 0); analogWrite(BIA, 0); analogWrite(BIB, Output); } if(Output==0) // สัญญาณป้อนกลับเท่ากับค่าที่ต้องการ สั่งมอเตอร์หยุด { analogWrite(AIA, 0); analogWrite(AIB, 0); analogWrite(BIA, 0); analogWrite(BIB, 0); } if(Output<0) //-1 ถึง -255 { Output = Output *-1; analogWrite(AIA, 0); analogWrite(AIB, Output); analogWrite(BIA, Output); analogWrite(BIB, 0); } // แสดงผลกราฟ Serial.print("\n"); // New line Serial.print (Setpoint); // Setpoint มีค่าอยู่ในช่วง 0 ถึง 1023 Serial.print("\t"); Serial.print (Feedback); // Feedback มีค่าอยู่ในช่วง 0 ถึง 1023 Serial.print("\t"); Serial.print((Output/255)*100); // Output มีค่าอยู่ในช่วง 0 ถึง 255 Serial.print("\t"); // แต่เวลาแสดงผลทำเป็น% อยู่ในช่วง 0-100% Serial.print( 1000); Serial.print("\t"); Serial.print( 100); Serial.print("\t"); Serial.print( 0); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#include <PID_v1.h>// เรียกใช้งาน Arduino-PID-Library https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h const int AIA = 9; // (pwm) pin connected to pin IN1+ const int AIB = 10; // (pwm) pin connected to pin IN1- const int BIA = 11; // (pwm) pin connected to pin IN2+ const int BIB = 12; // (pwm) pin connected to pin IN2- #define NUMPWM 2 double Setpoint, Feedback, Output; int count_time; //จูนระบบด้วยการปรับค่าเกน Kp และ Ki double Kp=12, Ki=4, Kd=0; // กำหนดค่าเกนทั้งสามตัว PID myPID(&Feedback, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);// เปิดการใช้งาน Arduino-PID-Library void setup(){ pinMode(AIA, OUTPUT); // set pins to output pinMode(AIB, OUTPUT); pinMode(BIA, OUTPUT); pinMode(BIB, OUTPUT); Setpoint = 500;//อ่านค่าทั้งต้องการ Feedback = analogRead(A4); //อ่านค่าจากตัวตรวจจับตำแหน่ง //turn the PID on myPID.SetMode(AUTOMATIC); myPID.SetSampleTime(1); myPID.SetOutputLimits(-255, 255); // ถ้าใช้ไฟจ่าย USB คอมพิวเตอร์ ลิมิตที่ +/-128 เพื่อไม่ให้คอมพอร์ตรีเซต // แต่ถ้าใช้พาวเวอร์แบงค์ ค่าสูงสุดคือ +/-255 Serial.begin(19200); } void loop(){ count_time++; if(count_time<=400)Setpoint = 450; if(count_time>400)Setpoint = 650; if(count_time>800)count_time = 0; Feedback = analogRead(A4); // อ่านค่าจากเซนเซอร์ตรวจจับตำแหน่ง myPID.Compute(); // สั่งให้ตัวPID เริ่มคำนวณ if(Output>0){ analogWrite(AIA, Output); analogWrite(AIB, 0); analogWrite(BIA, 0); analogWrite(BIB, Output); } if(Output<0){ Output = Output *-1; analogWrite(AIA, 0); analogWrite(AIB, Output); analogWrite(BIA, Output); analogWrite(BIB, 0); } // แสดงผลกราฟ Serial.print("\n"); // New line Serial.print((Setpoint/1023)*100); // Setpoint Serial.print("\t"); Serial.print((Feedback/1023)*100); // Feedback Serial.print("\t"); Serial.print((Output/255)*10); // Output Serial.print("\t"); Serial.print( 100); Serial.print("\t"); Serial.print( 10); Serial.print("\t"); Serial.print( 0); } |
รีวิว
ยังไม่มีบทวิจารณ์