Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Algorithm
- pwm
- half adder
- i2c 통신
- vivado
- soc 설계
- gpio
- D Flip Flop
- BASYS3
- LED
- dataflow modeling
- verilog
- test bench
- behavioral modeling
- atmega 128a
- DHT11
- uart 통신
- structural modeling
- Recursion
- Pspice
- hc-sr04
- ATMEGA128A
- Edge Detector
- prescaling
- ring counter
- KEYPAD
- Linked List
- stop watch
- FND
- java
Archives
- Today
- Total
거북이처럼 천천히
Verilog RTL 설계(8월 2일 - 2, PWM을 통한 Servo-motor 제어 - 2) 본문
RTL Design/Verilog RTL 설계
Verilog RTL 설계(8월 2일 - 2, PWM을 통한 Servo-motor 제어 - 2)
유로 청년 2024. 8. 16. 16:521. 시간에 따라 Servo-motor가 이동하도록 설계
- 이전 게시글까지 Servo-motor에 대해서 살펴보고, -90도, 0도, 90도에 위치시키도록 하기 위해서는 얼마만큼의 duty ratio가 필요한지를 실험을 통해 확인할 수 있었다.
- 이번 게시글에는 이를 토대로 servo-motor를 활용하도록 하겠다.
- Servo-motor에 대해서 궁금하거나 자세히 알고 싶다면 아래 게시글을 참고하길 바란다.
https://jbhdeve.tistory.com/306
Verilog RTL 설계(8월 2일 - 1, PWM을 통한 Servo-motor 제어 - 1)
1. Servo - motorServo는 "노예, 추종하다."를 의미하며, 라틴어의 servus에서 유래했다.Servo motor는 주로 기기를 시스템이 요구하는 위치로 이동하거나 특정 속도 및 토크로 가동시킬 때, 정확하게 제어
jbhdeve.tistory.com
- 이번에는 시간에 따라 Servo-motor를 -90도 ▶ 0도 ▶ 90도 ▶ 0도 ▶ -90도 ▶ .... 로 위치시키도록 설계하겠다.
- Servo-motor가 -90도, 0도, 90도에 위치시키기 위해서 이전 게시글을 통해 얻은 duty ratio을 활용하도록 하겠다.
< Source, PWM Control Module >
// PWM Control module
module pwm_cntr_1 #(
parameter sys_clk = 100_000_000,
parameter duty_step = 40,
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 );
// 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 temp_pwm, temp_pwm_nedge;
assign temp_pwm = (cnt_temp < temp_half) ? 0 : 1;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p),
.cp(temp_pwm), .n_edge(temp_pwm_nedge));
// duty_step 분주화
integer cnt_duty;
always @(posedge clk or posedge reset_p) begin
if(reset_p) cnt_duty = 0;
else if(temp_pwm_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
- 첫 번째 분주화 작업은 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_1(
input clk, reset_p,
output [3:0] com,
output [7:0] seg_7,
output pwm );
// Declare Parameter
reg up_down;
// 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] counter;
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin counter = 6; up_down = 1; end
else if(clk_1sec) begin
if(counter >= 25) begin counter = 24; up_down = 0; end
else if(counter <= 5) begin counter = 6; up_down = 1; end
else begin
if(up_down) counter = counter + 1;
else counter = counter - 1;
end
end
end
// PWM Control
pwm_cntr_1 #(.duty_step(200), .pwm_freq(50)) pwm_cntr_0 (.clk(clk), .reset_p(reset_p), .duty(counter), .pwm(pwm));
// Convert from binary to BCD.
wire [15:0] bcd_duty;
bin_to_dec bin_to_dec_0 (.bin(counter), .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 값은 5 ~ 25까지 값을 가지며, duty 값은 1초 One Cycle Pulse에 의해 1초마다 변화한다.
- up_down 변수에 의해 서보 모터에 전달되는 PWM의 Duty 값이 up counting이 되는가? down counting이 되는가? 가 결정된다.
- up_down 변수 값이 1이면 up-counting하며, up_down 변수 값이 0이면 down-counting한다.
< 구현 영상 >
- 50Hz 주파수를 갖는 PWM의 duty 값을 5 ~ 25까지 범위를 갖고, 서보 모터에 인가함으로서 1초마다 duty 값이 변화하면서 이에 따른 서보 모터는 위치 값이 변화함을 확인할 수 있다.
2. 버튼 값에 따라 Servo-motor가 이동하도록 설계
- 이번에는 3개의 버튼을 이용하여 각각의 버튼 값에 따라 서보 모터의 위치 값이 -90도, 0도, 90도에 위치시키도록 설계해보도록 하겠다.
- pwm_cntr 모듈은 그대로 사용하되, Top module만 변경하여 설계할 것이기 때문에 pwm_cntr 모듈에 대한 설명은 생략하도록 하겠다.
< Source, PWM Control >
// PWM Control
module pwm_cntr_2 # (
parameter sys_clk = 100_000_000,
parameter duty_step = 100,
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 );
// 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));
// duty_step 분주화
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
< Top module of servo motor >
// Top module of Servo-motor
module servo_motor_cntr_2(
input clk, reset_p,
input [2:0] btn,
output pwm,
output [3:0] com,
output [7:0] seg_7);
// Get one cycle pulse of button.
wire btn_mid, btn_left, btn_right;
btn_cntr btn_cntr_mid(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pedge(btn_mid));
btn_cntr btn_cntr_left(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pedge(btn_left));
btn_cntr btn_cntr_right(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pedge(btn_right));
// Select duty ratio.
reg [31:0] duty;
always @(posedge clk or posedge reset_p) begin
if(reset_p) duty = 5;
else begin
if(btn_mid) duty = 32'd15;
else if(btn_left) duty = 32'd5;
else if(btn_right) duty = 32'd25;
end
end
// PWM Control
pwm_cntr_2 #(.duty_step(200), .pwm_freq(50)) pwm_cntr (.clk(clk), .reset_p(reset_p), .duty(duty), .pwm(pwm));
// Convert from binary to BCD.
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
- button chattering 문제를 해결하기 위해 btn_cntr 모듈을 설계하였으며, btn_cntr 모듈내에서는 D-Flip Flop을 이용하여 button 값을 바로 입력 받는 것이 아닌 1msec delay time을 갖고, button 값을 받는다.
- 이를 통해 chattering 현상으로 인한 불안정한 버튼 값의 변화가 지나고 난 뒤, 안정된 버튼 값을 입력 받아 chattering 문제를 소프트웨어 적으로 해결하게 된다.
- 3개의 버튼을 통해 서보 모토의 위치를 3단계로 나누어 컨트롤 하게 된다.
< 구현 영상 >
'RTL Design > Verilog RTL 설계' 카테고리의 다른 글
Verilog RTL 설계(8월 12일 - 1, ADC Converter - 1) (0) | 2024.08.18 |
---|---|
Verilog RTL 설계(8월 2일 - 3, PWM을 통한 Servo-motor 제어 - 3) (0) | 2024.08.17 |
Verilog RTL 설계(8월 2일 - 1, PWM을 통한 Servo-motor 제어 - 1) (0) | 2024.08.16 |
Verilog RTL 설계(8월 1일 - 2, PWM을 통한 Motor 제어 - 1) (0) | 2024.08.12 |
Verilog RTL 설계(7월 23일 - 4, DHT11 구현 (3) ) (0) | 2024.08.10 |