Rotary Encoder เป็นอุปกรณ์ที่สามารถบอกตำแหน่งหรือความเร็วในการเคลื่อนที่เชิงมุม ส่วนมากภายในจะใช้เซนเซอร์แบบแสงซึ่งจะให้สัญญาณออกมาในรูปแบบ Pulse ที่สามารถนำมาประมวลผลได้ โดย Rotary Encoder สามารถแบ่งออกได้เป็น Absolute Encoder และ Incremental Encoder โดยในบทความนี้จะกล่าวถึงเฉพาะ Incremental Encoder เท่านั้น
Incremental Rotary Encoder
Incremental Encoder นั้นจะมีสัญญาณเอาต์พุตเป็น Pulse ต่อเนื่องเรื่อยๆ ถึงแม้ว่าจะหมุนครบรอบไปแล้วก็ตาม แต่ว่าไม่สามารถที่จะบอกทิศทางการหมุนได้ ดังนั้นแล้ว Incremental Encoder ส่วนมากจึงมีสัญญาณเอาต์พุตอีกช่องที่มีเฟสแตกต่างกัน ทำให้สามารถบอกทิศทางการหมุนได้ เรียกว่า Quadrature Encoder
 |
รูปที่ 1. Quadrature Encoder block diagram |
รูปที่ 1 เป็นบล๊อคไดอะแกรมของ Quadrature Encoder ซึ่งประกอบไปด้วยจานล้อหมุนที่มีวงรอบด้านนอกเป็นช่องๆสลับกับส่วนทึบหมุนไปมา ซึ่งจะทำให้ฝั่ง Detector Section ที่มี Photo Diodes ที่ถูกแบ่งออกเป็น 2 ส่วนคือ A กับ B เกิดสัญญาณที่มีเฟสแตกต่างกัน โดยสัญญาณเอาต์พุตที่ได้เป็นไปดังภาพที่ 2 ซึ่งจะทำให้สามารถรู้ได้ว่าหมุนไปทิศทางไหน ยกตัวอย่างเช่น ถ้าเฟส A นำเฟส B จะหมุนตามเข็มนาฬิกา หรือถ้าเฟส B นำเฟส A จะเป็นการหมุนทวนเข็มนาฬิกา
 |
รูปที่ 2. สัญญาณเอาต์พุตของ Quadrature Encoder |
นอกเหนือจากนั้น Encoder บางตัวจะมีสัญญาณช่องที่ 3 ด้วย เรียกว่า Zero หรือสัญญาณอ้างอิง (Reference signal) โดยเราสามารถที่จะนำสัญญาณนี้มาใช้เพื่อตรวจสอบตำแหน่งอ้างอิงได้ ซึ่งส่วนมากแล้วจะเรียกว่าเฟส Z
 |
รูปที่ 3. OMRON Rotary Encoder E6B2-CWZ6C |
Rotary Encoder ที่จะนำมาใช้งานและเขียนโปรแกรมในบทความนี้จะใช้ของ OMRON รุ่น E6B2-CWZ6C โดยมี Specification หลักๆ
- Powser Supply : 5-24VDC
- Resolution(P/R) : 1000 P/R
- Output phases : A,B และ Z
- Phase difference : 90°±45° between A and B (1/4 T ± 1/8 T)
- Output Configuration : NPN open-collector output
- Maximum permissible speed : 6000 r/min
สัญญาณเอาต์พุตของ OMRON Rotary Encoder E6B2-CWZ6C มีรูปแบบดังนี้
 |
รูปที่ 4. E6B2-CWZ6C Output signal |
 |
รูปที่ 5. E6B2-CWZ6C Wiring detail |
E6B2-CWZ6C จะมีสายเชื่อมต่อทั้งหมด 6 เส้น ตามรูปที่ 5. และวงจรเชื่อมต่อเป็นไปตามรูปที่ 6.
 |
รูปที่ 6. Encoder Interfacing with microcontroller |
Programing
บทความนี้ใช้ MCU เบอร์ PIC18F2550 ทำการเชื่อมต่อเฟส A,B และ Z กับ External Interrupt โดยให้ INT0 = A , INT1 = B และ INT2 = Z โดยทำการเขียนโปรแกรมอ่านค่าแบบที่เรียกว่า X4 Counting ซึ่งจะทำให้ใน 1 รอบ จะมีจำนวน pulse รวมทั้งสิ้น 4000 P/R จาก 1000 P/R และใช้เฟส Z เป็นสัญญาณอ้างอิงในการเริ่มนับและหยุดนับรวมถึงบอกจำนวนรอบ
 |
รูปที่ 7. X4 encoding (ni.com) |
มากกว่านั้นเราสามารถที่จะรู้ได้ว่า encoder หมุนไปทวนเข็มหรือตามเข็มนาฬิกา โดยการตรวจสอบการเปลี่ยนแปลงสถานะ โดยดูได้จาก State Diagram ข้างล่าง
 |
รูปที่ 8. X4 encoding state transition diagram |
และนี่คือ Interrupt Service Routine ของกระบวนการอ่าน Rotary Encoder ด้วยวิธี X4 encoding
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 86 87 88 89 90 91 92 | void interrupt() { /* External interrupt0 (Phase A) service routine */ if(INTCON.INT0IF == 1) { flag_detected = 1; // CW Detect rising edge for Phase A if((Phase_A == 1)&&(Phase_B == 0)&&(previous_state == 0x00)) { led = 1; previous_state = 0x10; intStep++; INTCON2.INTEDG0 = 0; //set interrupt0(A) edge to falling } // CW Detect falling edge for Phase A if((Phase_A == 0)&&(Phase_B == 1)&&(previous_state == 0x11)) { previous_state = 0x01; intStep++; INTCON2.INTEDG0 = 1; //set interrupt0(A) edge to rising } // CCW Detect rising edge for Phase A if((Phase_A == 1)&&(Phase_B == 1)&&(previous_state == 0x01)) { previous_state = 0x11; intStep--; INTCON2.INTEDG0 = 0; //set interrupt0(A) edge to falling }
// CCW Detect falling edge for Phase A if((Phase_A == 0)&&(Phase_B == 0)&&(previous_state == 0x10)) { previous_state = 0x00; intStep--; INTCON2.INTEDG0 = 1; //set interrupt0(A) edge to rising } INTCON.INT0IF = 0; // clear External interrupt 0 flag } /* External interrupt1 (Phase B) service routine */ if(INTCON3.INT1IF == 1) { flag_detected = 1; // CCW Detect rising edge for Phase B if((Phase_A == 0)&&(Phase_B == 1)&&(previous_state == 0x00)) { led = 0; previous_state = 0x01; intStep--; INTCON2.INTEDG1 = 0; //set interrupt1 (B) edge to falling }
// CCW Detect falling edge for Phase B if((Phase_A == 1)&&(Phase_B == 0)&&(previous_state == 0x11)) { previous_state = 0x10; intStep--; INTCON2.INTEDG1 = 1; //set interrupt1 (B) edge to rising }
// CW Detect falling edge for Phase B if((Phase_A == 1)&&(Phase_B == 1)&&(previous_state == 0x10)) { previous_state = 0x11; intStep++; INTCON2.INTEDG1 = 0; //set interrupt1 (B) edge to rising } // CW Detect rising edge for Phase B if((Phase_A == 0)&&(Phase_B == 0)&&(previous_state == 0x01)) { previous_state = 0x00; intStep++; INTCON2.INTEDG1 = 1; //set interrupt1 (B) edge to falling } INTCON3.INT1IF = 0; // clear External interrupt 1 flag } /* External interrupt2 (Phase Z) service routine */ if(INTCON3.INT2IF == 1) { INTCON3.INT2IF = 0; INTCON.INT0IE = 1; INTCON3.INT1IE = 1; flag_Z = 1; //flag1 = 1 is indicate that refence was detected intRound++; } }
|
วงจรสมบูรณ์ดูได้ในรูปที่ 9. ไมโครคอนโทรลเลอร์ใช้เบอร์ PIC18F2550 แบบ DIP 28 Pins ทำงานโดยใช้ Internal Oscillator สามารถใช้ไฟเลี้ยงได้จากทาง Connector , DC Jack หรือทาง USB PORT ได้ แสดงค่าที่อ่านได้ผ่าน RS232 ดังที่แสดงในรูปที่ 10. โดยสามารถ Reset ค่าทั้งหมดและเริ่มต้นนับใหม่ได้โดยการส่งคำสั่ง "Reset\r" ผ่านทาง RS232
 |
รูปที่ 9. Rotary Encoder postion x4 reading demonstration schematic (คลิ๊กที่รูปเพื่อ Download) |
 |
รูปที่ 10. แสดงค่าผ่านทาง RS232 (คลิ๊กที่รูปเพื่อขยาย) |
Download
Schematic ,
Source Code (ภาษา C ใช้ MikroC Pro for pic)
สัพพปาปัสสะ อกรณัง กุสลัสสูปสัมปทา สจิตตปริโยทปนัง#วิมุตติความหลุดพ้น
ReplyDelete