ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于FPGA与VHDL的直流电机测速PWM调速显示报警系统

基于FPGA与VHDL的直流电机测速PWM调速显示报警系统 简介这份「EDA直流电机测控仪课程设计」面向电子信息、自动化及FPGA初学者是一份围绕直流电机测控仪展开的课程设计文档可用于课程设计参考、实验报告撰写和电机控制入门实践。压缩包内共1个doc文件约900KB内容以设计说明与实验文档为主便于直接查阅、整理和打印。资料从FPGA背景、特点、分类、开发流程及Quartus II等工具切入重点给出基于EP2C35芯片的测控仪总体方案涵盖1MHz时钟、旋转电位器调速、PWM调速、8位七段数码管转速显示以及4×4键盘和16×16点阵扩展设计并涉及霍尔器件测速、直流电机驱动等环节。已有277人学习适合需要快速搭建课程设计框架、理解FPGA测控系统组成与模块划分的读者参考也可作为答辩准备和功能扩展的思路来源。1. 从霍尔脉冲到RPM直流电机测控仪的整体架构与选型取舍实验室的 SOPC-NIOSII-EP2C35 开发板上一台直流电机旁边立着转盘转盘边缘粘一片小磁钢正对着一颗开关型霍尔器件。电机每转一周霍尔输出端被磁钢拉低一次测速仪的原始信息就只有这一路方波。剩下的活全是数字逻辑把单位时间内的脉冲数换算成 RPM把键盘或旋钮的指令变成 PWM 占空比把转速同时推到 8 位数码管和 16×16 点阵上超速时再让蜂鸣器按节拍报警。这类 eda 课程设计之所以通常落在 FPGA 里是因为上面几件事必须并行测速闸门、动态扫描显示、键盘扫描、PWM 比较任何一件被拖慢读数就跳变、显示就闪烁。单片机靠定时器中断轮转也能做但用 EP2C35 这类器件每个模块各占一块逻辑、各跑各的节拍互不阻塞。适合刚接触 VHDL、想找一个能真正上板跑通的完整项目练手的人。2. 时钟分频与十进制计数链把 1MHz 变成能读的转速2.1 测速为什么用闸门计数而不是读脉冲间隔转速测量有两条路测频法和测周法。测频法固定一个闸门时间数里面有多少个脉冲低速时相对误差大测周法测两个脉冲之间的时间高速时误差大。直流电机在课程设计里的调速范围通常不宽用测频法实现起来最省事开一个 6 秒闸门数到的脉冲数乘以 10就是每分钟转速。闸门越长分辨率越高但刷新越慢。5 到 10 秒是常见选择6 秒正好让计数结果乘 10 就得 RPM不用做除法省掉一个除法器。代价是转速表大约每 6 秒才更新一次调速时手上得等一拍。2.2 时钟控制模块1Hz、1kHz 与锁存/清零时序整个系统的节奏都由时钟模块定它要把板上 1MHz 时钟切成三类信号秒脉冲 clkhz、蜂鸣器用的 1kHz、以及给计数器和锁存器的 ena/clr/load 三个控制位。library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity teltcl is port( clk : in std_logic; -- 板上 1MHz 时钟 ena : out std_logic; -- 计数器使能 clr : out std_logic; -- 计数器清零 load : out std_logic; -- 16 位锁存器锁存脉冲 clkhz : out std_logic; -- 1Hz秒计数用 clkkhz : out std_logic -- 1kHz蜂鸣器节拍 ); end teltcl; architecture behave of teltcl is signal clk1hz : std_logic; signal clk1khz : std_logic; signal sec_cnt : integer range 0 to 7; -- 0~7 秒循环 begin -- 1MHz 分频出 1Hz 与 1kHz占空比 50% process(clk) variable cnt1 : integer range 0 to 999999; variable cnt2 : integer range 0 to 999; begin if rising_edge(clk) then if cnt1 999999 then cnt1 : 0; else cnt1 : cnt1 1; end if; clk1hz 1 when cnt1 500000 else 0; if cnt2 999 then cnt2 : 0; else cnt2 : cnt2 1; end if; clk1khz 1 when cnt2 500 else 0; end if; end process; -- 秒计数第 6 秒末锁存第 7 秒清零 process(clk1hz) begin if rising_edge(clk1hz) then if sec_cnt 7 then sec_cnt 0; else sec_cnt sec_cnt 1; end if; end if; end process; load 1 when sec_cnt 6 else 0; clr 1 when sec_cnt 7 else 0; ena 1 when sec_cnt 6 else 0; clkhz clk1hz; clkkhz clk1khz; end behave;逻辑上分两段第一段是纯分频变量 cnt1 从 0 数到 999999 归零一个完整周期正好 1 秒前一半给高电平所以是 50% 占空比的 1Hzcnt2 数到 999得到 1kHz。第二段拿 1Hz 当节拍数秒0 到 5 秒期间 ena 有效让转速计数器工作第 6 秒末 load 拉高把计数值锁走第 7 秒 clr 把计数器抹掉下个周期重新开始。信号有效时刻作用enasec_cnt 66 秒闸门内允许计数loadsec_cnt 6锁存 16 位计数值clrsec_cnt 7清零计数器与进位链clkhz1Hz 方波秒计数节拍clkkhz1kHz 方波蜂鸣器断续音注意用rising_edge(clk1hz)属于派生时钟功能仿真没问题但综合到 Cyclone II 上 Quartus 会报时序约束警告。稳妥写法是把秒计数并进主时钟进程用 clk1hz 上升沿做条件判断而不是当时钟用。2.3 十进制计数链单级设计与进位脉冲转速最大 4 位十进制做法是先写一位十进制计数器再级联四份。单级的关键不是计数而是进位脉冲必须和归零同拍输出否则高位会多计或多漏。计数值下一拍进位0000~1000加一01001归零1进位脉冲只在 cnt1001 且 ena 有效的那一拍拉高下一级用它当使能。四级依次是各位、十位、百位、千位权重 1、10、100、1000。注意低位归零和高位加一必须发生在同一拍否则仿真里会看到数值从 0019 跳到 0030 这种鬼跳。2.4 16 位锁存器让数码管不再随计数抖如果数码管直接接计数器输出显示会在 6 秒闸门内一路狂奔末位根本看不清。锁存器的作用是把实时计数和显示数据隔开process(load) begin if rising_edge(load) then dout din; -- 只在 load 上升沿把当前计数值拷贝一次 end if; end process;din 是 16 位计数器输出dout 送去译码显示。count 在闸门内每分钟变化几千次load 每 7 秒才来一次显示值就稳定了。16 位宽度对应 4 位十进制每位 4 bit刚好够用不用做二进制到 BCD 的转换。3. PWM 占空比与 H 桥方向控制转速指令怎么落到电机端3.1 锯齿波比较法COUNT 与 DATAIN×1000 的关系pwm 驱动直流电机转速的核心是一个比较器加一个循环计数器。计数器从 0 数到 15999 反复循环形成锯齿波设定值 DATAIN 从 0 到 15表示 16 个速度档。计数小于设定阈值时输出高电平大于阈值时输出低电平。architecture rtl of pwm_gen is signal cnt : integer range 0 to 15999; begin process(clk) begin if rising_edge(clk) then if cnt 15999 then cnt 0; -- 锯齿波回零 else cnt cnt 1; end if; if cnt 0 then pwm 1; -- 每个周期起点拉高 elsif cnt datain * 1000 then pwm 0; -- 到达设定值翻低 end if; end if; end process; end rtl;逻辑说明datain0 时 cnt0 那拍立刻翻低占空比接近 0电机不转datain15 时阈值是 15000高电平占 15000/16000约 93.75%接近满速。参数说明周期上限 15999 决定了 PWM 频率1MHz 除以 16000 等于 62.5Hz步进 1000 决定了分辨率一共 16 档。3.2 分辨率与 PWM 频率的折中参数本设计取值影响周期计数16000频率 62.5Hz占空比步进100016 档每档 6.25%DATAIN 范围0~150 停止15 接近满速电机端平均电压旋钮给定 × 占空比由板上模拟给定决定上限这里有个反直觉的地方把占空比从 1/100 改成 1/1000 反而更平滑。步进越粗每加一档转速跳得越厉害数码管上看到的就是读数剧烈跳动。想再细一点把 1000 换成 125档位从 16 提到 128代价是 datain 位宽要变键盘输入也得跟着扩。3.3 方向与启停2 选 1 加与门进 H 桥PWM 波形本身只会调速不解决正反转和启停。方向由 Z/F 键控制一个 2 选 1 多路器决定波形从 H 桥的正端还是负端进去启停由 START 键和一个与门控制与门另一端接 pwm 原始波形run pwm_raw and start; -- START0 时整路封死 z_leg run when dir 0 else 0; -- 正转支路 f_leg run when dir 1 else 0; -- 反转支路H 桥用大功率管搭PWM 经方向选择后送进去做功率放大。方向切换的瞬间最好插入几毫秒死区否则上下桥臂直通会把管子烧掉课程设计里靠 START 先停再换向来规避。3.4 两个真会踩到的坑第一个坑PWM 占空比给到最大电机还是慢。原因不在逻辑在电路——PWM 信号只负责选通三极管真正决定电机供电电压的是电机左边那个旋钮。旋钮不开大PWM 满占空比也只是允许电流通过实际电压仍旧上不去。解决办法就是把旋钮调到较大位置PWM 再去做动态调节。第二个坑数码管转速读数跳动大。除了前面说的占空比步进还要检查闸门是否稳定在 6 秒。如果 clr 和 load 的先后次序写反会出现某一轮计数被清掉一半就锁存的情况读数直接腰斩。4. 4×4 键盘扫描与共用管脚的显示驱动4.1 行扫描读列四个状态就够4×4 键盘把 FPGA 的 8 个管脚分成两组4 根行线当输出4 根列线当输入。扫描时每次只把一行拉低其余行保持高电平然后读列线。哪一列被按下对应的列线就是低电平。process(clk) begin if rising_edge(clk) then case row_idx is when 0 row 1110; -- 扫第 1 行 when 1 row 1101; -- 扫第 2 行 when 2 row 1011; -- 扫第 3 行 when others row 0111; -- 扫第 4 行 end case; col_val col; -- 采列线电平 row_idx row_idx 1; -- 0→1→2→3→0 end if; end process;行列交点确定后输出一个 4 位键值几位为零就代表第几个键。逻辑说明行码用独热低电平列线也用独热低电平行号乘 4 加列号就是键位编号。行 \ 列列 0列 1列 2列 3行 0 (1110)键 1键 2键 3键 4行 1 (1101)键 5键 6键 7键 8行 2 (1011)键 9键 10键 11键 12行 3 (0111)键 13键 14键 15键 16注意机械按键抖动是几十毫秒级扫描时钟若直接是 1MHz一次抖动会被当成几十次按键。常见做法是扫描使能降频到 200Hz 左右再加一个 20ms 计数器连续两次读到同一个键值才确认。4.2 8 位数码管动态扫描与段码译码开发板上是两个四位一体共阴极数码管。共阴极的意思是段线给高电平点亮公共端接 GND。8 个管的 a 到 g 和 dp 全部并联位选各自独立被选通的那一位才显示数据。段码用 case 写最直观function seg7(b : std_logic_vector(3 downto 0)) return std_logic_vector is begin case b is when 0000 return 0111111; -- 0 when 0001 return 0000110; -- 1 when 0010 return 1011011; -- 2 when 1001 return 1101111; -- 9 when others return 0000000; -- 灭 end case; end function;8 位轮流点亮的频率要高于 50Hz否则肉眼看到闪。位选信号用一个三位计数器循环段码跟着对应位的 BCD 值走。显示内容上百、十、个位放计数器的后三级第六位固定显示 0其余位显示横线读数一眼就能读出来。4.3 点阵与数码管共用低 8 位管脚的分时策略这版硬件上一个容易忽略的点是七段数码管的段线和 16×16 点阵的低 8 列接在 FPGA 的同一组管脚上。也就是说这两个外设没法同时驱动必须分时复用。做法是拉一个 0 到 23 的扫描计数器0 到 7 分给 8 位数码管8 到 23 分给点阵的 16 行。切换时先把所有位选、行选拉无效再输出新的段码或列码。计数器区间驱动对象输出内容0~78 位数码管段码 对应位选8~2316×16 点阵第 N 行行选 该行 16 位列数据注意切换到点阵期间数码管的位选必须全部拉高无效反之点阵的行选也要关闭否则会出现上一帧残留的鬼影。点阵每行只点亮一列的时间极短靠视觉暂留拼成完整数字。5. 转速分级报警与上板联调技巧5.1 阈值判定与蜂鸣节拍速度分级是在锁存后的 RPM 值上做比较不占用测速通路。把 4000 和 2000 作为高、中、低的分界5000 作为警戒线超过时用 1kHz 时钟做门控让蜂鸣器每秒响一次。转速区间级别彩色 LED蜂鸣器小于 2000低速绿不响2000~4000中速蓝不响大于 4000高速红不响大于 5000警戒红1 秒间隔响process(clk1khz, alarm_en) begin if alarm_en 0 then beep 0; -- 报警开关闭合时静音 elsif rising_edge(clk1khz) then beep not beep; -- 1kHz 翻转靠秒门控断续 end if; end process;逻辑说明alarm_en 来自面板上的报警开关为 0 时直接封死输出为 1 时用 1kHz 驱动再配合一个 1Hz 的使能就能得到响一秒停一秒的效果。参数上报警开关和阈值比较是两路独立信号开关只切断声音不影响转速显示。5.2 上板联调的顺序与定位方法联调不要一上来就把电机接上按信号链从前往后推先单测时钟模块把 1Hz 和 1kHz 引到测试脚用示波器确认周期和占空比再单测十进制计数链手工给脉冲看进位然后测数码管和点阵的分时扫描最后才接驱动电路和电机。两个高频现象值得记一下数码管某一位始终不亮八成是位选极性搞反了共阴极位选是低有效写成高有效那一档就永远黑点阵显示拖影通常不是扫描太慢而是切换驱动对象时没有清屏把段码或列码清零一拍即可。调 PWM 手感时把步进值从 1000 改成 125 再重新综合上板档位从 16 档扩到 128 档同样一段键盘行程里转速的过渡会细密很多。本文还有配套的精品资源点击获取
返回列表