里程计
里程计一般用于车载、采煤机、掘进机等无卫星的场景,大部分里程计内部为增量式编码器。
增量式编码器一般有A、B、Z三相,这里只使用A和B相,如果不需要分辨正转或者反转,单接A相或者单接B相即可。
接收硬件
接收编码器主要为TLP2160双路光耦芯片,其中原理图如下:
DI1+和DI1-分别为第一路的发光二极管正和负,DI2+、DI2-为第二路的。其中推荐使用电流如下:
再结合串联806欧姆电阻可得,输入电压范围为3.627V~12.09V(这里没算发光二极管电阻),这里我们这里使用的是5V差分电压,是在范围内的。
FPGA代码
直接贴代码
module encoder_dec
(
input sys_clk,
input rst_n,
input quad_a,
input quad_b,
output reg[31:0] encoder_a
);
reg [4:0] delay_a; //消抖
reg [4:0] delay_b; //消抖
reg [1:0] div_a; //消抖后a
reg div_update_a;
reg div_b; //消抖后b
always @(posedge sys_clk) delay_a <= {delay_a[4-1:0], quad_a};
always @(posedge sys_clk) delay_b <= {delay_b[4-1:0], quad_b};
always@(posedge sys_clk or negedge rst_n) begin
if(!rst_n) begin
encoder_a <= 32'd0;
div_a <= 2'd0;
div_update_a <= 1'd0;
div_b <= 1'd0;
end
else begin
div_update_a <= 1'd0;
if(delay_a == 5'b00000)begin
div_a <= {div_a[0],1'b0};
//div_update_a <= 1'd1;
end
else if(delay_a == 5'b11111)begin
div_a <= {div_a[0],1'b1};
div_update_a <= 1'd1;
end
if(delay_b == 5'b00000)begin
div_b <= 1'b0;
end
else if(delay_b == 5'b11111)begin
div_b <= 1'b1;
end
if(div_update_a == 1'd1)begin
//产生上升沿了
if(div_a == 2'b01) begin
if(div_b == 1'b0) begin
encoder_a <= encoder_a + 1'b1;
end
else begin
encoder_a <= encoder_a - 1'b1;
end
end
end
end
end
endmodule
信号名称 | 说明 |
---|---|
sys_clk | 时钟 |
rst_n | 复位 |
quad_a | 编码器A相 |
quad_b | 编码器B相 |
encoder_a | 编码器计数值 |
其中流程为等待A相上升沿,再判断B相是高电平还是低电平,如果是高电平计数值加1,否则数值减1