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
- vivado
- test bench
- LED
- Recursion
- atmega 128a
- soc 설계
- stop watch
- prescaling
- Algorithm
- pwm
- i2c 통신
- hc-sr04
- ATMEGA128A
- Pspice
- ring counter
- behavioral modeling
- dataflow modeling
- java
- verilog
- structural modeling
- Linked List
- uart 통신
- half adder
- KEYPAD
- Edge Detector
- BASYS3
- DHT11
- D Flip Flop
- gpio
- FND
Archives
- Today
- Total
거북이처럼 천천히
Verilog RTL 설계(8월 2일 - 3, PWM을 통한 Servo-motor 제어 - 3) 본문
RTL Design/Verilog RTL 설계
Verilog RTL 설계(8월 2일 - 3, PWM을 통한 Servo-motor 제어 - 3)
유로 청년 2024. 8. 17. 23:461. 버튼을 통해 Servo-motor의 duty 를 컨트롤하기
- 4개의 버튼을 통해 서보 모터에 인가되는 PWM의 duty ratio를 컨트롤 할 수 있도록 설계하겠다.
- 4개의 버튼들은 다음과 같은 동작을 수행하게 된다.
- btn[0], btn_dir : duty ratio의 값을 up-counting할 것인지, down-counting할 것인지를 결정한다.
- btn[1], btn_min : duty ratio의 minimum value를 결정한다.
- btn[2], btn_max : duty ratio의 maximum value를 결정한다.
- btn[3], btn_reset : 설정된 duty ratio의 범위를 초기화한다.
1.1. 버튼을 통한 서보 모터 제어 알고리즘
- 서보 모터에 50Hz 주파수를 갖고, duty step이 200단계인 PWM을 인가한다.
- 이전 설계를 통해 해당 PWM을 전달할 경우, duty ratio가 5 ~ 25단계일 때 서보 모터가 -90도 ~ 90도 사이를 위치 조정할 수 있음을 확인할 수 있었기 때문에 이번 구현에서 duty 값은 5 ~ 25 범위를 갖고, up / down counting을 하게 된다.
- 4개의 버튼을 누르게 되면 다음과 동작하도록 설계하였다.
- btn_dir : 해당 버튼을 누르면 counting의 방향이 전환되게 된다.
- btn_min : 해당 버튼을 누르면 현재의 duty 값이 duty 값의 하한값이 된다.
- btn_max : 해당 버튼을 누르면 현재의 duty 값이 duty 값의 상한값이 된다.
- btn_reset : 해당 버튼을 누르면 duty 값의 하한, 상한값이 초기 상태인 5와 25로 돌아간다.
2. 버튼을 통해 Servo-motor의 duty 를 컨트롤 하기 (설계)
< Source, PWM Control Module >
// PWM Control Module
module servo_motor_cntr_3 #(
parameter sys_clk = 100_000_000,
parameter duty_step = 200,
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
- Servo-motor에 인가되는 PWM은 50Hz 주파수를 가지며, duty ratio를 200단계로 나누어 컨트롤 할 수 있다.
< Source, Top module of control survo-motor >
// Top module of Servo - motor
module top_module_of_servo_motor (
input clk, reset_p,
input [3:0] btn,
output [3:0] com,
output [7:0] seg_7,
output pwm );
// Get one cycle pulse of button.
wire btn_dir, btn_min, btn_max, btn_reset;
btn_cntr btn_cntr_dir (.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pedge(btn_dir));
btn_cntr btn_cntr_left (.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pedge(btn_min));
btn_cntr btn_cntr_right (.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pedge(btn_max));
btn_cntr btn_cntr_reset (.clk(clk), .reset_p(reset_p), .btn(btn[3]), .btn_pedge(btn_reset));
// 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));
// Select duty ratio of PWM.
reg [4:0] duty, min_duty, max_duty;
reg left_right;
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin
duty = 5; left_right = 0;
min_duty = 5; max_duty = 25;
end
else if(btn_reset) begin
min_duty = 5; max_duty = 25;
end
else if(btn_dir) left_right = ~left_right;
else if(btn_min) min_duty = duty;
else if(btn_max) max_duty = duty;
else if(clk_1sec) begin
if(!left_right) begin
if(duty >= max_duty) begin
duty = max_duty - 1;
left_right = ~left_right;
end
else duty = duty + 1;
end
else begin
if(duty <= min_duty) begin
duty = min_duty + 1;
left_right = ~left_right;
end
else duty = duty - 1;
end
end
end
// PWM Control module
servo_motor_cntr_3 #(.duty_step(200), .pwm_freq(50)) pwm_cntr
(.clk(clk), .reset_p(reset_p), .duty(duty), .pwm(pwm));
// Show FND to Basys 7-segment.
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 모듈와 D Flip-Flop을 통해 1msec delay time을 갖고, button 값을 읽게된다.
- duty의 하한 값을 5으로, 상한 값을 25으로 초기화한 뒤, 각 버튼의 one cycle pulse가 활성화 되면 해당 버튼의 역활에 맞게 현재의 duty 값을 duty 범위의 한계로 설정한다.
- btn_reset 버튼이 눌러지게 되면 세팅되었던 duty의 범위를 다시 5와 25로 초기화된다.
3. 구현 영상
- btn_min 버튼이 눌려지게 되면 현재 duty 값이 duty ratio의 하한 값으로 설정되며,
btn_max 버튼이 눌러지게 되면 현재 duty 값이 duty ratio의 상한 값으로 설정되게 된다. - btn_reset 버튼이 눌르게 되면 세팅 되었던 duty 값의 범위가 다시 초기화 된다.
'RTL Design > Verilog RTL 설계' 카테고리의 다른 글
Verilog RTL 설계(8월 12일 - 2, ADC Converter - 2) (0) | 2024.08.18 |
---|---|
Verilog RTL 설계(8월 12일 - 1, ADC Converter - 1) (0) | 2024.08.18 |
Verilog RTL 설계(8월 2일 - 2, PWM을 통한 Servo-motor 제어 - 2) (0) | 2024.08.16 |
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 |