RTL Design/Verilog RTL 설계
Verilog RTL 설계(8월 2일 - 1, PWM을 통한 Servo-motor 제어 - 1)
유로 청년
2024. 8. 16. 15:15
1. Servo - motor
- Servo는 "노예, 추종하다."를 의미하며, 라틴어의 servus에서 유래했다.
- Servo motor는 주로 기기를 시스템이 요구하는 위치로 이동하거나 특정 속도 및 토크로 가동시킬 때, 정확하게 제어할 수 있는 모터하고 할 수 있다.
- 따라서 Servo motor는 시스템에 의해 통제되며, 시스템의 명령에 의해 추종하며 동작하게 된다.
1.1. Servo - motor 의 특징
- 일반적인 모터인 경우, 모터의 방향과 PWM의 Duty ratio를 지정하면 원형으로 돌기만 하지만, 서보 모터는 제어 계측 회로에 의해 정확하게 움직일 수 있다.
- 따라서 서보 모터를 통해 원하는 방향 및 위치에 기기를 위치 시킬 수 있다는 특징을 갖는다.
2. SG90 Servo-motor
- 이번에 PWM을 통한 Servo-motor 제어에는 SG-90 서보 모터를 이용할 것이며, SG-90 서보 모터는 DC 모터이다.
- 아래그림은 50Hz PWM의 Duty ratio에 따른 SG-90 Servo-motor의 동작을 나타내고 있다.
- SG -90 Servo-motor는 아래와 같은 Duty ratio을 주어졌을 때, 다음과 같이 동작한다.
▶ -90도는 duty ratio가 ~1ms인 경우에 동작한다.
▶ 0도는 duty ratio가 1.5ms인 경우에 동작한다.
▶ 90도는 duty ratio가 1.5ms ~ 2ms인 경우에 동작한다. - 하지만, SG-90 서보 모터는 저렴한 서보 모터이기 때문에 Data sheet와 동일하게 동작하지 않고, 약간의 오차를 갖고, 동작한다.
- 따라서 Data sheet을 토대로 설계는 하되, 실험을 통해 "servo-motor의 위치를 각각 -90도, 0도, 90도로 만들기 위해서는 얼마만큼의 duty ratio를 가져야 하는가?"를 구해보도록 하겠다.
3. SG90 Servo-motor의 -90, 0, 90도로 위치 시키기 위한 duty ratio로 찾기.
- 실험을 통해 -90도, 0도, 90도로 위치시키기 위해서 얼마의 duty ratio가 필요한지를 알아보도록 하겠다.
- pwm_cntr 모듈을 통해 50Hz, duty ratio를 200단계로 나누어 컨트롤 할 수 있는 PWM을 생성하도록 하겠다.
< Source, PWM Control Module >
// PWM Control
module pwm_cntr_0 # (
parameter sys_clk = 100_000_000,
parameter duty_step = 80,
parameter pwm_freq = 50,
parameter temp = sys_clk / duty_step / pwm_freq,
parameter temp_half = temp / 2)
(
input clk, reset_p,
input [31:0] duty,
output pwm );
// pwm_freq 주파수를 갖는 pwm을 만들기 위해서
// System clock을 temp 분주화하여 sys_clk / temp 주파수를 갖는 pwm 생성
// temp 분주화
integer cnt_temp;
always @(posedge clk or posedge reset_p) begin
if(reset_p) cnt_temp = 0;
else begin
if(cnt_temp >= temp - 1) cnt_temp = 0;
else cnt_temp = cnt_temp + 1;
end
end
wire pwm_temp, pwm_temp_nedge;
assign pwm_temp = (cnt_temp < temp_half) ? 0 : 1;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p),
.cp(pwm_temp), .n_edge(pwm_temp_nedge));
// PWM의 Duty를 duty_step단계로 나누어 컨트롤하기 위해서
// sys_clk / temp 주파수를 갖는 pwm을 duty_step 분주화하여
// sys_clk / temp / duty_step == pwm_freq 주파수를 갖는 pwm을 생성
integer cnt_duty;
always @(posedge clk or posedge reset_p) begin
if(reset_p) cnt_duty = 0;
else if(pwm_temp_nedge) begin
if(cnt_duty >= duty_step - 1) cnt_duty = 0;
else cnt_duty = cnt_duty + 1;
end
end
assign pwm = (cnt_duty < duty) ? 1 : 0;
endmodule
- paramter를 통해 다양한 PWM 주파수을 갖고, Duty ratio을 단계별로 나누어 컨트롤 할 수 있도록 모듈을 설계하였다.
- 첫 번째 분주화 작업은 pwm_freq 주파수를 갖는 PWM을 생성하기 위한 작업이며, 이를 위해 10ns Clock Pulse를 temp 분주화 작업을 한다. 이를 통해 얻어진 PWM은 sys_clk / temp 주파수를 갖는 PWM이 된다.
- 두 번째 분주화 작업은 PWM의 Duty ratio을 duty_step 단계로 나누어 컨트롤하기 위한 작업이며, 이를 위해 첫 번째 분주화 작업을 통해 얻어진 PWM에서 duty_step 분주화 작업을 한다. 이를 통해 얻어진 PWM은 sys_clk / temp / duty_step == pwm_freq 주파수를 갖는 PWM이 된다.
< Source, Top Module of Servo-motor >
// Top module of servo-motor
module servo_motor_cntr_0(
input clk, reset_p,
output pwm,
output [3:0] com,
output [7:0] seg_7);
// Get 1sec one cycle pulse.
wire clk_1usec, clk_1msec, clk_1sec;
clk_div_100 clk_div_100_0 (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_1usec));
clk_div_1000 clk_div_1000_0 (.clk(clk), .reset_p(reset_p), .clk_source(clk_1usec),
.clk_div_1000(clk_1msec));
clk_div_1000 clk_div_1000_1 (.clk(clk), .reset_p(reset_p), .clk_source(clk_1msec),
.clk_div_1000_nedge(clk_1sec));
reg [7:0] duty;
always @(posedge clk or posedge reset_p) begin
if(reset_p) duty = 0;
else if(clk_1sec) begin
if(duty >= 199) duty = 0;
else duty = duty + 1;
end
end
// PWM Control
pwm_cntr_0 # (.duty_step(200), .pwm_freq(50)) pwm_cntr
(.clk(clk), .reset_p(reset_p), .duty(duty), .pwm(pwm));
// Convert from binary to BCD code
wire [15:0] bcd_duty;
bin_to_dec bin_to_dec_0 (.bin(duty), .bcd(bcd_duty));
// FND Control
fnd_cntr fnd_cntr_0 (.clk(clk), .reset_p(reset_p), .hex_value(bcd_duty), .com(com), .seg_7(seg_7));
endmodule
- PWM의 duty 값을 0부터 시작해서 200단계로 나누어 0 ~ 199까지 서보모터에 인가하여 -90도, 0도, 90도로 위치시키기 위해서 얼마의 duty ratio가 필요한지를 확인해보았다.
- 이를 위해 1초마다 활성화되는 One Cycle Pulse와 counter를 생성하여 duty 값으로 인가하였고, 현재 서보모터에 인가되는 duty를 확인하기 위해 BCD 코드로 변환한 후, FND로 출력하도록 설계하였다.
< 구동 영상 >
- 실험을 통해 50Hz, duty step이 50단계인 PWM을 서보 모터에 인가하였을 때, 다음과 같은 Duty 값일 때 원하는 각도로 위치한다는 것을 찾을 수 있었다.
▶ -90 도에 위치시키기 위해서는 duty = 5가 필요하다.
▶ 0 도에 위치시키기 위해서는 duty = 15가 필요하다.
▶ 90 도에 위치시키기 위해서는 duty = 25가 필요하다. - 이를 data sheet와 비교하면 다음과 같이 비교할 수 있다.
▶ data sheet에서 -90도를 위치시키기 위해서는 duty ratio가 1 이하 여야 하며, 이를 step of duty ratio를 200단계로 변환하면 10이하 여야 한다. 실험을 통해 확인 했듯이 duty = 5일 때, -90도에 위치했으며, data sheet와 일치함을 확인할 수 있다.
▶ data sheet에서 0도를 위치시키기 위해서는 duty ratio가 1.5 여야 하며, 이를 step of duty ratio를 200단계로 변환하면 15이하 여야 한다. 실험을 통해 확인 했듯이 duty = 15일 때, 0도에 위치했으며, data sheet와 일치함을 확인할 수 있다.
▶ data sheet에서 90도를 위치시키기 위해서는 duty ratio가 2이하 여야 하며, 이를 step of duty ratio를 200단계로 변환하면 15이상 20이하 여야 한다. 하지만, 실험을 통해 확인 했듯이 duty = 25일 때, 90도에 위치했기 때문에 이 부분에 대해서는 data sheet와 불일치임을 확인할 수 있었다.