본문 바로가기

VERILOG

Rotary Encoder(RSI 503) 및 MAX33076E(수신기) VERILOG 동작

 

ENCODER는 전기모터나 엔진의 회전각도 또는 회전속도를 측정할 때 사용되는 대표적인 센서입니다.

 

회전할 때 마다 펄스가 발생합니다.

 

즉, 펄스 수를 셈으로써 축의 각도를 검출할 수 있습니다.

 

앱솔루트식 로터리 인코더는 몇 가닥의 신호선에 의하여 축의 절대위치를 검출할 수 있습니다.

 

 

RSI503 엔코더를 동작하여 VIVADO를 통해 회전하는 펄스마다 카운트를 세어주는 테스트를 해보려고 합니다.

 

ENCODER의 동작을 이해해보겠습니다.

 

 

RSI503은 1024PPR(Perse per revolution)

"1ppr"은 "1 pulse per revolution"의 약자입니다. 이는 회전하는 기계 또는 장치에서 한 회전당 발생하는 펄스의 수를 나타냅니다.

"4체배"는 회전당 펄스의 수를 기준으로 펄스의 수를 네 배로 증가시키는 방식을 의미합니다. 따라서 1ppr의 경우에는 한 회전당 하나의 펄스가 생성되지만, 4체배인 경우에는 한 회전당 네 개의 펄스가 생성됩니다.

이것은 회전 각도의 해상도를 높이는 방법 중 하나로 사용됩니다. 4체배 인코더는 같은 회전량을 측정할 때 더 많은 펄스를 생성하여 더 정밀한 회전 위치를 측정할 수 있습니다.

 

 

다음과 같이 1,2,3,4 phase가 하나의 ppr 이 되어 1024*4 = 4096pulse

위의 동작을 보면 A가 0,0,1,1 이 될 때 B는 1,0,0,1이 됩니다. 

같은 타이밍 에서

phase 1에서 A=0 B=0

phase 2에서 A=0 B=1

phase 3에서 A=1 B=1

phase 4에서 A=1 B=0

이렇게 4번 바뀜을 확인할 수 있습니다.

 

엔코더는 A,B상, A,B,Z 상 이런식으로 다양한 유형이 있는데 RSI503은 A,B,Z상이 있습니다.

Z는 HIGH가 되면 리셋이 된다고 보시면 됩니다. 

한바퀴가 돌면 카운트 값은 리셋이 됩니다.

 

 

엔코더는 위의 그림과 같이 2방향으로 CW 시계방향, CCW 반시계반향으로 돌 수 있고

저는 이를 고려하여 시계방향으로 돌 때는 +카운트, 반시계방향으로 돌 때는 -카운트를 해주려고 합니다.

 

이제 이 ENCODER의 각 신호를 연결하고 수신해줄 수신기를 알아보겠습니다.

 

 

수신기의 보드 전면 사진입니다.

 

수신기는 위의 그림과 같이 차동 신호를 입력으로 받아 밑의 그림과 같이 Y1, Y2, Y3등 단일 신호로 출력하여줍니다.

 

엔코더의 각 선

S00, S00_N 은 A

S90, S90_N 은 B

Sref, Sref_N 은 Z 로써

 

수신기의 J1, J2, J3에 각각 연결하여 줍니다.

 

 

그리고 제가 쓰는 RSI503은 인가전압 범위가 9V~30V 로써 SPMS로 15.6V를 연결하여 공급해줬습니다.

 

 

MAX33076E 의 핀맵입니다. 

 

회로 연결할 때 MAX33076E칩에 VCC를 찍어봤더니 전원이 들어오지않아

 

위의 커넥터 VCC에는 연결을 했는데

 

 

위의 JU1을  3.3V 와 VCC를 연결하여 1,4 연결을 해주니 전원이 들어갑니다.

 

 

각 핀에 전압이 들어가는지 확인하고 각 A, B, Z의 엔코더 회전 시 동작파형을 찍어봅니다.

 

 

A상을 오실로스코프로 SINGLE SEQ 를 눌러서 REDAY 상태에서 한번 더 눌러서 트리거를 잡아줍니다. 

회전을 돌리는 속도에 따라 주기의 차이가 있습니다.

 

 

A상이 CH3이고 B상이 CH4입니다.

CW 시계방향으로 돌렸을 때 A상이 먼저 1이 들어옴을 확인할 수 있습니다.

 

 

A상이 CH3이고 B상이 CH4입니다.

CCW 반시계방향으로 돌렸을 때 B상이 먼저 1이 들어옴을 확인할 수 있습니다.

 

 

 

Z상은 1024PPR당 한번 동작하므로 파형을 잡아내기가 어려웠습니다.

트리거로는 잡히지않고 파형이 잡혔을 때 STOP을 눌러줬습니다.

 

동작이 잘 됨을 확인했으니 VIVADO로 테스트를 진행합니다.

 

module encoder(
input        CLK_125_P,                   // 125 MHz clock positive input
input        CLK_125_N,                   // 125 MHz clock negative input 
input        A, B, Z,
input        rst_n
);

wire clk;                                       // Clock signal
// IBUFDS: Differential Input Buffer
// 7 Series
// Xilinx HDL Language Template, version 2017.4
IBUFDS #(
.DIFF_TERM("FALSE"),                           // Differential Termination
.IBUF_LOW_PWR("TRUE"),                          // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("DEFAULT")                          // Specify the input I/O standard
) IBUFDS_inst (
.O(clk),                                        // Buffer output    "clk" in your case
.I(CLK_125_P),                                  // Diff_p buffer input (connect directly to top-level port)   "clk_p" in your case
.IB(CLK_125_N)                                  // Diff_n buffer input (connect directly to top-level port)  "clk_n" in your case
);
// End of IBUFDS_inst instantiation

(* MARK_DEBUG = "TRUE" *)    reg direction;
(* MARK_DEBUG = "TRUE" *)    reg [20:0] counter;
    
reg [2:0] A_mem, B_mem;
    reg Z_OX;
(* MARK_DEBUG = "TRUE" *)  wire counter_en = A_mem[2] ^ A_mem[1] ^ B_mem[2] ^ B_mem[1];
wire dir = A_mem[1] ^ B_mem[2];

always @(posedge clk)
begin
A_mem <= {A_mem[1:0], A}; // shift left and save new value
B_mem <= {B_mem[1:0], B};
Z_OX <= Z;

if(counter_en) begin
counter <= dir ? (counter + 1) : (counter - 1); // if(direction == 1) +1 else -1
direction <= dir;
end
        else if(Z_OX) begin
            counter <= 0;
        end
end

endmodule

 

동작은 A의 0,1 과 B의 0,1을 EX-OR 로 묶어줘서 카운터가 가능하게끔 조건을 만들어주고

A의 첫번째와 B의 두번째가 EX-OR 둘 중에 하나가 1이 들어오면 카운터가 1이 증가하고

1이 들어오지않으면 -1이 되게끔 코드를 짜줬습니다.

 

 

1바퀴당 Count +4096 리셋

(1024PPR)*4 정방향

 

 

1바퀴당 Count -4096 리셋

(1024PPR)*4 역방향

 

4096의 카운터는 1024PPR에 4체배로 1바퀴당 4096이 올라가고 Z가 동작하여 리셋이 되는 것을 확인할 수 있었습니다.