? ? ? ? 閑來無事整個(gè)小車玩玩,設(shè)想的小車可以有藍(lán)牙模塊來控制模式切換,通過發(fā)送指令來更改相對(duì)應(yīng)的功能,當(dāng)避障的時(shí)候可以自動(dòng)規(guī)避障礙物,當(dāng)處于紅外循跡時(shí),可以跟隨規(guī)劃的軌跡前線,當(dāng)手動(dòng)遙控時(shí)可以控制前進(jìn)后退左右轉(zhuǎn)向停止等功能。
? ? ? ? 先介紹一下使用的紅外模塊,其上有四個(gè)管腳,vcc接電源,gnd接地,D0傳輸紅外線是否被吸收,A0傳輸模擬信號(hào)主要是不同距離輸出不同的電壓,但是此腳一般可以不接.
? ? ? ? 然后思路就是通過判斷D0傳過來的電平信號(hào)來判斷小車有沒有接觸到黑線,當(dāng)紅外線被吸收,也就是觸碰到黑線,D0會(huì)持續(xù)輸出高電平,直到它檢測(cè)到紅外線返回才會(huì)回歸低電平,基于對(duì)管腳傳回的電平檢測(cè),可以判斷是否接觸到黑線。
這部分代碼很好寫,可以參考如下代碼:
`timescale 1ns / 1ps
module red_line(
input sysclk ,///系統(tǒng)時(shí)鐘
input rst_n ,///復(fù)位
input [1:0] D0 ,///紅外探測(cè)模塊的電平輸入
output reg [3:0] car//輸出輪子控制
);
always @(posedge sysclk)
if(!rst_n)
car<=4'b1001;
else if( D0[0]==1 && D0[1]==1 )
car<=4'b0000;
else if(D0[0]==1) //左邊的紅外探測(cè)模塊
car<=4'b0101;
else if(D0[1]==1) //右邊的紅外探測(cè)模塊
car<=4'b1010;
else
car<=4'b1001; //保持狀態(tài)
endmodule
輸入系統(tǒng)時(shí)鐘,復(fù)位,紅外探測(cè)模塊的電平輸入,然后輸出小車輪子一個(gè)怎么走,就只有一個(gè)簡單的判斷語句。
然后是超聲波模塊,超聲波模塊的應(yīng)用,之前寫過了,這里就不再贅述。
超聲波模塊的距離還要輸入到一個(gè)避障模塊中,這個(gè)模塊只負(fù)責(zé)成立輸入的距離信息,判斷是否達(dá)到閾值。
`timescale 1ns / 1ps
module car_c(
input sysclk,
input rst_n,
input [13:0] distance,
output reg [3:0] car
);
always @(posedge sysclk)
if(!rst_n)
car<=4'b1001;
else if(distance>=15)
car<=4'b1001;
else if(distance<15)
car<=4'b1010 ;
else
car<=car;
//assign car=4'b1001; //1010 左轉(zhuǎn) 0101 右轉(zhuǎn) 1001 前進(jìn) 0110 后退
endmodule
然后是藍(lán)牙模塊,藍(lán)牙模塊包括兩部分,接收的rx,這里是基于藍(lán)牙模塊來說的,對(duì)藍(lán)牙模塊的接收和發(fā)送,我們需要通過藍(lán)牙模塊來進(jìn)行指令控制,輸入特定的十六進(jìn)制代碼輸出特定的控制信息:
這里我們定義了開發(fā)板的振動(dòng)頻率也就是一秒震動(dòng)多少次,然后是波特率,這里沒有涉及到其他的模塊,如果是不同的藍(lán)牙模塊之間通信,波特率要設(shè)置的一樣。
//串口讀取,可調(diào)整波特率,運(yùn)行頻率,本次設(shè)計(jì)不可以修改數(shù)據(jù)傳輸?shù)拈L度//
`timescale 1ns / 1ps
module uart_RX_car
#(
parameter SYSCLK = 50_000_000 ,//系統(tǒng)時(shí)鐘
parameter Baud = 9600 //波特率
)
(
input sysclk ,
input rst_n ,
input RX ,
output reg vaild ,//數(shù)據(jù)有效
output reg [7:0] Data
);
localparam CLK_DELAY = SYSCLK/Baud;
localparam CLK_MID = CLK_DELAY/2;
localparam IDLE=2'd0;//空閑狀態(tài),等待RX信號(hào)被拉低
localparam START=2'd1;//起始狀態(tài)
localparam DATA=2'd2;//數(shù)據(jù)接收
localparam STOP=2'd3;//停止?fàn)顟B(tài)
reg [1:0] cur_state;
reg [1:0] next_state;
reg [1:0] rx_flag = 2'b11;
reg [4:0] cnt_bit;//傳輸數(shù)據(jù)個(gè)數(shù)
reg [31:0] cnt;//記錄波特率,即記錄何時(shí)讓cnt_bit加1
******開始信號(hào)寄存*****
always@(posedge sysclk)
if(!rst_n)
rx_flag<=2'b11;
else
rx_flag<={rx_flag[0],RX};
******state1*****
always@(posedge sysclk)
if(!rst_n)
cur_state<=IDLE;
else
cur_state<=next_state;
******state2*****
always@(*) begin
next_state = IDLE;
case(cur_state)
IDLE:begin
if(rx_flag==2'b10)
next_state = START;
else
next_state = IDLE;
end
START:begin
if(cnt_bit==5'd1)
next_state = DATA;
else
next_state = START;
end
DATA:begin
if(cnt_bit==5'd9)
next_state = STOP;
else
next_state = DATA;
end
STOP:begin
if(cnt_bit==5'd9 && rx_flag == 2'b11)
next_state = IDLE;
else
next_state = STOP;
end
default:begin
next_state = IDLE;
end
endcase
end
******state3*****
always@(posedge sysclk)
if(!rst_n) begin
cnt_bit <= 5'd0;
cnt <= 32'd0;
Data <= 8'd0;
vaild <= 32'd0;
end
else
case(next_state)
IDLE:begin
cnt_bit <= 5'd0;
cnt <= 32'd0;
vaild <= 32'd0;
Data <= Data;//可以為0,也可以保持上一次的數(shù)據(jù)
end
START:begin
if(cnt >= CLK_DELAY-1)begin
cnt <= 32'd0;
cnt_bit <= cnt_bit + 32'd1;
end
else begin
cnt_bit <= cnt_bit;
cnt <= cnt + 32'd1;
end
Data <= Data;
vaild <= 0;
end
DATA:begin
if(cnt >= CLK_DELAY-1)begin
cnt <= 32'd0;
cnt_bit <= cnt_bit + 32'd1;
end
else begin
cnt_bit <= cnt_bit;
cnt <= cnt + 32'd1;
end
if(cnt == CLK_MID-1) //中點(diǎn)的時(shí)候進(jìn)行數(shù)據(jù)的采集,這樣能保證數(shù)據(jù)采集比較穩(wěn)定//
Data <= {RX,Data[7:1]};
else
Data <= Data;
vaild <= 0;
end
STOP:begin
if(cnt >= CLK_DELAY-1)begin
cnt <= 32'd0;
cnt_bit <= cnt_bit + 32'd1;
end
else begin
cnt_bit <= cnt_bit;
cnt <= cnt + 32'd1;
end
Data <= Data;
if(cnt == CLK_MID-1)
vaild <= 1;
else
vaild <= 0;
end
default:begin
cnt_bit <= 5'd0;
cnt <= 32'd0;
Data <= 8'd0;
vaild <= 32'd0;
end
endcase
endmodule
然后是接收控制信息的模塊,rx傳出來的Data會(huì)輸入到這個(gè)模塊里面,根據(jù)輸入的控制信息輸出
對(duì)應(yīng)的小車控制信息。文章來源:http://www.zghlxwxcb.cn/news/detail-724131.html
module rx_ctrl(
input sysclk ,
input rst_n ,
input [7:0] Data ,
output reg [3:0] car_ctrl_2
);
always@(posedge sysclk)
if(!rst_n)
car_ctrl_2 <= 4'b0000;
else
case(Data)
8'h47 : car_ctrl_2 <= 4'b1001;//前進(jìn)
8'h4b : car_ctrl_2 <= 4'b0110;//后退
8'h4a : car_ctrl_2 <= 4'b1010;//右轉(zhuǎn)
8'h48 : car_ctrl_2 <= 4'b0101;//左轉(zhuǎn)
8'h49 : car_ctrl_2 <= 4'b0000;//停止
default :car_ctrl_2 <= 4'b0000;
endcase
endmodule
然后是TOP模塊,我們需要將所有的模塊都都連接起來。這里頂層加了一個(gè)led的輸出,這樣方便我們觀察我們當(dāng)前處于什么狀態(tài),也可以方便我們切換狀態(tài),通過判斷l(xiāng)ed處于什么狀態(tài),將小車的控制輸出交給相對(duì)應(yīng)的控制輸出模塊。在這個(gè)里面,數(shù)碼管和led都可以不用加,這里加入了只是因?yàn)榭梢愿玫膸椭覀冇^察小車的狀態(tài)。文章來源地址http://www.zghlxwxcb.cn/news/detail-724131.html
`timescale 1ns / 1ps
module TOP8(
input sysclk,
input rst_n,
input echo,//輸出的超聲波
input [1:0] D0,
input RX,
output trig ,//產(chǎn)生高電平
output reg [3:0] led ,
output [7:0] seg ,
output [3:0] dig ,
output reg [3:0] car
);
//assign car=4'b1010;
wire [13:0] distance;
wire [7:0] Data;
wire [3:0] car_ctrl0;//避障
wire [3:0] car_ctrl1;//循跡
wire [3:0] car_ctrl2;//藍(lán)牙
always @(posedge sysclk)
if(!rst_n)
led<=4'b0000;
else
case(Data)
8'h41:led<=4'b0001;//避障
8'h42:led<=4'b0010;//循跡
//8'h43:led=4'b0100;//藍(lán)牙
default :led<=4'b0100;
endcase
always @(posedge sysclk)
if(!rst_n)
car<=4'b0000;
else
case(led)
4'b0001:car<=car_ctrl0;//避障
4'b0010:car<=car_ctrl1;//循跡
4'b0100:car<=car_ctrl2;//藍(lán)牙
default :car<=4'b0000;
endcase
csb csb1(
.sysclk (sysclk ),
.rst_n (rst_n ),
.trig (trig ),//產(chǎn)生高電平
.echo (echo ),//輸出的超聲波
.distance(distance)
);
seg seg1(
. sysclk (sysclk) ,
. rst_n (rst_n ) ,
. num (distance ) , //數(shù)碼管上顯示的數(shù)字0-9999
. seg (seg ) ,//段選8個(gè)燈
. dig (dig ) //位選4個(gè)數(shù)碼管
);
car_c car1(
. sysclk (sysclk) ,
. rst_n (rst_n ) ,
. distance (distance) ,
. car (car_ctrl0 )
);
red_line red1(
.sysclk (sysclk),
.rst_n (rst_n ),
.D0 (D0 ),
.car (car_ctrl1 )
);
uart_RX_car
#(
. SYSCLK(50_000_000 ) ,//系統(tǒng)時(shí)鐘
. Baud (9600 ) //波特率
)
uart1(
. sysclk ( sysclk ) ,
. rst_n ( rst_n ) ,
. RX ( RX ) ,
. vaild ( vaild ) ,//數(shù)據(jù)有效
. Data ( Data )
);
rx_ctrl rx1(
. sysclk ( sysclk ) ,
. rst_n ( rst_n ) ,
. Data ( Data ) ,
.car_ctrl_2 (car_ctrl2 )
);
endmodule
到了這里,關(guān)于基于FPGA的藍(lán)牙遙控,超聲波避障,紅外循跡的智能小車的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!