当前位置:首页 > 新闻资讯 > FPGA之家动态 >

FPGA智能小车开发板实战:从循迹避障到多传感器融合的完整指南

时间:2026-10-25      来源:FPGA_UCY 关于我们 0

1. 从零上手FPGA智能小车:这套开发板到底能帮你做什么

如果你手头正好有一块FPGA智能小车开发板,或者正在犹豫要不要入手一套来练手,那这篇内容就是为你准备的。我前后用过几套不同架构的FPGA小车平台,从最基础的循迹避障到带视觉反馈的路径规划都折腾过一轮,踩过的坑不算少。今天就把FPGA智能小车开发板的使用逻辑、核心模块、实操流程和常见故障排查,完整地梳理一遍。

FPGA智能小车开发板,本质上是一块以FPGA芯片为核心控制器的移动机器人平台。它和市面上常见的单片机小车最大的区别在于:单片机是串行执行指令,而FPGA是并行处理逻辑。这意味着什么?举个例子,你在做电机控制的同时还要跑传感器融合、PWM调速、编码器计数,如果用单片机,这些任务得排队轮流执行,稍不注意就出现响应延迟;而FPGA可以把这些任务分配到不同的硬件逻辑单元里,真正实现“同时开工”。这就是为什么很多对实时性要求高的场景——比如高速循迹、多路超声波同步采集、多电机协同控制——会优先考虑FPGA方案。

这套开发板通常包含几个核心部分:FPGA主控芯片及最小系统、电机驱动模块、电源管理模块、传感器接口(红外、超声波、编码器等)、以及扩展IO口。不同厂商的板子在外设配置上会有差异,但整体架构思路是一致的。它适合谁来用?我的判断是:有一定数字电路基础、学过Verilog或VHDL、想找一个综合性项目来打通“代码到实物”全链路的开发者。如果你完全没接触过FPGA,直接上小车可能会有点吃力,建议先把流水灯、数码管、按键消抖这些基础实验过一遍再回来。

接下来的内容,我会按照“整体设计思路→核心模块拆解→实操流程→问题排查”的顺序展开,每个环节都配上我实际调试时的参数和做法,尽量让你看完就能直接动手。

2. 整体方案设计与选型思路拆解 2.1 为什么用FPGA而不是单片机做小车控制

这个问题我被问过很多次。先说结论:不是单片机不好,而是FPGA在某些特定需求下优势太明显了。

最典型的场景是多路PWM输出。假设你的小车是四轮驱动,每个轮子需要独立的PWM调速信号,同时还要读取四路编码器的脉冲信号来计算转速。如果用单片机,PWM输出可以用硬件定时器解决,但四路编码器计数就需要频繁中断,CPU开销很大。而FPGA的做法是:为每个轮子分配一个独立的PWM生成模块和一个编码器计数模块,这些模块在硬件层面并行运行,互不干扰。你只需要在顶层模块里把它们例化并连接好信号线,剩下的交给硬件自动完成。

另一个场景是传感器数据采集的同步性。比如你用超声波测距,发射触发信号和接收回波信号之间的时间差就是距离。如果用单片机轮流采集多路超声波,第二路发射的时候第一路的回波可能还没回来,时序上就容易混乱。FPGA可以做到多路超声波同时发射、同时计时,采集效率成倍提升。

当然,FPGA也有它的代价:开发周期比单片机长,调试难度更高,成本也更贵。所以我的建议是,如果你的小车只需要简单的循迹和避障,单片机足够了;但如果你想做高速竞速、多传感器融合、或者想深入理解数字系统的硬件设计,FPGA小车是非常值得投入的项目。

2.2 开发板核心模块的架构逻辑

一块典型的FPGA智能小车开发板,在架构上可以分成三层:

第一层是主控与电源层。 FPGA芯片通常需要多个电压域供电,比如核心电压1.2V、IO电压3.3V、辅助电压2.5V等。板子上会有对应的LDO或DC-DC稳压电路。电源部分的设计质量直接影响FPGA能不能稳定运行,我遇到过好几次因为电源纹波过大导致FPGA随机死机的情况,后来在电源输出端并了一个大电容才解决。

第二层是外设驱动层。 包括电机驱动芯片(常见的有L298N、TB6612、DRV8833等)、传感器接口电路、以及电平转换电路。这里需要注意:FPGA的IO口驱动能力有限,一般不能直接驱动电机,必须通过驱动芯片。另外,如果传感器是5V电平而FPGA的IO是3.3V,就需要电平转换,否则可能烧坏FPGA的IO口。

第三层是扩展与调试层。 包括JTAG下载接口、UART串口、LED指示灯、按键等。JTAG接口用于下载配置文件和在线调试,UART用于和上位机通信,LED和按键用于快速验证基本功能。

理解这三层架构之后,你在拿到任何一块FPGA小车开发板时,都能快速定位到各个功能模块的位置,知道从哪里开始下手。

2.3 工具链选型与开发环境搭建

FPGA开发离不开厂商提供的EDA工具。目前主流的工具有Xilinx的Vivado(或ISE)、Intel(Altera)的Quartus、以及Lattice的Diamond等。具体用哪个,取决于你板子上的FPGA芯片是哪家的。

以Xilinx Artix-7系列为例,Vivado是首选。安装Vivado的时候有个坑:它默认会安装很多你根本用不到的器件库,占用大量磁盘空间。我的做法是只勾选自己芯片对应的系列,比如Artix-7,其他全部取消。这样安装包能从几十GB缩减到十几GB。

开发环境搭建好之后,你需要确认三件事:一是JTAG下载器驱动是否正常安装,二是板子的供电是否稳定,三是能否成功扫描到FPGA芯片。这三步都通过了,才能开始写代码。

注意:不同厂商的下载器不能混用。Xilinx的Platform Cable USB只能用于Xilinx芯片,Altera的USB-Blaster只能用于Altera芯片。买板子的时候一般会配对应的下载器,别搞丢了。

3. 核心模块深度解析与实操要点 3.1 电机驱动模块的PWM调速原理与参数计算

电机驱动是智能小车最核心的功能之一。FPGA控制电机的本质,是通过PWM信号调节电机两端的平均电压,从而控制转速。

PWM调速的核心参数有两个:频率和占空比。频率决定了电机响应的平滑度,占空比决定了转速大小。频率太低,电机会有明显的抖动和噪音;频率太高,驱动芯片可能响应不过来。根据我的实测经验,对于普通直流减速电机,PWM频率在1kHz到20kHz之间比较合适。我一般选10kHz,这个频率下电机运行平滑,驱动芯片也不会发热严重。

占空比的计算就很简单了:假设PWM周期是100个时钟周期,占空比为60%,那么高电平持续60个周期,低电平持续40个周期。在Verilog里,可以用一个计数器来实现:

module pwm_gen(
    input clk,          // 系统时钟,假设50MHz
    input rst_n,        // 复位信号,低有效
    input [7:0] duty,   // 占空比,0-100
    output reg pwm_out  // PWM输出
);
reg [15:0] counter;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        counter <= 16'd0;
    else if (counter >= 16'd4999)  // 50MHz / 10kHz = 5000
        counter <= 16'd0;
    else
        counter <= counter + 1'b1;
end
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        pwm_out <= 1'b0;
    else if (counter < duty * 50)  // duty * (5000/100)
        pwm_out <= 1'b1;
    else
        pwm_out <= 1'b0;
end
endmodule

这段代码里,系统时钟是50MHz,PWM频率设为10kHz,所以计数器从0数到4999就是一个完整的PWM周期。占空比通过duty信号控制,范围0到100。注意duty乘以50是因为5000个计数周期对应100%占空比,所以每1%对应50个计数。

实际接线的时候,PWM输出不能直接接电机,必须经过电机驱动芯片。以TB6612为例,它有两个输入引脚(AIN1、AIN2)控制方向,一个PWM引脚控制速度。方向控制逻辑是:AIN1=1、AIN2=0正转,AIN1=0、AIN2=1反转,AIN1=AIN2=0停止。这个逻辑在FPGA里用组合逻辑就能实现,非常简单。

3.2 红外循迹传感器的信号处理与滤波策略

红外循迹是智能小车最基础的功能。原理很简单:红外发射管发出红外光,遇到白色地面反射回来被接收管检测到,遇到黑色线条则不反射。通过判断接收管输出的高低电平,就能知道小车是否偏离了黑线。

但实际用起来,红外传感器有几个坑。第一个坑是环境光干扰。如果场地灯光太强,或者有阳光直射,红外接收管可能一直输出低电平,导致误判。解决办法是给传感器加遮光罩,或者在软件里做动态阈值调整。第二个坑是传感器安装高度。太高了反射信号弱,太低了容易刮到地面。我的经验是距离地面1到2厘米比较合适,具体要根据传感器型号微调。

在FPGA里处理红外信号,关键是要做消抖滤波。红外传感器的输出在黑白交界处可能会有抖动,如果不处理,小车的方向控制就会频繁切换。我一般用移位寄存器做简单的多数表决滤波:

reg [3:0] sensor_shift;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        sensor_shift <= 4'b0000;
    else
        sensor_shift <= {sensor_shift[2:0], sensor_raw};
end
// 4个周期中有3个以上为高才认为是高
wire sensor_filtered = (sensor_shift[3] + sensor_shift[2] + 
                        sensor_shift[1] + sensor_shift[0]) >= 3;

这段代码的意思是:连续采样4次,如果其中3次以上都是高电平,才认为信号有效。这样可以有效滤除毛刺。采样频率取决于你的系统时钟,一般用1kHz左右的采样率就够了。

循迹的控制逻辑也不复杂。假设小车前面装了5路红外传感器,从左到右编号1到5。正常直行时,中间传感器(3号)检测到黑线;如果2号或1号检测到黑线,说明小车偏右了,需要向左修正;反之则向右修正。修正的力度可以通过PWM占空比的差值来调节,偏得越多,差值越大。

3.3 超声波避障的时序控制与距离计算

超声波测距模块(比如HC-SR04)的工作时序是这样的:给Trig引脚一个至少10微秒的高电平脉冲,模块自动发射8个40kHz的超声波脉冲,然后Echo引脚会输出一个高电平,高电平的持续时间就是超声波从发射到遇到障碍物反射回来的时间。

距离的计算公式是:距离 = 高电平时间 × 声速 / 2。声速在常温下大约是340米/秒,也就是34000厘米/秒。如果高电平时间是580微秒,那么距离 = 580 × 10^-6 × 34000 / 2 ≈ 9.86厘米。

在FPGA里实现这个逻辑,需要三个模块:触发信号生成、回波信号计时、距离计算。触发信号生成很简单,用一个计数器每隔一定时间(比如50毫秒)产生一个10微秒的高脉冲。回波计时用一个计数器在Echo为高时开始计数,Echo变低时停止。距离计算可以用硬件乘法器或者查找表来实现。

这里有个细节需要注意:超声波模块的Echo输出是5V电平,而FPGA的IO通常是3.3V。直接连接可能会损坏FPGA的IO口。我一般用一个电阻分压电路把5V降到3.3V,或者用专用的电平转换芯片。这个问题在第一次调试的时候特别容易忽略,等到IO口烧了才后悔。

另外,超声波测距的有效角度大约只有15度,如果障碍物不在正前方,可能检测不到。所以实际做避障的时候,我一般会用两个超声波模块,一个朝左前,一个朝右前,或者用一个舵机带动超声波模块左右扫描。舵机控制也是PWM信号,周期20毫秒,高电平时间0.5到2.5毫秒对应0到180度。

3.4 编码器测速与闭环控制的实现

如果你想让小车跑得稳、跑得准,光有开环PWM调速是不够的。电机在负载变化、电池电压下降的时候,转速会明显变化。这时候就需要编码器做闭环控制。

编码器一般安装在电机轴上,电机每转一圈输出一定数量的脉冲。比如每转一圈输出20个脉冲,减速比是1:30,那么车轮每转一圈就是600个脉冲。在FPGA里,可以用一个计数器对编码器脉冲进行计数,每隔固定时间(比如10毫秒)读取一次计数值,然后清零重新计数。这个计数值就反映了这段时间内的平均转速。

闭环控制的核心是PID算法。在FPGA里实现PID,可以用定点数运算来简化。比例项P直接乘以误差,积分项I累加误差,微分项D取误差的变化量。三项加权求和后输出给PWM模块。参数整定是个经验活,我一般先把I和D设为0,只调P,让系统刚好出现轻微振荡,然后加D抑制振荡,最后加I消除稳态误差。

实操心得:编码器计数的时候一定要注意方向判断。如果电机反转,计数器应该减而不是加。判断方向的方法是看两路编码器信号的相位差:A相超前B相90度是正转,B相超前A相90度是反转。在FPGA里可以用D触发器锁存A相在B相上升沿时的值来判断。

4. 完整实操流程与关键环节实现 4.1 硬件组装与接线检查清单

拿到开发板之后,不要急着上电。先按照下面的清单逐项检查:

检查项 具体内容 常见问题

电源

电池电压是否在额定范围

电压过低导致FPGA无法配置

电机驱动

驱动芯片供电是否正常

驱动芯片发热严重

传感器

红外/超声波接口是否对应

接口插反导致信号异常

下载器

JTAG排线是否插紧

接触不良导致下载失败

跳线帽

各功能模块跳线是否正确

跳线错误导致功能不工作

我自己的习惯是:先用万用表量一遍电源对地有没有短路,再上电测各电压域是否正常,最后才插下载器。这个顺序能避免大部分烧板子的悲剧。

接线的时候有个原则:强电和弱电分开走线。电机线电流大,容易对传感器信号产生干扰。如果电机线和传感器线捆在一起,红外传感器可能会误触发。我一般把电机线走一边,传感器线走另一边,交叉的地方尽量垂直。

4.2 FPGA工程的创建与引脚约束

以Vivado为例,创建工程的流程是:新建工程→选择芯片型号→添加Verilog源文件→添加约束文件→综合→实现→生成比特流→下载。

其中最关键的一步是引脚约束。你需要根据开发板的原理图,把Verilog模块的输入输出端口映射到FPGA的实际引脚上。约束文件的格式是这样的:

# 时钟引脚
set_property PACKAGE_PIN E3 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
# PWM输出引脚
set_property PACKAGE_PIN A1 [get_ports pwm_out]
set_property IOSTANDARD LVCMOS33 [get_ports pwm_out]
# 红外传感器输入引脚
set_property PACKAGE_PIN B1 [get_ports sensor_in]
set_property IOSTANDARD LVCMOS33 [get_ports sensor_in]

引脚号一定要对照原理图来写,写错了轻则功能不工作,重则烧IO口。IOSTANDARD也要注意,如果板子上的IO电压是3.3V,就写LVCMOS33;如果是2.5V,就写LVCMOS25。这个不能猜,必须看原理图。

约束文件写完之后,跑一遍综合和实现,看看有没有时序违例。如果有,需要检查时钟频率是否设得太高,或者逻辑路径是否太长。对于小车这种应用,50MHz的系统时钟一般不会有问题,但如果你的逻辑特别复杂,可能需要插入流水线寄存器。

4.3 分模块调试与联调策略

我的调试策略是:先分模块单独验证,确认每个模块都能正常工作之后,再做联调。这样做的好处是,出问题的时候容易定位。

具体步骤是这样的:

第一步,验证时钟和复位。写一个最简单的LED闪烁程序,确认FPGA能正常配置、时钟能正常起振。这一步通过了,说明开发环境没问题。

第二步,验证PWM输出。用示波器或者逻辑分析仪看PWM波形,确认频率和占空比符合预期。如果没有仪器,可以接一个LED,看亮度变化是否平滑。

第三步,验证传感器输入。用手遮挡红外传感器,观察FPGA内部的信号变化。可以在Vivado里用ILA(集成逻辑分析仪)抓取信号,非常方便。

第四步,验证电机驱动。先不给PWM,只给方向信号,看电机能不能正反转。然后再给PWM,看调速是否正常。

第五步,联调。把循迹、避障、测速这些功能逐个加进来,每加一个功能就测试一次,确保没有相互干扰。

注意:联调的时候一定要把小车架空,让轮子悬空转。否则小车突然跑起来,你可能来不及断电,容易撞坏东西或者扯断线。

4.4 上位机通信与参数在线调整

小车跑起来之后,你肯定需要实时查看速度、传感器状态这些数据,或者在线调整PID参数。这时候就需要上位机通信。

最简单的方案是用UART串口。FPGA里实现一个UART发送模块,把数据打包成固定格式发出去,上位机用串口助手接收显示。UART的波特率一般用115200,数据位8位,停止位1位,无校验。

UART发送模块的核心是一个状态机:空闲状态等待发送请求,收到请求后先发起始位(低电平),然后依次发8个数据位(低位在前),最后发停止位(高电平)。每个位的持续时间由波特率决定,115200波特率对应每个位约8.68微秒。假设系统时钟50MHz,那么每个位需要计数434个时钟周期。

module uart_tx(
    input clk,
    input rst_n,
    input [7:0] data_in,
    input tx_start,
    output reg tx_out,
    output reg tx_done
);
reg [15:0] baud_cnt;
reg [3:0] bit_cnt;
reg [9:0] shift_reg;
reg sending;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        tx_out <= 1'b1;
        tx_done <= 1'b0;
        sending <= 1'b0;
        baud_cnt <= 16'd0;
        bit_cnt <= 4'd0;
    end
    else if (tx_start && !sending) begin
        shift_reg <= {1'b1, data_in, 1'b0};  // 停止位+数据+起始位
        sending <= 1'b1;
        baud_cnt <= 16'd0;
        bit_cnt <= 4'd0;
    end
    else if (sending) begin
        if (baud_cnt >= 16'd433) begin
            baud_cnt <= 16'd0;
            tx_out <= shift_reg[0];
            shift_reg <= {1'b1, shift_reg[9:1]};
            bit_cnt <= bit_cnt + 1'b1;
            if (bit_cnt >= 4'd9) begin
                sending <= 1'b0;
                tx_done <= 1'b1;
            end
        end
        else begin
            baud_cnt <= baud_cnt + 1'b1;
            tx_done <= 1'b0;
        end
    end
end
endmodule

有了UART通信,你就可以在上位机上用Python或者MATLAB写一个简单的界面,实时显示小车状态,或者发送指令调整参数。这个功能对于调试PID特别有用,不用每次改参数都重新下载比特流。

5. 常见问题排查与避坑经验实录 5.1 下载配置失败的原因与排查路径

下载失败是新手遇到最多的问题。根据我的经验,原因通常集中在以下几个方面:

第一,下载器驱动没装好。 在设备管理器里看看有没有识别到下载器。如果显示未知设备,需要手动安装驱动。Xilinx的下载器驱动在Vivado安装目录下的data\xicom\cable_drivers文件夹里。

第二,JTAG排线插反了。 排线的红色边一般对应引脚1,看看板子上的JTAG座有没有标引脚1的位置。插反了不会烧,但肯定连不上。

第三,FPGA供电不足。 有些板子用USB供电,如果USB口输出电流不够,FPGA可能配置到一半就失败了。换一个电流大一点的USB口,或者用外部电源供电。

第四,芯片型号选错了。 Vivado工程里选的芯片型号必须和板子上的实际芯片一致。选错了综合能过,但下载会报错。

第五,比特流文件生成有问题。 看看综合和实现的日志里有没有严重警告。有时候时序不满足,生成的比特流下载后FPGA工作不稳定。

排查的时候,我一般按这个顺序来:先确认驱动和连接,再确认供电,最后确认工程配置。大部分问题在前两步就能解决。

5.2 电机不转或转速异常的诊断方法

电机不转,先别急着怀疑FPGA代码。用万用表量一下电机驱动模块的输出电压,如果没有电压,说明问题在驱动模块或者FPGA的PWM信号没出来。

判断PWM信号有没有出来,最简单的方法是用LED接在PWM输出脚上。如果LED亮度可以调节,说明PWM正常;如果LED一直亮或者一直灭,说明PWM模块有问题。

如果PWM正常但电机不转,检查驱动芯片的使能引脚(EN)有没有拉高。很多驱动芯片有一个使能引脚,不拉高的话输出是高阻态,电机不会转。

如果电机转速异常,比如忽快忽慢,可能是PWM频率太低导致的。把频率提高到10kHz以上试试。另外,电池电压下降也会导致转速变慢,这时候闭环控制就派上用场了。

还有一种情况是电机干扰导致FPGA复位。电机启动瞬间电流很大,会在电源线上产生尖峰,如果FPGA的复位电路没有滤波,可能会误触发复位。解决办法是在FPGA的复位引脚旁边加一个0.1微法的电容。

5.3 传感器误触发与信号干扰的解决方案

红外传感器误触发是最让人头疼的问题之一。我遇到过小车在白色地面上突然认为检测到黑线,然后疯狂转向的情况。后来发现是阳光从窗户照进来,红外接收管饱和了。

解决这个问题有几个思路:一是给传感器加遮光罩,用热缩管套住接收管,只留一个窄缝;二是降低红外发射管的驱动电流,减少反射信号的强度;三是在软件里做动态阈值调整,根据环境光强度自动调整判断门限。

超声波传感器的干扰主要来自多路超声波之间的串扰。如果两个超声波模块同时发射,A模块可能收到B模块的回波,导致测距错误。解决办法是分时复用,让多个超声波模块轮流工作,每个模块工作的时候其他模块停止发射。在FPGA里用一个状态机控制切换顺序就行。

编码器信号的干扰通常表现为计数不准。如果编码器线太长,或者和电机线捆在一起,脉冲信号上会有毛刺,导致多计数。解决办法是给编码器信号加RC滤波,或者在FPGA里做数字滤波,连续采样多次才确认一个脉冲。

5.4 常见问题速查表现象 可能原因 排查方法 解决措施

下载失败

驱动未安装

检查设备管理器

安装对应驱动

下载失败

JTAG插反

检查排线方向

重新插拔

FPGA不工作

供电不足

测量电压

更换电源

电机不转

PWM无输出

LED测试

检查PWM模块

电机不转

使能脚未拉高

测量EN引脚

拉高使能

转速不稳

PWM频率低

示波器观察

提高频率

红外误触发

环境光干扰

遮挡测试

加遮光罩

超声波串扰

同时发射

分时测试

分时复用

编码器多计数

信号毛刺

逻辑分析仪

加滤波

FPGA随机复位

电源尖峰

示波器观察

加滤波电容

这张表是我自己调试时总结的,基本上覆盖了八成以上的常见问题。遇到问题的时候先查表,能省不少时间。

6. 进阶功能扩展与性能优化方向 6.1 从循迹到路径规划的升级思路

基础循迹只能让小车沿着一条黑线走,如果你想让它自主规划路径,就需要更高级的算法。最简单的升级是加入路口识别:当多个红外传感器同时检测到黑线时,说明遇到了十字路口或者T型路口,这时候可以根据预设的规则选择转向。

再进一步,可以用超声波或者激光雷达构建环境地图,然后用A 或者Dijkstra算法做路径规划。这些算法在FPGA上实现比较复杂,但也不是不可能。我试过用FPGA做简单的栅格地图存储和A 搜索,把地图存在Block RAM里,用状态机逐格搜索。速度比单片机快很多,因为搜索过程是硬件并行的。

不过说实话,如果你的主要目的是学习FPGA,不建议一上来就搞路径规划。先把循迹和避障做扎实,理解时序控制和状态机的设计思路,再往上加功能会顺畅很多。

6.2 多传感器融合的时序优化技巧

多传感器融合的核心难点是时序同步。不同传感器的采样周期不一样:红外传感器可以每毫秒采样一次,超声波需要几十毫秒才能完成一次测距,编码器需要根据速度动态调整采样窗口。

在FPGA里做时序优化,我的做法是用一个全局的时基计数器,产生多个不同频率的使能信号。比如1kHz的使能信号用于红外采样,20Hz的使能信号用于超声波触发,100Hz的使能信号用于编码器读取。这些使能信号在同一个时钟域下生成,天然同步,不会出现竞争冒险。

另外,传感器数据的读取最好用双缓冲或者FIFO。比如超声波测距完成之后,把距离值写入FIFO,主控制逻辑从FIFO里读。这样即使主控制逻辑正在处理其他任务,也不会丢失传感器数据。

6.3 资源占用分析与代码优化建议

FPGA的资源是有限的,尤其是逻辑单元和Block RAM。如果你的设计太复杂,综合的时候会报资源不足。我的一般原则是:能用硬件复用的地方就复用,不要每个功能都单独例化一个模块。

比如PWM生成,如果四个轮子都需要PWM,不需要例化四个PWM模块,只需要一个PWM模块加上一个四选一的多路选择器,分时输出到四个轮子。当然,这样做的代价是PWM更新率降低,但对于电机控制来说,10kHz的PWM频率分时四路,每路还有2.5kHz,完全够用。

代码优化方面,尽量用同步逻辑,避免组合逻辑环路。状态机的状态编码用独热码还是二进制码,取决于你的资源情况。独热码消耗更多触发器但组合逻辑简单,二进制码相反。对于小车这种规模的设计,二进制码一般就够了。

实操心得:综合之后一定要看资源报告。如果LUT占用超过80%,就要考虑优化了。另外,看看时序报告里的最差路径,如果裕量很小,说明设计有风险,温度变化或者电压波动都可能导致时序违例。

7. 个人调试体会与实用建议

折腾FPGA智能小车这段时间,我最大的体会是:硬件调试和纯软件开发完全是两回事。软件出错了可以断点调试、单步执行,硬件出错了只能靠示波器和逻辑分析仪去猜。所以,养成好的调试习惯比写代码的能力更重要。

我的习惯是每写一个模块就先单独测试,确认没问题再集成。集成的时候先跑最简功能,再逐步加功能。每次加功能之前,先备份一个能正常工作的版本,这样出了问题可以快速回退。

另外,不要忽视机械结构的影响。我遇到过好几次代码没问题但小车跑不好的情况,最后发现是轮子打滑、重心偏移、或者传感器安装角度不对。FPGA小车是一个软硬件结合的系统,任何一部分出问题都会影响整体表现。

最后分享一个小技巧:在FPGA里留一个“调试模式”,通过拨码开关或者按键切换。调试模式下,小车不跑,只输出传感器数据和内部状态到LED或者串口。这样你可以在不改变代码的情况下,快速查看系统运行状态,定位问题非常方便。


注明:本内容来源网络,不用于商业使用,禁止转载,如有侵权,请来信到邮箱:429562386ⓐqq.com 或联系本站客服处理,感谢配合!

上一篇:FPGA 查找表和寄存器等详解

下一篇:

✖

用户登陆

    未注册用户登录后会自动为您创建账号

✖

提交留言