BASYS3를 이용한 VERILOG 스마트팜 만들기(1)
프로젝트 제작 기간 | 도구 | 프로젝트 목표 |
5.17 ~ 5.24 | BOARD BASYS 3 / Xilinx Vivado | Smart Farm 구현 (온습도센서, 초음파센서, 조도센서, 서보모터, 모터, 모터드라이버 ) |
목차
- SmartFarm에 필요한 초음파 센서와 온습도 센서와 조도센서를 이용해 기본모드를 제작하였다.
- 온습도 센서를 기본모드로 설정하여 FND에 출력할 수 있게 설계 하였습니다.
- 온습도센서의 값을 이용하여 습도의 차이에 따라 환풍기를 설계할 수 있도록 PWM을 통해모터를 습도에 따라 다르게 구현하였습니다.
- 온도에 따라 높은온도의 경우 서보모터를 이용해 창문 개폐를 설계하였고, 낮은 온도의 경우 LED를 켜 히터역할을 설계하였습니다.
- 버튼을 누르면 모드가 바뀌며 조도센서와 초음파센서를 FND로 결과값을 확인 할 수 있게 설계하였습니다.
보드 연결
사용하는 보드인 BASYS3에 센서들의 값을 받아올 수 있게 연결해준다.
배선 연결
위의 보드 설명에 맞게 부품을 연결한다.
스마트팜 상태도
SMART FARM의 TOP MODULE
SmartFarn 의 TOP모듈을 구현하였다.
module smartfarm_top(
input clk, //클락
input [4:0] btn, // 총 사용하는 버튼
inout dht11_data,
input vauxp6,
input vauxn6,
input echo,
output [1:0] pwm_mode,
output trig,
output pwm_fan,
output pwm_window,
output [3:0] com_an,
output reg led,
output [7:0] seg_7 // 7-segment와 연결
);
wire dht_btn, light_btn, ultra_btn;
wire [7:0] humidity, temperature;
wire [3:0] light_com, ultra_com, dht_com;
wire [7:0] light_seg, ultra_seg, dht_seg;
reg [1:0] mode;
assign reset_n = ~btn[2]; // btn2번을 누르게 되면 반전되면서 모드가 바뀌게 된다.
clock_usec uCLK(.clk(clk), .reset_n(reset_n), .clk_usec(clk_usec));
clock_msec mCLK(.clk(clk), .clk_usec(clk_usec), .reset_n(reset_n), .clk_msec(clk_msec));
// debouncing
D_flip_flop_posedge_trig dff_dht(.D(btn[0]), .E(clk_msec), .Q(dht_btn));
D_flip_flop_posedge_trig dff_ultra(.D(btn[1]), .E(clk_msec), .Q(ultra_btn));
D_flip_flop_posedge_trig dff_light (.D(btn[3]), .E(clk_msec), .Q(light_btn));
//btn의 입력에따른 모드 2bit 설정
always @(posedge dht_btn or posedge ultra_btn or posedge light_btn or negedge reset_n)
begin
if(!reset_n) begin
mode = 2'b00;
end
else begin
if (dht_btn) mode = 2'b00;
else if(ultra_btn) mode = 2'b01;
else if (light_btn) mode = 2'b10;
end
end
//온습도 센서, 초음파 센서, 조도 센서 인스턴스
DHT11_top dht11( .clk(clk), .btn(btn[2]), .dht11_data(dht11_data), .humidity(humidity), .temperature(temperature), .com_an(dht_com), .seg_7(dht_seg) );
ultrasonic_top ultra_top(.clk(clk), .trig(trig), .echo(echo), .btn(btn[2]), .com_an(ultra_com), .seg_7(ultra_seg) );
ch6_ADC_top at( .vauxp6(vauxp6), .vauxn6(vauxn6), . clk(clk), .com_an(light_com), .seg_7(light_seg));
// 4 bit 의 mux 를 사용해야하는데, 한 번에 먹스를 사용하게 되면 13 bit가 되므로 한비트씩 끊어서 하기
mux_4_1 m0 (.D({0, light_com[0], ultra_com[0], dht_com[0]}), .S(mode), . F(com_an[0]));
mux_4_1 m1 (.D({0, light_com[1], ultra_com[1], dht_com[1]}), .S(mode), . F(com_an[1]));
mux_4_1 m2 (.D({0, light_com[2], ultra_com[2], dht_com[2]}), .S(mode), . F(com_an[2]));
mux_4_1 m3 (.D({0, light_com[3], ultra_com[3], dht_com[3]}), .S(mode), . F(com_an[3]));
mux_4_1 s0 (.D({0, light_seg[0], ultra_seg[0], dht_seg[0]}), .S(mode), . F(seg_7[0]));
mux_4_1 s1 (.D({0, light_seg[1], ultra_seg[1], dht_seg[1]}), .S(mode), . F(seg_7[1]));
mux_4_1 s2 (.D({0, light_seg[2], ultra_seg[2], dht_seg[2]}), .S(mode), . F(seg_7[2]));
mux_4_1 s3 (.D({0, light_seg[3], ultra_seg[3], dht_seg[3]}), .S(mode), . F(seg_7[3]));
mux_4_1 s4 (.D({0, light_seg[4], ultra_seg[4], dht_seg[4]}), .S(mode), . F(seg_7[4]));
mux_4_1 s5 (.D({0, light_seg[5], ultra_seg[5], dht_seg[5]}), .S(mode), . F(seg_7[5]));
mux_4_1 s6 (.D({0, light_seg[6], ultra_seg[6], dht_seg[6]}), .S(mode), . F(seg_7[6]));
mux_4_1 s7 (.D({0, light_seg[7], ultra_seg[7], dht_seg[7]}), .S(mode), . F(seg_7[7]));
//---------------------------------FAN---------------------------------//
// 습도가 60 이상이면 duty rate 40으로, 습도 70이상이면 duty rate 60, 습도 80이상이면 duty rate 90
reg [15:0] duty_temp_window, duty_temp_fan;
wire clk_160ns, clk_2560ns, clk_40us;
clock_divider cd_16( .clk(clk), .sel(3), .clk_out(clk_160ns)); // 160ns
clock_divider cd_256( .clk(clk_160ns), .sel(3), .clk_out(clk_2560ns)); // 160ns * 16 = 2560분주
clock_divider cd_4096( .clk(clk_2560ns), .sel(3), .clk_out(clk_40us));
pwm_top LUT(.clk(clk), .reset_btn(btn[2]), .duty_cycle(duty_temp_fan), .pwm(pwm_fan), .pwm_mode(pwm_mode));
always @(negedge reset_n or negedge clk_40us)
begin
if(!reset_n) begin
duty_temp_fan = 0;
end
else begin
if(humidity > 60) begin //duty 40%
duty_temp_fan = 16'd8000;
end
else if(humidity > 70) begin //duty 60%
duty_temp_fan = 16'd12000;
end
else if(humidity > 80) begin //duty 90%
duty_temp_fan = 16'd16000;
end
else begin
duty_temp_fan = 0;
end
end
end
//--------------------------------WINDOW--------------------------------//
//온도가 26 미만인 경우 역방향 회전, 27 초과인 경우는 정방향 회전
pwm_top LUT2(.clk(clk), .reset_btn(btn[2]), .duty_cycle(duty_temp_window), .pwm(pwm_window), .pwm_mode(pwm_mode));
always @(negedge reset_n or negedge clk_40us)
begin
if(!reset_n) begin
duty_temp_window = 16'd1900;
end
else begin
if(temperature > 27 ) begin //duty 40%
duty_temp_window = 16'd1100;
end
if (temperature < 26 )begin
duty_temp_window = 16'd1900;
end
end
end
//---------------------------------LIGHT---------------------------------//
// 온도가 25보다 작은 경우엔 led on, 그 외 led off
always @(negedge clk_40us ) begin
if(temperature < 25) led = 1'b1;
else led =1'b0;
end
endmodule
버튼구상
RTL회로
'VERILOG' 카테고리의 다른 글
[프로젝트]BASYS3를 이용한 VERILOG 다기능 시계 만들기(4) (0) | 2023.06.08 |
---|---|
[프로젝트]BASYS3를 이용한 VERILOG 다기능 시계 만들기(3) (0) | 2023.05.26 |
[프로젝트]BASYS3를 이용한 VERILOG 다기능 시계 만들기(2) (0) | 2023.05.26 |
[프로젝트]BASYS3를 이용한 VERILOG 다기능 시계 만들기(1) (0) | 2023.05.26 |
8:1멀티플렉서 (0) | 2023.04.19 |