FPGA项目三:PWM呼吸灯(上)

简介: FPGA项目三:PWM呼吸灯

第一节 项目背景


随着照明领域需求的不断扩大,LED 技术也在迅速发展,其控制方式也越来越多样化,可以产生多样的视觉效果。相较于只具备“开”“关”功能的传统 LED 照明,能够实现从 0 到 100%灯光亮度调节的 LED 灯在家装灯饰、舞美灯光等领域的需求更为突出。这种灯的灯光亮度可以通过调节控制由高到低的逐渐变化,像是人在呼吸一般,因而被称作呼吸灯。呼吸分为两个过程,一个是“呼”,一个是“吸”。而所谓的“呼吸灯”就是将人的呼吸频率通过光的强弱表现出来,其被广泛应用于手机上,并成为各大品牌手机的卖点之一。当手机里有未处理的通知,比如未接来电或未查收的短信时,呼吸灯就会像呼吸一样有节奏的由暗到亮不断变化,从而起到通知提醒的作用。

呼吸灯的设计方法有很多,例如采用 555 定时器的设计方案,电路利用电容充放电的原理较为简单,也可以用单片机产生脉冲宽度调制来驱动 LED。本案例中采用 PWM 驱动 LED 灯的方法来进行设计。


脉冲宽度调制技术(Pulse Width Modelation,PWM)是利用微处理器/FPGA 的数字输出对模拟电路进行控制的一种有效技术,其广泛应用于测量、通信、功率控制与变换等众多领域。PWM 数字信号从处理器到被控系统都采用数字形式,无需进行数模转换。航模中的控制信号大多是 PWM 信号,比如 FUTABA、JR 等舵机的控制都采用 PWM 方式,发射机给接收机输送脉冲后接收机会控制舵机进行旋转。举个例子,假定基础脉宽是 100ms,当发射机的脉宽增大(如增加到 150ms)时接收机控制舵机进行正向旋转;反之发射机的脉宽减小(如减小到 50ms)时,接收机控制舵机进行逆向旋转。

PWM 是一种对模拟信号电平进行数字编码的方法。通过使用高分辨率计数器对方波的占空比进行调制,从而对一个具体模拟信号的电平进行编码。由于在给定的任何时刻,满幅值的直流供电只存在有(ON)和无(OFF)两种状态,因此 PWM 信号仍然是数字信号。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。直流供电被加到负载上的时候为“通”,负载供电被断开的时候为“断”。只要有足够的带宽,任何模拟值都可以使用 PWM 进行编码。


通俗来说,PWM 是连续的、具有一定比例占空比的脉冲信号,可以通过控制占空比来对其进行改变。简单来说,可以认为 PWM 就是一种方波,如图 3.3-1 所示。

1670858412568.jpg

PWM原理的补充讲解:

以单片机为例,我们知道,单片机的IO口输出的是数字信号,IO口只能输出高电平和低电平


假设高电平为5V 低电平则为0V 那么我们要输出不同的模拟电压,就要用到PWM,通过改变IO口输出的方波的占空比从而获得使用数字信号模拟成的模拟电压信号


我们知道,电压是以一种连接1或断开0的重复脉冲序列被夹到模拟负载上去的(例如LED灯,直流电机等),连接即是直流供电输出,断开即是直流供电断开。通过对连接和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值(即0~5V之间任意大小)的模拟电压


比方说 占空比为50% 那就是高电平时间一半,低电平时间一半,在一定的频率下,就可以得到模拟的2.5V输出电压 那么75%的占空比 得到的电压就是3.75V

1670858423205.jpg

pwm的调节作用来源于对“占周期”的宽度控制,“占周期”变宽,输出的能量就会提高,通过阻容变换电路所得到的平均电压值也会上升,“占周期”变窄,输出的电压信号的电压平均值就会降低,通过阻容变换电路所得到的平均电压值也会下降

也就是,在一定的频率下,通过不同的占空比 即可得到不同的输出模拟电压

pwm就是通过这种原理实现D/A转换的。


总结:

PWM就是在合适的信号频率下,通过一个周期里改变占空比的方式来改变输出的有效电压

PWM频率越大,相应越快,了解 PWM 之后。


下面来学习一下 PWM 实现呼吸灯的原理:

信号的高低电平变化可以控制 LED 灯的明灭状态。当输出信号为低电平时 LED 灯亮,反之,当输出信号为高电平时 LED 灯灭。当输出电平持续为低,则灯一直保持亮的状态;而当输出电平持续为高,则灯一直保持灭的状态。如果输出信号 50%为低电平,50%为高电平,在 PWM 适宜的周期下LED 灯光会变暗,这也说明占空比对 LED 灯的明暗程度会产生影响。

另一个影响 LED 亮度的因素则是 PWM 波形的周期。试想一下,如果 PWM 的周期是 2 秒,占空比为 50%,此时观察到 LED 的状态是暗 1 秒、亮 1 秒,而不是半亮的状态。只有缩短 PWM 的期,才能看到 LED 半亮的状态。根据经验可知,如果要达到改变亮度的效果PWM 的周期以 10 毫秒为宜。

综上所述,通过控制高低电平的时间,即占空比(高电平占周期的百分比),以及控制 PWM 的周期,就可以改变灯的明暗程度。


如何实现PWM信号输出?

那么如果要实现PWM信号输出如何输出呢?


1)可以直接通过芯片内部模块输出PWM信号,前提是这个I/O口要有集成模块,只需要简单几步操作即可,这种自带有PWM输出的功能模块在程序设计更简便,同时数据更精确。如下图,一般的IC口都会标明这个是否是PWM口;

1670858442511.jpg

2)但是如果IC内部没有PWM功能模块,或者要求不是很高的话可以利用I/O口设置一些参数来输出PWM信号,因为PWM 信号其实就是一高一低的一系列电平组合在一起。具体方法是给I/O加一个定时器,对于你要求输出的PWM信号频率与你的定时器一致,用定时器中断来计数,但是这种方法一般不采用,除非对于精度、频率等要求不是很高可以这样实现。


第二节 设计目标


了解 PWM 呼吸灯的运行原理后来明确本次设计的功能目标。

确定功能目标是本书以及至简设计法的特别之处,只有对设计的功能目标有一定的理解和预期,才能更好地进一步讨论如何逐步进行代码设计和实现。后续设计中的每一个步骤都是围绕着设计目标的实现来针对性的展开,如果对于设计目标一知半解,那么在后续的设计思路中可能难以形成体系化的思考模式,只能碎片式的接收知识。设计目标就像大楼的设计图,如果连最终想要实现的目标都无法确定,那么后续的讨论就没有任何意义。因此在学习完整设计案例的过程中,静下心来从明确设计目标开始,一步步细细咀嚼,逐步掌握,才可以起到事半功倍的效果。


本工程旨在实现控制 LED 灯亮度的功能,具体要求为:上电后,LED 灯显示接近于灭,随后每隔 2 秒亮度发生一次变化,在前 10 秒时间内,每隔 2 秒逐渐变亮。在下一个 10 秒时间内,每隔 2秒,亮度逐渐变暗。简单来说即是以 20 秒为一次循环,每隔 2 秒变化一次,前 10 秒亮度逐渐增大,后 10 秒亮度逐渐减小。

选用开发板的硬件原理图如下图所示。

1670858471883.jpg

本设计的上板效果如图 3.3-3 所示

1670858483992.jpg

如果想要观看上板后的演示视频,可以登录至简设计法官方网站进行观看。


第三节 设计实现


3.1顶层设计


新建目录:D:\mdy_book\mdyBookPwmled,并在此目录中新建一个名为 mdyBookPwmled.v的文件。

用 GVIM 打开该文件后开始编写代码。在这里再次强调,初学者按照本书提供的路径名和文

件名创建文件,不要对路径名或文件名进行任何更改。因为对于初学者来说,如果贸然按照自己的意

愿更名,后续操作中可能会出现中文路径、空格路径等非法路径的问题,或者有些文件名更改后会出

现报错的现象。因此建议先按照要求更名保存,在多次进行工程练习熟悉了各个步骤后再进行自主更

名操作。在操作中不要想当然,细心操作以避免不必要的错误。


首先对板子上的 LED 灯进行分析,每个 LED 灯都与一个信号相连。这个信号一端连接 LED,另一端连接 FPGA。FPGA 通过控制这一信号的输出就可以控制 LED 灯的亮、灭以及亮度。当 FPGA 输出信号为 0 时,LED 灯点亮,反之,当 FPGA 输出信号为 1 时,LED 灯熄灭。通过输出 PWM波形并控制其占空比,FPGA 可以实现对 LED 灯的亮度进行控制。硬件电路图的连接关系如下表所示。本工程中 LED1 灯连接的 FPGA 管脚为 AA4,对应 FPGA工程信号为 led;工程的时钟管脚为 G1,对应 FPGA 工程信号为 clk;复位管脚为 G1,对应 FPGA工程信号为 rst_n。

1670858512843.jpg

综上所述,本工程一共需要三个信号,时钟 clk,复位 rst_n 和输出信号 led。将 module 的名称

定义为 mdyBookPwmled,在顶层信号代码中需要将与外部相连接的输入/输出信号列出,从而实现

信号与管脚的连接,其具体代码如下:

1670858523332.jpg

随后对信号的输入输出属性进行声明,指出对于 FPGA 来说这一信号属于输入还是输出,若为输入声明则为 input,若为输出声明则为 output。在本设计中,由于 clk 是外部晶振输送给 FPGA 的,因此在 FPGA 中 clk 为输入信号 input;同样地,rst_n 是外部按键给 FPGA 的,在 FPGA 中 rst_n 也为输入信号 input;同时可知 led 是 FPGA 输出控制 LED1 显示状态的,因此 led 为输出信号 output。


根据三个信号的属性将输入输出端口定义补充完整,其代码如下:

1670858535574.jpg


3.2 信号设计


在进行信号设计之前先按照至简设计法的思路来进行架构设计。回顾一下设计需求:通电后,LED 灯显示接近于灭,在之后的 10 秒内,每隔 2 秒钟亮度变化一次,逐渐变亮;在下一个 10 秒内,依旧是每隔 2 秒亮度变化一次,但是会逐渐变暗。可以将其总结为:本设计以 20 秒为一次循环,每隔 2 秒变化一次,前 10 秒亮度逐渐增大,后 10 秒亮度逐渐减小。


前文中详细的介绍过 PWM 的原理,可以得知通过控制 PWM 的占空比可以实现 LED 灯的亮度控制。PWM 占空比越大(高电平时间越长,低电平时间越低),灯的亮度越暗。可以这样理解:FPGA 控制 led 信号的输出,可以输出为 PWM 波形并通过调整占比来达到改变 LED 灯亮度的效果。


根据设计目标可以得出设计方案:每 20 秒一次循环,每隔 2 秒改变一次 led 的占空比,前 10 秒占空比逐渐变小,LED 灯逐渐变亮,后 10 秒占空比逐渐变大,LED 灯也随之逐渐变暗。由于设计目标只对亮度改变进行要求,并没有说明具体的占空比是多少,因此本书自行设定占空比。可以在上板时根据观察到的视觉效果,调整占空比的大小。本书设定占空比如下:

1670858550464.jpg

第 1 个 2 秒内,占空比为 95%;

第 2 个 2 秒内,占空比为 85%;

第 3 个 2 秒内,占空比为 70%;

第 4 个 2 秒内,占空比为 50%;

第 5 个 2 秒内,占空比为 20%;

第 6 个 2 秒内,占空比为 20%;

第 7 个 2 秒内,占空比为 50%;

第 8 个 2 秒内,占空比为70%;

第 9 个 2 秒内,占空比为 85%;

第 10 个 2 秒内,占空比为 95%。

之后以此为规律循环往复。


经过多次的实验和测试后发现:PWM 每 10 毫秒刷新一次,LED 灯显示的亮度效果是最好的。因此根据经验值,本书将 PWM 波周期设为 10 毫秒。建议初学者按照书中提供经验值来进行操作,在完全掌握了设计原理可以独立完成设计后,可以再进行不同波型以及不同占空比的尝试。


根据前文分析,得到 led 信号的变化波形图如下图所示。



第 1 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(9.5 毫秒时变低);

第 2 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(8.5 毫秒时变低);

第 3 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(7.0 毫秒时变低);

第 4 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(5.0 毫秒时变低);

第 5 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(2.0 毫秒时变低);

第 6 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(2.0 毫秒时变低);

第 7 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(5.0 毫秒时变低);

第 8 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(7.0 毫秒时变低);

第 9 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(8.5 毫秒时变低);

第 10 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(9.5 毫秒时变低);


此处PWM 波变低的时间是根据 10 毫秒 PWM 波的占空比算出来的,例如占空比为 95%时可以得出 10ms×95%=9.5ms,以此类推,可以得出所有 PWM 波的变化值。


根据至简设计法原理,总结需求可知,这次设计需要以下三个计数器:

计算输出 10 毫秒 PWM波的计数器;

计算每一个持续 2 秒时间的计数器;

计算次数(1-10 次)的计数器。

来思考一下:既然设计目标为 2 秒改变一次状态,那么为什么除了计算 2 秒的计数器之外还要增加次数的计数器,这样岂不是更麻烦吗?实际上增加计数器的操作正是采用了至简设计法的设计思路,让信号代码更加有条理并便于设计师确定位置。


举个生活中常见的例子,如下图所示,可以把每一次 20 秒的循环看做楼层,把每 2 秒一次的状

态改变看做门牌号,循环中的 2 秒、4 秒、6 秒时间即在对应门牌 1 号 2 号 3 号,以此类推。如果只

用一个计数器的话,那么一楼门牌号为 1、2、3、4、5、6、7、8,二楼门牌号为 9、10、11、12、

13、14、15、16、17、18,三楼以此类推。随着楼层的变高,这种计数方式的弊端就会显露出来。

比如在这种情况下想要寻找 76 号,就可能需要很久才能找到。

1670858562163.jpg

如果在一个计数单位的基础上再加一个计数单位,即采用两种技术模式,一个记楼层,一个记门牌号,如下图所示。在同样的门牌号计数中,可以记为一楼的 1、2、3、4、5、6、7、8 号,二楼的

1、2、3、4、5、6、7、8、9、10 号,以此类推,每一层都有对应的房间号。在这种计数模式下,

如果想要找到七层的 6 号房间,不需要多做思考就可以一下定位到正确位置。


此外,如果想要定位到每一层固定位置的房间,同样可以使用两种计数单位复合的模式:用 cnt

0 来表示房间号,其范围是 0-9,用 cnt1 来表示楼层号,其范围是 0-1,通过 cnt0 和 cnt1 两个计数

器可以找到任何一个房间。如果想找同一个位置的房间,也可以直接用 cnt0 来表示。例如 cnt04

可以统一表示每层楼的四号房间。但如果只有房间号这一计数模式而没有楼层的话,想表示每层楼的

四号房间,则表示方式为“cnt04”、“cnt0=12”,更高楼层以此类推。两种表现形式的难易程度

显而易见。


相关文章
|
6月前
|
C语言 异构计算
FPGA数字钟项目总结
FPGA数字钟项目总结
|
测试技术 异构计算
【FPGA基础入门实践】Verilog 基本项目操作逐步演示
【FPGA基础入门实践】Verilog 基本项目操作逐步演示
216 0
|
异构计算
FPGA项目四:串口通信(下)
FPGA项目四:串口通信
126 2
FPGA项目四:串口通信(下)
|
异构计算
FPGA项目三:PWM呼吸灯(下)
FPGA项目三:PWM呼吸灯
195 1
FPGA项目三:PWM呼吸灯(下)
|
异构计算
FPGA项目五:数码管动态扫描(下)
FPGA项目五:数码管动态扫描
206 0
FPGA项目五:数码管动态扫描(下)
|
程序员 异构计算
FPGA项目五:数码管动态扫描(中)
FPGA项目五:数码管动态扫描
254 0
FPGA项目五:数码管动态扫描(中)
|
异构计算
FPGA项目五:数码管动态扫描(上)
FPGA项目五:数码管动态扫描
300 0
FPGA项目五:数码管动态扫描(上)
|
程序员 异构计算
FPGA项目四:串口通信(中)
FPGA项目四:串口通信
295 0
FPGA项目四:串口通信(中)
|
芯片 异构计算
FPGA项目四:串口通信(上)
FPGA项目四:串口通信
372 0
FPGA项目四:串口通信(上)
|
程序员 异构计算
FPGA项目三:PWM呼吸灯(中)
FPGA项目三:PWM呼吸灯
253 0
FPGA项目三:PWM呼吸灯(中)

热门文章

最新文章