การเชื่อมต่อและการเขียนโปรแกรมใช้งาน Rotary Encoder แบบ X4 Counting


     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

OMRON Rotary Encoder
รูปที่ 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

Interfacing
รูปที่ 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)


Comments

  1. สัพพปาปัสสะ อกรณัง กุสลัสสูปสัมปทา สจิตตปริโยทปนัง#วิมุตติความหลุดพ้น

    ReplyDelete

Post a Comment

Popular posts from this blog

MCS-51 Based Tachometer (เครื่องวัดความเร็วรอบ)

สร้าง Traindata สำหรับ OCR ด้วย Tesseract