Sunday, July 27, 2014

สร้างมอเตอร์จำลองอิเล็กทรอนิกส์กัน

บทความนี้กล่าวถึงการพัฒนาวงจรจำลองการทำงานของมอเตอร์กระแสตรงแบบมีแปรงถ่าน (รูปที่ 1) เพื่อใช้ประกอบการสอนวิชาระบบควบคุม ในกรณีที่ไม่ได้มีการขับเคลื่อนระบบทางกลจริง การใช้มอเตอร์จริงมีข้อเสียคือมีน้ำหนักมากเคลื่อนย้ายไม่สะดวก และในการทดลองอิมพลิเมนต์หรือปรับแต่งตัวควบคุมป้อนกลับ อาจเกิดอันตรายหรือความเสียหายได้เมื่อระบบไม่เสถียร นอกจากนั้นมอเตอร์ของใหม่ยังมีราคาค่อนข้างสูง การซื้อมอเตอร์เก่าจากตลาดมือสองอาจได้อุปกรณ์ที่ไม่สมบูรณ์ เช่นสายเอนโคเดอร์หลวมหรือขาด หรือไม่ทราบว่าต่ออย่างไร ปัญหาทั้งหมดเหล่านี้เป็นอุปสรรคต่อการทดลองขั้นพื้นฐานในห้องปฏิบัติการสาขาระบบควบคุม

 
รูปที่ 1: มอเตอร์ดีซีแบบมีแปรงถ่าน

จากอุปสรรคดังกล่าว ผู้เขียนจึงมีความคิดที่จะสร้างโมเดลอิเล็กทรอนิกส์ที่สามารถจำลองการทำงานของมอเตอร์กระแสตรง ซึ่งต่อไปจะเรียกว่า emotor. ซึ่งคาดว่าจะมีประโยชน์ในการศึกษาระบบควบคุมป้อนกลับขั้นพื้นฐาน เพราะเป็นฮาร์ดแวร์ที่สร้างง่าย ใช้งานง่าย ต้นทุนต่ำ ปลอดภัย และน่าสนใจกว่าการจำลองบนซอฟต์แวร์ล้วนๆ โดยใช้ MATLAB/Simulink หรือ Scilab/Xcos

ในอดีตผู้เขียนได้เคยสร้างโมดูลลักษณะดังที่กล่าว โดยสามารถจำลองมอเตอร์ได้พร้อมกันหลายแกน ตั้งชื่อโปรเจ็คว่า ServoSim. บอร์ดต้นแบบนั้นสามารถสร้างสัญญาณเอนโคเดอร์ได้พร้อมกัน 4 แชนเนล แต่ข้อด้อยคือไม่มีส่วนที่แสดงการหมุนให้เห็นเหมือนมอเตอร์จริง สำหรับโปรเจ็ค emotor ในบทความนี้ จะทำการจำลองมอเตอร์เพียงตัวเดียว มีวงจรง่ายกว่า โดยสามารถสร้างต้นแบบบนบอร์ดอเนกประสงค์ได้ดังแสดงในรูปที่ 2* ใช้เวลาในการบัดกรีเพียงไม่กี่ชั่วโมงเท่านั้น จะเห็นว่านอกจากบอร์ดจะสร้างสัญญาณเอนโคเดอร์แบบส่วนเพิ่ม (incremental encoder) A, B และ index pulse Z แล้ว ยังมี LED 6 ตัว ประกอบเป็นวงกลม มีระยะห่างกัน 60 องศาบนเส้นรอบวง ซึ่งจะเป็นส่วนแสดงการหมุนของมอเตอร์ ความเร็วรอบสามารถสั่งได้จากสัญญาณอินพุตในรูปของ PWM และ DIR ซึ่งเป็นวิธีการเดียวกับที่ใช้ขับมอเตอร์จริงในรูปที่ 1

 
 
รูปที่ 2 บอร์ดต้นแบบของemotor

แผนภาพอย่างง่ายของ emotor แสดงในรูปที่ 3 จะเห็นว่าใช้ไมโครคอนโทรลเลอร์ของ บ.ไมโครชิพ รุ่น dsPIC30F2010 ซึ่งมีราคาต่ำและสมรรถนะเพียงพอสำหรับโครงงาน และเนื่องจากวงจรนี้ไม่ได้ต้องการสัญญาณคล็อกที่เที่ยงตรงมาก จึงสามารถเลือกใช้โมดูลกำเนิดสัญญาณภายในชิพเลย (อย่างไรก็ตามบนบอร์ดต้นแบบได้เตรียมซ็อกเก็ตไว้เผื่อต้องการใช้โมดูลคริสตัลจากภายนอก เช่นถ้าต้องการเพิ่มการสื่อสารผ่าน UART จะต้องการคล็อกที่เที่ยงตรงกว่า)

 
รูปที่ 3 แผนภาพอย่างง่ายของ emotor

จากแผนภาพจะเห็นว่า คำสั่งความเร็วรอบจะรับผ่านอินพุต A/D โดยใช้วงจรฟิลเตอร์ RC อย่างง่ายเพื่อเปลี่ยนสัญญาณ PWM เป็นแรงดันแอนะล็อก ส่วนคำสั่งทิศทางการหมุน DIR จะรับเป็นสัญญาณดิจิทัลได้เลย ในการทดสอบโมดูลสามารถใช้แรงดันที่ได้จาก VR โดยเลือกจัมเปอร์ 2 ตัว ให้อินพุตความเร็วไปต่อกับ VR และอินพุตทิศทางต่อกับจัมเปอร์ที่เลือกระดับลอจิก 0/1 โดยเมื่อปรับ VR ตามเข็มนาฬิกาจะเป็นการเพิ่มความเร็วรอบ เมื่อตั้งจัมเปอร์ให้ DIR=0 จะทำให้ emotor หมุนตามเข็ม ขณะที่ DIR=1 จะหมุนทวนเข็ม สัญญาณเอนโคเดอร์ QA, QB, Z เป็นเอาต์พุตออกที่ขา RB4, RB5, RD1 ตามลำดับ (บนบอร์ดต้นแบบจะต่อ LED เล็กๆ 3 ตัวกับขาเหล่านี้เพื่อเช็คเบื้องต้นว่ามีเอาต์พุตออกหรือไม่) ส่วนเอาต์พุต Tach out จะเป็นแรงดันที่สอดคล้องกับความเร็วรอบของมอเตอร์ ใช้วิธีการเฉลี่ยค่าที่ส่งออกผ่าน PWM โดยฟิลเตอร์ RC เช่นเดียวกับที่กระทำกับอินพุต ท้ายสุด สวิทซ์กดติดปล่อยดับ SW1 ใช้สำหรับสร้างการรบกวนแรงบิดให้กับมอเตอร์ (เหมือนกับว่าเราใช้มือจับที่เพลา) มีประโยชน์ในการทดสอบการขจัดการรบกวนโดยตัวควบคุมป้อนกลับ

บอร์ดต้นแบบได้ถูกทดสอบ (รูปที่ 4) และหลังจากแก้ไขบั๊กแล้วก็ทำงานได้ตามต้องการ ดูวีดีโอการทดสอบเบื้องต้นได้ที่ด้านล่างของบทความนี้

 
รูปที่ 4 ทดสอบการทำงานของ emotor

ถึงแม้จะเป็นโปรเจ็คง่ายๆ แต่emotor ก็เป็นแบบฝึกหัดที่ดีในการโปรแกรมโมดูล ADC, timer, และ PWM ใน dsPIC ซึ่งหลักการสามารถนำไปใช้กับผลิตภัณฑ์ไมโครคอนโทรลเลอร์อื่นๆ ได้ ซอร์สโค้ดภาษา C โดยสมบูรณ์มีให้ในหน้าเพจนี้ ผู้สนใจสามารถนำไปสร้างเองได้ทันที เนื่องจากโค้ดไม่มีอะไรซับซ้อน ดังนั้นจะอธิบายเพียงโครงสร้างโดยรวมเท่านั้น

โปรแกรม emotor.c เป็นแบบหลายเทรดที่ประกอบด้วย: main และไทเมอร์รูทีน TSR1 และ TSR2 หลังจากที่ตั้งค่าเริ่มต้นของตัวแปรและโมดูลทั้งหมดแล้ว โปรแกรมจะเข้าสู่ลูปที่วนรอบตลอดกาล เรามักเรียกลูปนี้ว่า เทรดหลัก (main thread) หน้าที่ของเทรดหลักคืออ่านค่าคำสั่งความเร็ว (แรงดันไฟฟ้าที่ขา RB0) ผ่านโมดูล ADC0 และหาค่าเฉลี่ยร่วมกับ 3 ค่าเดิมก่อนหน้าเพื่อลดทอนสัญญาณรบกวนความถี่สูง หลังจากนั้นทำการคำนวนค่ามุมที่เปลี่ยนแปลง minc ที่สัมพันธ์กับคำสั่งความเร็ว เพื่อให้เทรด TSR1 อ่านค่าและอัพเดทมุมของมอเตอร์ นอกจากนั้นยังคำนวนตัวแปร enloop ที่ใช้กำหนดว่าสัญญาณเอนโคเดอร์ A,B ต้องเปลี่ยนแปลงค่าเมื่อใด ก่อนที่จะคำนวนค่าเหล่านี้ เทรดหลักจะตรวจสอบก่อนว่ามีการกดสวิทซ์ SW1 หรือไม่ ถ้า SW1 ถูกกด ค่าความเร็วจะถูกลดลงเหลือ 0.6 ของค่าเดิม หน้าที่สุดท้ายของเทรดหลักคือส่งค่าความเร็วให้กับโมดูล PWM ซึ่งทำหน้าที่เหมือนสัญญาณจาก tachometer

เทรด TSR1 (ไทเมอร์ 1) จะทำหน้าที่จัดการการหมุนของมอเตอร์ กล่าวได้ว่าเทรดนี้จะต้องการทรัพยากร CPU มากสุดเพราะถูกโปรแกรมให้ทำงานทุกคาบเวลา 100 ไมโครวินาที ด้วยอัตราการทำงานที่เร็วมากนี้ทำให้ไม่สามารถใส่คำสั่งหรือคำนวนที่ซับซ้อนมากเกินไป เพราะเทรดอาจทำงานไม่เสร็จทันเวลา ดังนั้นเทรดนี้จะทำหน้าที่เพียงอัพเดทตัวแปรมุมของมอเตอร์ mangleและสร้างสัญญาณเอนโคเดอร์ A,B ที่เปลี่ยนสถานะตามเงื่อนไขเวลาที่กำหนดโดยตัวแปร encloop (คำนวนในเทรดหลัก) และทิศทางกำหนดโดยค่า DIR ที่อ่านโดยตรงจากขา RB1 เราจะไม่ใส่โค้ดการอัพเดทสถานะของ LEDs ลงในเทรดนี้เพราะมีอัตราที่เร็วเกินความจำเป็น (สายตาของมนุษย์ไม่สามารถจับการเปลี่ยนแปลงที่เกิดขึ้นด้วยอัตรา 10 KHz) นอกจากนั้นยังทำให้จำนวนคำสั่งมากเกินไปสำหรับ TSR1 ดังนั้นจะปล่อยให้เป็นหน้าที่ของไทเมอร์ 2

เทรด TSR2 ถูกโปรแกรมให้ทำงานทุกคาบเวลา 10 มิลลิวินาที ทำหน้าที่เปลี่ยนสถานะของ LED 6 ตัว ตามตำแหน่งองศาของมอเตอร์ และยังทำหน้าที่สร้างอินเด็กซ์ พัลซ์ Z

อ่านเพิ่มเติมเกี่ยวกับ โครงสร้างของโปรแกรมหลายเทรดโดยใช้ไทเมอร์อินเตอร์รัพท์.

เก็บตกเกร็ดในการออกแบบและโปรแกรม emotor

  1. dsPIC30F2010 เป็นตัวประมวลผลที่ไม่มีสมรรถนะสูงมาก โดยเฉพาะเมื่อใช้คล็อกภายใน 7.37 MHz โดยไม่มีการคูณด้วย PLL นอกจากนั้นยังไม่มีหน่วย FP (floating point) ดังนั้นถ้าใช้การคำนวนแบบ floating point กับตัวแปร float หรือ double ตัวประมวลผลจะต้องอาศัยไลบรารี่เพิ่มเติม ทำให้โค้ดมีขนาดใหญ่และใช้เวลาการคำนวนมากขึ้น เนื่องจาก emotor ไม่ต้องการความละเอียดในการคำนวนสูง จึงเลือกใช้การคำนวนแบบใช้เลขจำนวนเต็ม (integer arithmetic) ทำให้ช่วยลดจำนวนคำสั่ง (เมื่อคอมไพเลอร์แปลงเป็นภาษาเครื่อง) และเวลาในการคำนวน โดยเฉพาะคำสั่งในเทรด TSR1 ที่จะต้องสั้นและเร็วที่สุด ดังนั้นเมื่อดูจากโปรแกรม ผู้อ่านอาจงงกับหน่วยที่ใช้บ้าง เช่นองศาของมอเตอร์จะถูกคูณด้วย 100 เพื่อให้มีความละเอียดเพิ่มขึ้น (แต่ไม่มีหน่วยเรียกที่เหมาะสมเพราะองศาไม่ใช่ SI unit จึงไม่สามารถเรียกว่า 10 มิลลิองศา ผู้พัฒนาที่เคร่งครัดกับการกำหนดหน่วยอาจเปลี่ยนเป็นใช้หน่วยเรเดียน (radian) ซึ่งเป็น SI และซอยลงเป็นไมโครเรเดียน เป็นต้น) แต่บางทีการคำนวนโดยเลขจำนวนเต็มอาจสร้างปัญหาได้ ตัวอย่างเช่น ลองสังเกตโค้ดในเทรดหลักนี้
    minctmp = (unsigned int)3.6*speedcmd; // motor angle increment
    if (minctmp==0) minctmp=1; // avoid divide by 0
    enloop = (unsigned int)encstep/minctmp;
    ตัวแปร minctmp เป็นแบบ unsigned int สิ่งที่เกิดขึ้นในการคำนวนบรรทัดแรก คือเมื่อคำสั่งความเร็วมีค่าน้อยมาก ค่าของ minctmp จะเป็นศูนย์ ดังนั้นถ้าคำนวนบรรทัดที่ 3 เลยจะทำให้ CPU หยุดทำงานเนื่องจากเกิดการหารด้วยศูนย์ ทางแก้แบบง่ายๆ ที่ใช้คือเพิ่มบรรทัดที่ 2 เข้าไป ทำให้ตัวแปร minctmp มีค่าน้อยสุดเท่ากับหนึ่ง ผลคือ emotorจะไม่มีวันหยุดนิ่งได้ในระบบลูปเปิด แม้ให้ค่าคำสั่งความเร็วเป็นศูนย์ แต่จะมีการหมุนอย่างช้าๆ อย่างไรก็ตามปรากฏการณ์นี้สามารถเกิดขึ้นได้ในมอเตอร์จริงเช่นกัน และกลับเป็นสิ่งที่ทำให้การออกแบบตัวควบคุมป้อนกลับเพื่อรักษาตำแหน่งมีความสนุกมากขึ้น เพราะ emotor จะหยุดนิ่งต่อเมื่อระบบถูกปิดเท่านั้น
  2. เป็นที่รู้กันดีว่าในระบบหลายเทรด ผู้พัฒนาต้องระวังปัญหาที่เรียกกันว่า read-modify-write ในโปรแกรม emotor ของเราก็เช่นกัน เนื่องจากเทรด TSR1 จะถูกเรียกทำงานด้วยความถี่สูงมาก และมีค่าลำดับความสำคัญ (interrupt priority) สูงกว่าเทรดหลัก (CPU priority) ขณะที่ตัวแปร minc และ encnloop ที่เป็นแบบโกลบอล (global) จะถูกอัพเดทโดยเทรดหลัก ดังนั้นการอัพเดทตัวแปรเหล่านี้จำเป็นต้องเป็นแบบอตอมิค (atomic) คือจะต้องไม่มีการอินเตอร์รัพท์ใดๆ เกิดขึ้นจนกว่าจะเขียนข้อมูลเสร็จสิ้น มีหลายวิธีที่สามารถทำได้ วิธีการง่ายๆ ที่ใช้คือเพิ่มค่าลำดับความสำคัญของ CPU ให้สูงสุด (7) ก่อนเริ่มเขียน และลดค่าลงตามเดิม (0) หลังเสร็จ สามารถใช้มาโครดังนี้
    SET_CPU_IPL(7);
       minc = minctmp;
       encnloop = enloop;
    SET_CPU_IPL(0);
    ส่วนวิกฤตนี้จะต้องดำเนินการให้เร็วที่สุดเท่าที่จะทำได้ คือทำการเขียนตัวแปรเพียงอย่างเดียว สำหรับการคำนวนใดๆ ให้กระทำภายนอก มิฉะนั้นแล้วจะมีผลกระทบต่อสมรรถนะโดยรวมเนื่องจากเทรดทั้งหมดจะถูกบล็อคในช่วงเวลานี้

ข้อแนะนำในการปรับปรุง emotor

  1. อิมพลิเมนต์การรบกวนแรงบิดแบบ 2 ขั้น คือเมื่อผู้ใช้เริ่มกด SW1 คำสั่งความเร็วจะลดลงเหลือ 0.6 ของค่าเดิม แต่หากกด SW1 ค้างไว้ช่วงเวลาหนึ่ง เช่น 3 วินาที การรบกวนจะมีค่ามากขึ้น คือทำให้ความเร็วลดลงเหลือเพียง 0.3 ของค่าเดิม
  2. เพิ่มตัวแปรหน่วงเวลามอเตอร์ที่ปรับค่าได้จากภายนอกโดยใช้ VR หรือจัมพ์เปอร์

ตัวอย่างปฏิบัติการสาขาระบบควบคุม

ในส่วนนี้จะยกตัวอย่างการใช้ emotor ในการทดลองด้านระบบควบคุม แนะนำให้เพิ่มฟังก์ชันสื่อสารสำหรับเก็บข้อมูลเพื่อการวิเคราะห์ เช่น ผลตอบสนองขั้นบันได
  1. ต่อ emotorเข้ากับตัวประมวลผลอีกตัวหนึ่งที่อิมพลิเมนต์ตัวควบคุม PID ปรับค่าพารามิเตอร์ ปิดลูปป้อนกลับและสั่งให้ความเร็วถูกคุมค่าอยู่ประมาณครึ่งหนึ่งของความเร็วสูงสุด (LED จะหมุนรอบด้วยความเร็วประมาณ 5 รอบต่อวินาที) ทดลองกดสวิทซ์ SW1 เพื่อรบกวนแรงบิด emotorจะต้องยังคงหมุนด้วยความเร็วรอบเท่าเดิม
  2. อิมพลิเมนต์ระบบควบคุมตำแหน่งที่ทำให้ emotorหยุดค้างที่ตำแหน่งที่กำหนด
  3. ทดลองใช้การหาเอกลักษณ์ระบบวิธีต่างๆ เช่น กำลังสองน้อยสุด เพื่อหาโมเดลคณิตศาสตร์ของ emotor วิเคราะห์โมเดลที่ได้
  4. ใช้โมเดลที่หาได้เพื่อออกแบบตัวควบคุมขั้นสูงโดยวิธีที่ท่านเลือก เช่น การจัดสันฐานวงรอบ QFT, LQG/LTR, $H_\infty$ เป็นต้น

วีดีโอ

วีดีโอด้านล่างนี้แสดงการทดสอบemotor ขั้นพื้นฐาน (แบบลูปเปิด โดยใช้ VR และจัมเปอร์เป็นตัวป้อนคำสั่งความเร็วและทิศทาง).

 
ดาวน์โหลดซอร์ส: emotor.c

สร้างโปรเจ็คใหม่ใน MPLAB หรือ MPLABX และเพิ่มซอร์สไฟล์นี้เข้ากับโปรเจ็ค คอมไพล์และโหลดเข้าตัว dsPIC

No comments:

Post a Comment