实现了带编码器的RTL级设计。

发布时间:2025-7-9

类别:行业知识

阅读:0

摘要:

实现了带编码器的RTL级设计。

图1:L298N和12V编码器电机原理图。

aa15ed26-56d4-11f0-9ca0-92fbcf53809c.png

图 2a:带有PWM源启用输入的FPGA电机控制器框图。

aa216f66-56d4-11f0-9ca0-92fbcf53809c.png

图2b:带有PWM源INx输入的FPGA电机控制器框图。

对于上面列出的前两点,即从设定值生成PWM信号所需的逻辑,了解L298N的工作原理非常有帮助。因此,下一节(可选阅读)将介绍这部分内容以及其他背景知识。

技术回顾

本节将对组件进行技术回顾,并介绍与这些组件接口所需的数字和模拟概念。本节涵盖的信息并非执行本项目的必要条件,但有助于理解创建各种模块和逻辑的原因。

L298N电机驱动器

如图 3 所示,L298N 可归类为一种直流放大器,它在其输入端转换脉冲宽度调制 (PWM) 信号,在本例中为 0 和 3.3VDC,并将其按比例转换为稳定的 0V 直流电压至 Vs,如前所述。

aa271934-56d4-11f0-9ca0-92fbcf53809c.png

图3:L298N电机驱动器

FPGA 的较低输出电压 0 - 3.3V 能够驱动 TTL 逻辑输入 (IN1 - IN4) 并使能 A 和 B 的原因在于 [1] 中列出的规格以及图 4b 所示的规格。其中说明如下:

控制信号输入电压范围:

逻辑低电平:-0.3V≤Vin≤1.5V

逻辑高电平:2.3V ≤ Vin ≤ Vss

其中,Vss 由 L298N 模块板载的 5V 直流稳压器供电。由于 FPGA 不会从 L298N 接收数字数据,因此无需逻辑电平转换器

L298N 模块是基于 L298 集成电路 (IC) 构建的。L298 IC 是一款高电压、高电流双全桥驱动器。L298 IC 的额定电压 Vs = 5V 至 46V(图 2a 和 2b),但 L298N 模块在 35V 以上的电压下存在散热和元件限制。

aa35826c-56d4-11f0-9ca0-92fbcf53809c.png

图 4a:L298IC-双全桥驱动器。[1]

aa3a9004-56d4-11f0-9ca0-92fbcf53809c.png

图 4b:L298部分电气特性列表[1]。

L298 双 H 桥

让我们快速看一下 H 桥电路。如果还没有完全理解下面的信息,不用担心,但为了完整性,我想补充一下。另外,如果愿意,可以跳过本节。

图 5 是 [1] 中 L298 框图的复制版。图中展示了数字电路(与门和非门)和模拟电路(BJT 晶体管电阻)的混合。逻辑门和 BJT 晶体管构成了电流控制电路。为了更好地理解电流控制电路的整体功能,下面给出了该图的简化版本及其说明。

aa3e9744-56d4-11f0-9ca0-92fbcf53809c.png

图5:L298IC框图[1]

图 6 用开关概念代替了电流控制电路。这展示了 H 桥电路的工作原理,我们也将用它来解释在 IN 引脚和 EN 引脚上使用 PWM 的区别。

aa499e82-56d4-11f0-9ca0-92fbcf53809c.png

图6:简化的单H桥电路表示

要使电机正转,需要闭合 S1 和 S4,完成从 Vs 经电机到地的电路(即电流路径)。S3 和 S2 根据需要保持断开。要使电机反转,则需要相反的情况,即闭合 S3 和 S2,断开 S1 和 S4。图 7a 和 b 说明了这一概念。

aa4d8f7e-56d4-11f0-9ca0-92fbcf53809c.png

图 7a 和 b:电机正向和反向旋转。

将此电路分析与图6联系起来,让我们看看用与逻辑门和BJT实现的开关。下面的逻辑方程等同于与门的输出,我们在这里将其标记为_d(代表数字)。

SW1_d = IN1 AND ENA

SW2_d = NOT IN1 AND ENA

SW3_d = IN2 AND ENA

SW4_d = NOT IN2 AND ENA

当上述任意 SWx_d 等于逻辑高电平时,相应的 BJT 导通。这是通过基极-发射极正向偏置(Vbe 超过基极输入和发射极输出引脚之间 +0.7V 的压降阈值)来实现的。当集电极电压分别大于基极和发射极电压(Vc >> Vb > Ve)时,导通的晶体管就像一个闭合的开关。参见图 8。

aa514e0c-56d4-11f0-9ca0-92fbcf53809c.png

图8:NPN晶体管[5]。

希望开关类比能够简化数字晶体管的控制逻辑。如果感兴趣并且具备相关背景知识,建议找一本好书或参考资料,进一步了解晶体管的工作原理以及不同类型的晶体管。

接下来,如果需要复习一下 PWM,我们来快速回顾一下。如果不需要,可以跳过此部分。

PWM

为了使连接到 L298N 电机驱动器的电机实现变速,我们使用了 PWM(脉冲宽度调制)。PWM 是一种获取可变模拟电压的数字方法。因此,方波数字信号的占空比(逻辑高电平时间与总脉冲周期的关系)可以通过增加或减少来改变模拟电路中的平均电压(图 9)。例如,如果 NPN 晶体管的基极-发射极结在给定的时间内导通时间更长,则电流会更大,从而导致集电极输出连接和发射极(在本例中为地)之间的电压降 (Vce) 更大。图 10 演示了这一概念 [7]。

aa55c23e-56d4-11f0-9ca0-92fbcf53809c.png

图9:各种占空比产生的 PWM[6]。

ab0885d6-56d4-11f0-9ca0-92fbcf53809c.png

图10:使用 PWM 和 NPN BJT 的直流电机电路[6]。

L298N PWM输入响应特性

如本文开头所述,使用 PWM 实现变速有两种不同的方法。方法 1 是用 PWM 驱动输入引脚(IN1、2、3 和 4),并将使能引脚设置为高电平,如图 11a 所示。方法 2 是将输入引脚对设置为高电平和低电平,以获得正确的旋转方向,并用 PWM 驱动使能引脚,以实现变速,如图 11b 所示。

ab0c904a-56d4-11f0-9ca0-92fbcf53809c.png

图11a:使用PWM控制电机速度的方法1[2]。

ab1629c0-56d4-11f0-9ca0-92fbcf53809c.png

图 11b:使用 PWM 控制电机速度的方法 2 [2]。

使用方法 1 可获得如图 7a 和 7b 所示的电流。唯一的区别在于每个脉冲周期内从 Vs 到 Gnd 的电流流动时间。

使用方法 2 会得到略有不同的响应。如果驱动电机正向旋转,IN1 上的 PWM 信号将处于活动状态,而 IN2 上的 PWM 信号将保持在低电平。由于 ENA 已通过跳线设置为逻辑高电平,因此开关切换完全由 IN1 上的有效 PWM 信号控制。将 IN2 和 ENA 都设置为受控的稳定值(0 和 1)后,SW3 始终设置为“关闭”或“打开”,SW4 始终设置为“打开”或“闭合”。但是,用于 SW4(~In1 和 EnA)的非门将在 PWM 占空比的低电平期间打开 SW2。这发生在 SW1 处于“关闭”或“打开”状态时。因此,电机的正极和负极连接到地。这会导致在 SW2 处于“打开”状态时释放反向的感应电动势 (EMF)。这种配置在较低转速下有用,但在较高转速下,由于反向 EMF 电压的反复损耗,会导致更高的电流消耗。

ab1a6094-56d4-11f0-9ca0-92fbcf53809c.png

图12a和b:左图,In1+PWM 周期的一部分。右图,PWM周期的接地状态。

12V直流编码器齿轮电机

我们为移动机器人选择的直流电机是专门配备磁编码器的。这对于此类直流电机来说很常见。对电机控制精度要求更高的直流电机则使用光学编码器。

旋转磁编码器有两个霍尔效应传感器。它们相对于电机轴线呈 90 度角放置。图 13 展示了这种布置如何产生相位差 90 度的编码器信号。

ab1e8c00-56d4-11f0-9ca0-92fbcf53809c.png

图13:霍尔效应传感器用于测量转速和方向[8]。

此图简化了,因为只使用了两个磁极。大多数带有磁编码器的电机都有数十到数百个这样的磁极,从而提高了电机旋转位置的分辨率。此外,有些系统会配备 4 个霍尔传感器,以进一步提高精度

上面显示的霍尔效应传感器产生的两个信号被指定为通道 A 和 B。这些通道具有以下特点:

它们的相位差为 90 度(见图 14)。

如果 A 领先于 B,那么电机就只能朝一个可能的方向转动。

如果 B 领先于 A,那么电动机的转动方向与前一个子弹的转动方向相反。

方波的频率与齿轮的旋转速度成正比。

ab2286f2-56d4-11f0-9ca0-92fbcf53809c.png

图14:编码器通道A和B 波形。

通过计算电机单次旋转产生的脉冲数,可以推导出由所用物理极数获得的分辨率。该信息可用于估算机器人的里程,方法是使用累积计数(我喜欢称之为“tics”)来计数/旋转,并使用车轮的直径(或半径)来计算其周长。

FPGA电机控制器设计细节

本节将详细介绍移动机器人电机驱动系统的关键 Verilog 代码。为了方便起见,该代码将与图 2a 所示的系统框图关联起来,并在下面的图 15 中复制。此外,我推导的 PID 算法可用作超前-跟随电机速度比较系统,并将进行详细解释。

Verilog 源层次结构

从图 15 所示的初始顶层设计中,派生出 Verilog 模块层次结构,然后在 AMD Vivado 中创建(图 16)。

ab265534-56d4-11f0-9ca0-92fbcf53809c.png

图15:电机控制系统的初始和最终框图

ab2a6926-56d4-11f0-9ca0-92fbcf53809c.png

图16:AMDVivado中的Verilog模块层次结构

外部引脚声明

接下来是用于 FPGA 与外部接口的输入和输出信号声明的 Verilog 代码(图 17)。在本例中,它用于 L298N、两个 12V 直流编码器电机(图 1)以及 RC 接收器单元(未显示)。

ab2ea086-56d4-11f0-9ca0-92fbcf53809c.png

图17:Verilog-顶层模块I/O定义至外部引引脚

编码器计数器模块

编码器计数器模块所用的代码源自fpga4fun.com [9](http://fpga4fun.com/)。在那里,可以找到详细的解释以及描述所用逻辑的波形图。本质上,只需使用系统时钟进行过采样、几个逻辑门和 D 触发器(为跨时钟域添加了几个额外的触发器)即可确定自旋的计数和方向。图 18 展示了代码的实现。

ab3a70d2-56d4-11f0-9ca0-92fbcf53809c.png

图18:编码器计数器逻辑[9]。

我还添加了仅创建正计数的逻辑。这对于我们稍后介绍的PID是必需的。

RC信号选择模块

此模块的名称有点用词不当。最初,该模块仅用于接收来自 RC 模块的方向信号,并将每个信号转换为两位值(图 19)。一位指示左轮应该前进还是后退,另一位指示右轮。每位都位于每个设定值(左轮和右轮)的最高有效位 (MSB)。目前,来自此模块并进入 PID 模块的左右电机设定值是相同的值(位 [6:0])。可以在顶部模块中更改用户设定值,方法是将 curr_setpt1 和 2 初始化为新值,然后运行 Vivado 进行综合、实现并生成比特流。此过程最多需要两分钟左右。

ab41cf4e-56d4-11f0-9ca0-92fbcf53809c.png

图19:rc_signal_selectv 的 RC 启用代码部分

ab4c6328-56d4-11f0-9ca0-92fbcf53809c.png

图 20:添加到rc_signal_select.y的非 RC 模式的附加多路复用逻辑。

PWM模块

如上所述,用户设定值(顶层名为 curr_setpt1 & 2)存储在 8 位寄存器的低 7 位中。因此,设定值取值范围为 0 至 127。该值表示馈入 L298N 的 PWM 的占空比。PWM 如何将设定值转换为占空比时间宽度?这是通过 PWM 模块中的 7 位计数器实现的。PWM 的输出最初为逻辑高电平(计数器 = 0)。当以 256 kHz 时钟频率计数的计数器计数到设定值时,PWM 输出逻辑低电平,直到计数器达到 127。结果是一个 2kHz 方波 PWM,占空比为设定值/127。

使用 Vivado 时钟向导从 100 MHz 系统时钟生成了一个 8.192 MHz 时钟。这样,256 kHz 模块中计数器的一位只需要与逻辑“1”进行比较。最终的 PWM 频率为 2 kHz,接近 1.5 kHz 的示例 [2],并且运行良好。

PID

PID 控制器模块的设计并不像我想象的那么简单。问题在于设定值(0 - 127)与每设定采样周期 T(例如 100 毫秒)读回的增量计数之间的转换。图 21 展示了讨论中的 PID 反馈回路框图。

ab5784ce-56d4-11f0-9ca0-92fbcf53809c.png

图 21:时间采样PID 控制反馈回路

对我来说,这里的问题是我没有看到(也没有产生)从 delta tics(计数)/T 回到设定值的低错误转换。

因此,决定使用设定点输入 r[k] 作为基准值,并添加一个基于两个电机先前计数和当前计数差异的修改值(误差值),从而包括每个电机每个周期 T(速度)总计数差异的离散时间分析/比较。

根据使用这些小型直流编码器电机的经验,注意到,在相同的PWM占空比设置下,一个电机的扭矩往往大于另一个电机。因此,在PID控制算法中,可以快速确定响应速度更快的电机,并将其用作主电机,以匹配速度和行驶距离。这样,速度修改只会针对速度较慢的电机的设定值输入r[k]进行。否则,电机的转速会非常快地上升。

让我们看一下所提出的领先-跟随方程,然后看一下这个离散领先-跟随电机反馈控制回路的伪代码。

e[k] = Feedback_1[k] - Feedback_2[k]; (1)

其中,e[k] 是在采样周期 k 处计算出的误差,Feedback_n[k] 是在采样周期 k 处电机 n(即 n = 1 或 2)的编码器计数器值。

Δx1[k] = Feedback_1[k] - PrevFeedback_1[k-1] (2)

Δx2[k] = Feedback_2[k] - PrevFeedback_2[k-1] (3)

Δx1x2[k] = Δx1[k] - Δx2[k] (4)

其中,PrevFeedback_n[k-1] 是电机 n 的编码器计数 Feedback[k-1] 在采样周期 k-1 保存,Δx1x2[k] 是电机 1 和 2 的转速差。

与图21所示的PID控制系统一样,有一些权重值(常数Ki、Ke和Kv)用于将公式(1)和公式(4)相乘,然后再相加。因此,得到的公式如下(图22所示的部分代码):

ab614aa4-56d4-11f0-9ca0-92fbcf53809c.png

我们将在下面讨论局部放电后误差方程的总体方程为:

u[k] = setpoint[k] + motorNSpdMod (5)

其中,N 再次表示电机数量 1 或 2。

可能注意到,公式 (5) 缺少积分元素。我将解释如何在 u[k](公式 5)中添加积分,这是平滑 FPGA 代码部分中误差振荡(反复从正到负)的关键,但最初并未考虑到这一点。

在 Vivado 中使用 Verilog 编写设计代码后,我创建了一个直流编码器电机的仿真模型,并在测试台上进行了两次实例化。该电机模型从被测单元 (UUT) 采样 PWM 波输入,并将计算出的转速转换为相应频率的编码器 A/B 通道波形。编码器波形通道被输入到 UUT 中。此外,我添加了一个“阻力”值,使电机的转速相对于其他电机有所降低。这使得速度较慢的电机的编码器数量较少,从而与实际电机和系统响应具有一定的相似性。当然,这是一个非常简单的模型,因为对一个电机增加的阻力是恒定的。如果在电机模型中至少创建一个简单的物理惯性响应,将会非常有利。该模型还假设移动机器人使用恒定的平坦水平表面。

不幸的是,我看到机器人落地后的响应与仿真结果不同,而我之前预想的没有物理模型会是这样的。

FPGA 中使用的公式经过测试,并根据需要进行了修改(例如,缩短 T 值、调整 Ke 和 Kv 值等),最初使用 Arduino Mega MCU 和 FPGAbot(不含 FPGA)在 C/C++ 中进行了验证。这缩短了验证和修改的周期。以下代码片段来自 Mega 测试(函数 PD_Alg(args)),代表了领先跟随算法(图 22)。

ab6910e0-56d4-11f0-9ca0-92fbcf53809c.png

图 22:C/C++代码中的领先-跟随PD算法。

代码的下半部分,motorNSpdMod 会根据最大设定值 (255 - C_fwdSpd - 20) 进行检查,以防止值过高。255 是最大占空比值(0 到 255),C_fwdSpd 实际上是两个电机的设定值(相同值),而 20 只是一个任意值,在 Arduino IDE 控制台上查看 Serial.print() 滚动显示的数据时,这个值似乎是合理的,如图 23 所示。

ab744f78-56d4-11f0-9ca0-92fbcf53809c.jpg

图 23:FPGAbot在地毯上运行的Serial.print()调试数据

从打印出来的数据来看,显然可以通过稍微调整 Ke 和 Kv,甚至在混合中添加一个积分元素来实现更好的响应。

FPGA 变体的领先-跟随 PID 方程实现

图 23a 和 b 分别给出了在领先-跟随方程 (5) 中添加积分之前和之后的仿真结果。

图 24a:领先-跟随PID Verilog 实现仿真。

图 24b:领先-跟随PID Verilog 实现仿真。

下图(图 25a 和 b)分别表示 e[k](误差)、dx1dx2(电机速度变化量)和 u[k](电机调制值)。图 25b 还添加了 Ki*integral[k](调制值之和乘以分数)的数据,这些数据列于公式 (6) 中。

u[k] = setpoint[k] + motorNSpdMod + Ki ΣmotorNSpdMod (6)

ab933c62-56d4-11f0-9ca0-92fbcf53809c.png

图 25a:领先-跟随控制算法的Verilog 实现中没有积分部分。

ab9f7fe0-56d4-11f0-9ca0-92fbcf53809c.png

图 25b:添加了积分的领先跟随控制算法的Verilog实现。

从这两幅图中不难看出,本例中积分非常迅速地抑制了误差和速度增量的振荡。这使得 u[k] 的调整非常平缓,与原始设定值吻合。

领先-跟随FB控制算法Verilog代码

图 22 所示的 C/C++ 代码在 MCU 上按顺序运行。这就是它们的工作原理。为了在 Verilog 中复制顺序计算,使用了一个状态机,每 10 ns(100 MHz 系统时钟)从一个计算状态切换到另一个计算状态。该算法的计算分布在 7 个状态中,计算时间为 70 ns。并不担心将计算时间缩短几十纳秒,并牺牲代码的可读性。与采样周期 T 相比,节省的时间在持续时间上要小三个数量级。为了使其更具可读性,将计算拆分成多个简洁的阶段会创建数据依赖关系,从而需要额外的时钟周期。

为了避免使用浮点数表示 Ki、Ke 和 Kv,从而节省大量 FPGA 逻辑资源,通过将误差、速度增量和积分右移(除以 2^n)来近似这些小数值。然而,在 Verilog 中使用有符号和无符号变量(寄存器)时需要谨慎。我发现,如果使用逻辑移位“>>”,负数右移最终会得到一个很大的正数。为了避免这种情况,需要使用算术右移表示“>>>”。

图 26a、b 和 c 中的代码演示了目前为止在 Verilog 中实现 PID 领先-跟随反馈 (FB) 控制算法所涵盖的概念,并在 Vivado 中进行了仿真(图 24a 和 b)。

aba39422-56d4-11f0-9ca0-92fbcf53809c.png

图 26a:Verilog 领先-跟随算法 e[k] 和 dx1dx2 计算。

aba810e2-56d4-11f0-9ca0-92fbcf53809c.png

图 26b:使用ke*e[K] 和Kv*dx1dx2计算motorNSpdMod

abac655c-56d4-11f0-9ca0-92fbcf53809c.png

图 26c:Verilog 领先-跟随算法 u[k] 计算



今日

焦点

/FOCUS

更多 >

PDF索引:

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

0

1

2

3

4

5

6

7

8

9

IC型号索引:

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

0

1

2

3

4

5

6

7

8

9

Copyright 2024 gkzhan.com Al Rights Reserved 京ICP备06008810号-21 京

0.218055s