เจ้า MKR MotorCarrier เนี่ย เป็นบอร์ดเสริม (booster) อเนกประสงค์สำหรับเชื่อมต่อกับสเต็ปเปอร์มอเตอร์ แม้มันจะบอกว่าสนับสนุนสเต็ปเปอร์ แต่เราจะมาสำรวจกันจริงๆ ว่า 'อินเทอร์เฟซบูสเตอร์' ที่ต้องใช้เพื่อขับมอเตอร์ 28BYJ-48 แบบทั้ง unipolar และ bipolar ด้วยการควบคุม H-bridge แบบแม่นยำสุดๆ นั้นเป็นยังไง
พี่ใช้สเต็ปเปอร์มอเตอร์ยอดฮิตอย่าง 28BYJ-48 นี่แหละ หาง่ายโคตร และมักมาพร้อมกับบอร์ดขับ (driver) ที่ใช้ชิป ULN2003 แต่บอร์ดขับนั้นเราจะไม่ใช้ที่นี่นะ ตัว 28BYJ-48 เป็นมอเตอร์แบบ 2-phase, unipolar ครับ เฟสหนึ่งอยู่ระหว่างสายสีน้ำเงินกับสีเหลือง ส่วนอีกเฟสอยู่ระหว่างสายสีม่วงกับสีส้ม แต่ละเฟสมีจุดร่วมตรงกลาง (common center tap) เป็นสายสีแดง ซึ่งแบ่งเฟสหนึ่งออกเป็นสองขดลวด

เดี๋ยวไปดูท้ายโปรเจกต์สำหรับการใช้งานมอเตอร์ตัวนี้ในโหมด bipolar นะ
ลำดับการกระตุ้น (activation sequence) ที่ใช้ขับสเต็ปเปอร์ที่นี่คือโหมดที่เรียกว่า half-step mode:

มันมีโหมดอื่นๆ เช่น wave-drive และ full-step-drive แต่วันนี้ไม่พูดถึงนะ มีตัวอย่างให้เห็นเยอะแยะ แต่ไม่จำเป็นสำหรับการอธิบายตอนนี้ ลำดับการกระตุ้นที่แสดงต้องตีความดังนี้: เมื่อจุดร่วมตรงกลาง (common center tap) ต่อกับ +VM การ "กระตุ้น" ก็คือการให้สัญญาณ LOW ไปที่ขดลวดที่ต้องการ หรือถ้าจุดร่วมตรงกลางต่อกับ GND การกระตุ้นต้องใช้สัญญาณ HIGH
วิศวกรรมการต่อสาย: ปัญหา +VM
การต่อจุดร่วมตรงกลาง (common center tap) ไปที่ +VM นี่ไม่ใช่เรื่องเล่นๆ นะ น้อง ในขณะที่เรามีจุดต่อ GND ให้ใช้ผ่านขั้วต่อสกรูทั้งสองด้านของบอร์ด MKR MotorCarrier แต่เราไม่มีอะไรแบบนั้นสำหรับ +VM เลย

เป็นไปได้ที่จะได้ +VM ผ่าน via (การเชื่อมต่อไฟฟ้าระหว่างชั้นของแผ่นวงจร) ตามที่เห็น แต่มันต้องการ **การบัดกรีที่แม่นยำมาก** ไม่แนะนำให้ต่อ +VM ตรงๆ จากแหล่งจ่ายไฟหรือจากแบตเตอรี่นะ เพราะถ้าทำแบบนั้น แม้จะปิดสวิตช์ไฟแล้ว เอาต์พุตของไดรเวอร์ยังคงมีไฟค้างอยู่ได้
แหล่งจ่ายไฟที่ต้องใช้ต้องจ่ายไฟได้อย่างน้อย 6.5V ตามสเปคของ MKR MotorCarrier ขดลวดแต่ละขดของหนึ่งเฟสวัดได้ 20Ω และสองขดลวดสามารถทำงานพร้อมกันได้ ดังนั้นแหล่งจ่ายต้องจ่ายกระแสได้ .65A
มีคำเตือนนิดนึง: สเต็ปเปอร์มอเตอร์ 28BYJ-48 ออกแบบมาสำหรับแรงดัน 5V แต่พี่ใช้กับแหล่งจ่าย 7V ก็ไม่เคยมีปัญหาอะไรเลย
มุมขั้น (step angle) ของมอเตอร์ในโหมด half step คือ 5.625° มันถูกทดเกียร์ลงด้วยอัตรา 63.68395 เท่า ดังนั้นที่เพลาข้อต่อ (shaft) จะเหลือ 0.088326807617932° หมายความว่าต้องใช้ 4075.7728 ขั้นเพื่อหมุนครบหนึ่งรอบ พูดให้ชัดๆ เลยนะ
กายวิภาคของ 28BYJ-48: Unipolar vs. Bipolar
บน MKR MotorCarrier มี 2 วิธีในการขับมอเตอร์ วิธีหนึ่งใช้ไดรเวอร์ MC33926 (เอาต์พุต M3±/M4±) และอีกวิธีใช้ไดรเวอร์ DRV8871 (เอาต์พุต M1±/M2±) ทางทฤษฎีมีวิธีที่สามผ่านตัวแปลระดับสัญญาณ (level translator) LSF0108 แต่อุปกรณ์ตัวนี้จ่ายกระแสไม่พอแน่นอน สำหรับสเต็ปเปอร์ 28BYJ-48
ไดรเวอร์ทั้งสองแบบมีโครงสร้างเอาต์พุตเป็น H-bridge ตามรูปด้านล่าง ซึ่งแสดงหนึ่งเฟสของสเต็ปเปอร์มอเตอร์ระหว่างเอาต์พุต OUT1 และ OUT2

ก่อนอื่นเรามาดูความเป็นไปได้ของการตั้งค่านี้กับ MC33926 กัน (Cn± หมายถึงจุดร่วมตรงกลาง ไม่ว่าจะต่อกับ +VM หรือ GND) MC33926 สามารถควบคุมได้โดยตรงจากโฮสต์ ผ่านพิน D2, D3, D4 และ D5 ไม่จำเป็นต้องใช้ SAMD11 บนตัว MotorCarrier เอง หรือไลบรารีเสริมใดๆ ทั้งสิ้น จัดไปวัยรุ่น!

ตามลำดับการกระตุ้นที่ให้มา ต้องหลีกเลี่ยงการเปิดทั้งสองด้านของเฟส (1&2) พร้อมกัน ดังนั้นในโหมด common+ ต้องหลีกเลี่ยงการให้อินพุตทั้งหมดเป็น 0 และในโหมด common- ต้องหลีกเลี่ยงการให้อินพุตทั้งหมดเป็น 1 นะน้อง
ทีนี้ปัญหามันอยู่ตรงนี้ไง ตอนที่ MKR 1010 WiFi เพิ่งบูตหรือรีเซ็ตใหม่ๆ I/O ของมันจะยังไม่นิยามค่า ซึ่งก็ส่งผลให้อินพุตของ MC33926 ไม่นิยามตามไปด้วย ถ้าอินพุตของ MC33926 หลุด (disconnected) มันจะให้เอาต์พุตเป็น high (ไม่ได้แสดงในตาราง) ในกรณีของ Cn- นี่จะนำไปสู่สภาวะที่ไม่พึงประสงค์เลย จุดอ่อนของ CarrierBoard นี้แก้ได้โดยการต่อ ตัวต้านทานดึงลง (pull-down resistors) 10kΩ เข้ากับขา D2, D3, D4, D5 ของเฮดเดอร์บนบอร์ดโฮสต์จ้า
ถ้าไม่มีตัวดึงลงให้ต่อ ทางเลือกเดียวคือต้องต่อ common tap ไปที่ +VM อย่างน้อยก็เพื่อให้การทำงานเป็นไปตามเอกสารที่บอกไว้
นี่คือตารางความจริงสำหรับการตั้งค่าแบบใช้ DRV8871 อีกครั้ง Cn± หมายถึง common tap ต่อกับแรงดันมอเตอร์ +VM หรือ GND ส่วน Z หมายถึงสภาวะเอาต์พุตแบบไตรสเตต (tri-state)

เมื่อใช้ Cn+ ต้องหลีกเลี่ยงการตั้งค่าอินพุต IN1=1 และ IN2=1 พร้อมกัน ถ้ารับประกันได้ว่าหลีกเลี่ยงสภาวะนี้ได้ ทุกอย่างก็โอเค
เพื่อควบคุม DRV8871 เราต้องใช้ SAMD11 บนบอร์ดและไลบรารีที่เกี่ยวข้อง การจำลองค่า 0 กับ 1 ที่อินพุตทำได้โดยใช้คำสั่ง `setDuty()` ของไลบรารี โดยเฉพาะ `setDuty(0)`, `setDuty(100)` และ `setDuty(-100)` นั่นแหละ
การผสานซอฟต์แวร์และปรับให้เหมาะสม
โปรเจคนี้มีเส้นทางควบคุมสองทาง:
- Hardware Direct Steer: ใช้ ไดรเวอร์ MC33926 (เอาต์พุต M3/M4) วิธีนี้ให้บอร์ด MKR โฮสต์ควบคุมมอเตอร์ได้โดยตรงด้วยความหน่วงระดับต่ำกว่าไมโครวินาที ข้ามตัวประมวล SAMD11 บนบอร์ดไปเลยเพื่อความเร็วสูงสุด เร็วปรื๊ด!
- Library-Based Control: ใช้ ไดรเวอร์ DRV8871 (เอาต์พุต M1/M2) ผ่านตัวประมวล SAMD11 และคำสั่ง I2C วิธีนี้สะดวกดี แต่มีแล็กเพิ่มมานิดหน่อย (~9.8ms ต่อครั้ง) เหมาะกับงานที่ต้องการความแม่นยำในสภาวะคงที่มากกว่า จะเอาไปใช้กับหุ่นยนต์ความเร็วสูงอาจจะช้าไปสักนิด
มีปัญหาฟิร์มแวร์บางอย่างเมื่อใช้ SAMD11 บนบอร์ด CarrierBoard นี่ไม่ได้เชื่อมต่อกับปุ่มรีเซ็ตมือแบบที่ MKR 1010 WiFi มีนะ พี่เคยเจอโปรแกรมค้างเป็นระยะๆ ตอนใช้ปุ่มรีเซ็ตมือ คาดว่าเพราะตอนที่ MKR 1010 WiFi กำลังรีบูต ฟิร์มแวร์ของ SAMD11 โดยเฉพาะการสื่อสาร I2C มันยังคงทำงานต่ออยู่ สรุปจากที่ลองมา พวกฟังก์ชัน 'setter' อย่าง `setDuty()` ไม่เคยทำให้ค้าง แต่พวก 'getter' อย่าง `getRaw()` นี่แหละตัวดี
ตัวอย่างสเก็ตช์ค่อนข้างตรงไปตรงมา ยกเว้นบางจุดที่พี่จะแตะให้ฟังตรงนี้ ค่า `SCTR` (sector count) สามารถเป็นค่าใดก็ได้จนถึง 65535 การหมุนหนึ่งรอบเต็มนับได้ประมาณ 4047 สเตป ความถี่ที่แนะนำคือ 100Hz ซึ่งหมายความว่าเวลาแล็ก `LAG` จะเป็น 10000μs÷8steps=1250μs โดยยังไม่รวมโอเวอร์เฮดของซอฟต์แวร์ เมื่อวัดจริง โอเวอร์เฮดประมาณ ≈22μs เมื่อใช้ MC33926 และ ≈2038μs เมื่อใช้ไลบรารี (SAMD11/DRV8871) โดยการวัดทั้งสองแบบรวมการเรียก `micros()` และการส่งข้อมูลไป serial monitor (2E6 Baud) ไว้แล้ว ดังนั้นกับ `Stepper_on_M1_M2` ความเร็วสูงสุดจึงทำไม่ได้ และการดีเลย์ด้วย `LAG` ก็ไม่จำเป็นพูดกันตรงๆ
ในสเก็ตช์ทั้งสองอัน ต้องระวังเรื่องการคอมเมนต์/ยกเลิกคอมเมนต์บรรทัดที่ระบุไว้ให้ดี ขึ้นอยู่กับว่าจะเลือกโหมด common+ หรือ common- นะ
แทนที่จะใช้สเก็ตช์ `Stepper_on_M3_M4` ที่แสดงไว้ ก็สามารถใช้ Arduino Stepper library ได้ตามปกติ แต่เพราะต้องผ่านตัวกลางคือ SAMD11 บนบอร์ด การทำแบบนี้กับ DRV8871 (คือ M1±/M2±) จึงเป็นไปไม่ได้จ้า รู้ไว้ใช้ว่า!
ด้วยความสามารถของ DRV8871 ที่มีทั้งโหมด tri-state และ H-bridge ทำให้เราสามารถขับมอเตอร์ 28BYJ-48 แบบ bipolar stepper ได้ด้วยนะน้อง! ต่างกันยังไงเหรอ? ถ้าเป็นโหมด unipolar ในแต่ละช่วงเวลาจะจ่ายไฟให้แค่ส่วนหนึ่งของเฟส แต่ถ้าเป็น bipolar จะใช้ทั้งเฟส โดยสลับขั้ว GND/+VM ทั้งสองด้าน ซึ่งการสลับขั้วแบบนี้แหละที่ H-bridge ทำได้ แล้วขา center tap ร่วมล่ะ? ถ้าจ่ายไฟทั้งสองเฟสพร้อมกัน จุดร่วมนั้นจะมีแรงดันประมาณ ½VM ซึ่งโอเคอยู่ แต่ถ้าจ่ายแค่เฟสเดียว อีกเฟสก็ปล่อยให้เป็น tri-state ไป ก็ไม่มีปัญหา เอาโค้ด Stepper_on_M1_M2 ไปลองขับดูได้เลย โดยไม่ต้องต่อขา center tap ไม่ว่าจะเลือก common+ หรือ common- ก็ไม่ต่างกัน
ส่วน MC33926 นี่ไม่มี tri-state นะจ๊ะ ต้องตัดสายเชื่อมระหว่าง center taps ออกจากกันก่อนถึงจะใช้ไดรเวอร์ตัวนี้ได้ โชคดีที่มีตัวอย่างให้ดูว่าตัดยังไง หลังจากตัดแล้ว ก็สามารถขับ 28BYJ-48 แบบ bipolar ด้วย MC33926 ได้เลย เช่นกัน ไม่ว่าจะเลือก common+ หรือ common- ใน Stepper_on_M3_M4 ก็ไม่ต่าง
เวลาขับ stepper ไม่ว่าจะเป็น unipolar หรือ bipolar ผ่านไลบรารี (ซึ่งใช้ SAMD11 บนบอร์ด) มอเตอร์จะทำงานไม่ลื่นเท่ากับขับโดยตรงผ่าน MC33926 นะ หลังจากวัดเวลาดูแล้วพบว่า การเรียกฟังก์ชันอย่าง setDuty() ใช้เวลาประมาณ 9.8ms ส่วนใหญ่เป็นเพราะ latency ของบัส I2C นั่นหมายความว่าเวลาในการตั้งค่าภายในแต่ละสเตปนั้นเทียบได้และไม่ควรเพิกเฉยกับอัตราการทำงาน (100Hz) ของสเตปเปอร์ โค้ด Bipolar_on_M1_M2 จะช่วยปรับปรุงเวลาให้มีประสิทธิภาพมากขึ้นนิดหน่อย
ไม่ว่าน้องจะกำลังสร้างสไลด์สำหรับแล็บสุดเพอร์เฟกต์ หรือแขนกลแรงบิดสูง โปรเจกต์นี้ก็เป็นเหมือนคัมภีร์ที่ช่วยขยายขีดความสามารถของฮาร์ดแวร์ MKR Motor Carrier ของน้องได้เลยล่ะ! สู้งานนะน้อง!