Language/Verilog

Vivado : RGB LED, DC motor

짱도르딘 2024. 8. 1. 17:05
728x90

RGB LED

 

RGB를 나타내는 LED를 제어할 예정이다.

 

LED를 제어할 탑모듈의 코드는 아래와 같다. pwm_100 step 컨트롤러는 이전글을 참고하면 된다.

 

 

Vivado : PWM 제어

PWM LED의 밝기는 Duty rate에 따라 달라진다. LED 뿐만 아닌 모터의 경우에는 속도도 달라진다. PWM을 제어해 보기 위해 아래와 같은 코드를 구현해 보았다. 우선 Duty를 100단계로 설정하기 위하여 dut

jangdong.tistory.com

 

LED를 제어할 pwm의 컨트롤러 코드는 아래의 내용과 같다.

 

사용자가 임의로 주파수를 조절할 수 있도록 parameter를 먼저 선언하였다.

module pwm_Nstep_freq
#(
    parameter sys_clk_freq = 100_000_000, // System Clock = 100MHz
    parameter pwm_freq = 10_000, // PWM Frequency = 10000Hz
    parameter duty_step = 100, // 우리가 제어할 수 있는 Pulse 폭의 Step
    parameter temp = sys_clk_freq / duty_step / pwm_freq,
    parameter temp_half = temp / 2)
(
    input clk, reset_p,
    input [31:0] duty, // 100단계 만큼
    output pwm);
    
    integer cnt_sysclk;
    wire clk_freqXstep;
    
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)cnt_sysclk = 0;
        else begin
            if(cnt_sysclk >= temp-1) cnt_sysclk = 0;
            else cnt_sysclk = cnt_sysclk + 1;
        end    
    end
    
    assign clk_freqXstep = (cnt_sysclk < temp_half) ? 1 : 0;
    
    wire clk_freqXstep_nedge;
    edge_detector_n ed(
    .clk(clk), .reset_p(reset_p), .cp(clk_freqXstep),
    .n_edge(clk_freqXstep_nedge));
    
    integer cnt_duty;
    
    // 100분주
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)cnt_duty = 0;
        else if(clk_freqXstep_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; // 90보다 작을동안 1, 아니면 0
endmodule

 

아래의 코드는 LED를 구동시킬 탑모듈의 코드이다.

 

RGB를 각각 다른 clk_div로 선언하여 색깔마다의 변화 속도를 제어하였다.

module led_pwm_top(
    input clk, reset_p,
    output pwm, led_r, led_g, led_b);

    reg [31:0] clk_div;
    always @(posedge clk) clk_div = clk_div + 1;

    pwm_100step pwm_inst(.clk(clk), .reset_p(reset_p), .duty(clk_div[25:19]), .pwm(pwm));
     
     // RGB 제어
    pwm_Nstep_freq #(.duty_step(77)) pwm_r(.clk(clk), .reset_p(reset_p), .duty(clk_div[28:23]), .pwm(led_r));  
    pwm_Nstep_freq #(.duty_step(93)) pwm_g(.clk(clk), .reset_p(reset_p), .duty(clk_div[27:22]), .pwm(led_g));     
    pwm_Nstep_freq #(.duty_step(103)) pwm_b(.clk(clk), .reset_p(reset_p), .duty(clk_div[26:21]), .pwm(led_b));

endmodule

 

 

위 탑모듈의 코드를 실행시키면 아래와 같은 동작을한다.

 

 

 

 


DC motor control

이번에는 DC 모터 드라이버를 통해 DC 모터를 제어할 예정이다.

 

모터드라이버의 구조도는 아래의 사진과 같다.

 

 

 

 

모터 드라이브

 

전압은 ATmega의 전원을 통하여 인가하였고, 모터가 오른쪽일시 PWM Signal의 오른쪽 3개의 핀을, 왼쪽일시 왼쪽의 3개의 핀을 사용하면 된다.

 

모터 제어 탑모듈의 코드는 아래의 코드와 같다.

module dc_motor_pwm_top(
    input clk, reset_p,
    output motor_pwm);
    
    reg [31:0] clk_div;
    always @(posedge clk) clk_div = clk_div + 1;
    
    pwm_Nstep_freq #(
        .duty_step(4),
        .pwm_freq(100))
    pwm_motor(
    .clk(clk), 
    .reset_p(reset_p), 
    .duty(clk_div[31:30]),
    .pwm(motor_pwm));
    
endmodule

 

 

위 코드를 동작시키면 아래와 같이 모터가 동작하는 것을 확인할 수 있다.

 

728x90