0%

CPLD 五层楼的简易电梯控制系统

GitHub地址:https://github.com/ICEORY/ElevatorCPLD

整体方案设计

项目本着“各个击破,各司其职”的指导思想进行设计。各个击破是指将整个电梯控制系统分为各个小模块进行设计,在完成小模块设计之后再进行组合最终实现需要的功能;各司其职指在设计的时候保证每个小模块执行自己要实现的功能,能够正确处理设计范围内的输入。

将整个控制系统根据功能细分为各个小功能模块,主要利用JK触发器74113o以及8-3编码器74148、数值比较器7485等数字模块搭建出系统需要的各个小模块,最后根据各个模块的之间的逻辑联系构建出整个系统。

在使用QuartusII软件搭建各个模块时,每搭建一个功能模块就要对其输入输出逻辑进行仿真,保证其输入输出的波形图满足需要的逻辑功能。当每个模块都能各司其职时,最终搭建整个控制系统才能做到事半功倍,清晰有条理。

根据题目的设计要求,整个电梯控制系统结构图如下所示:

system_overview

根据上述功能,将电路分为以下几个模块:

模块名称 目标实现功能
keyinput 获取单个按键输入,并能够存储按键状态,能够根据外部输入重置按键状态
doormotor 轿厢门电机,控制开关门动作,进行10ms计时,9s工作周期,其中开关门各一秒,停止7s,具有复位重新计时功能
motion 20s工作周期,能够根据上下行方向控制三相输出端的输出顺序
timescale 输入1KHZ时钟信号,进行分频之后输出1HZ,10HZ,100HZ,1KHZ的时钟信号
floorcount 输入楼层到达信号时上升沿触发,根据运行方向进行所存储的楼层数的加减,并输出计算结果
nextfloor 根据运行方向上的按键信息判断是否需要继续运行,判断是否需要开门,判断下次运行方向
otherdevice 对电梯其他辅助模块如蜂鸣器、排气、照明等设备进行控制
display 轿厢内、电梯门口的电梯所在楼层信息显示,包括所在楼层,运行方向

电梯运行的逻辑如下所示:

elevator_running_logic

电路设计及原理说明

按键电路设计

keyinput模块设计

根据功能要求,该模块的应具备以下的输入输出端口:

input output
KEY KEYSTATE
DONE DO
CLK

在逻辑上应满足:

  1. 接收到外界按键信息时,将输出的KEYSTATE强制为1;
  2. 当接收到复位指令DONE=1时,将KEYSTATE复位为0,并输入DO信号,用于指示其他模块执行任务;如:用于开门信号;

根据以上要求,使用JK触发器搭建该子模块,真值表如下:

KEYSTATE真值表:

KEY DONE KEYSTATE KEYSTATE*
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 1
1 1 1 1

DO真值表:

DONE KEYSTATE DO DO*
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 0
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 1

根据计算得到的逻辑关系使用74113搭建出如下电路:

keyinput_circuit

仿真结果如下所示:

keyinput_simulation

updownkey模块设计

构建完单个按键的输入电路之后利用该模块进一步构建电梯上下行选择按键输入;该模块由由八个keyinput单元构成;其输入输出如下表所示:

input output
UP1~UP4 KEYSTATE1~KEYSTATE8
DOWN2~DOWN5 DOOR`~DOOR5
CLK
FLOORA~FLOORC
U/D
ARRIVE

根据五层电梯的实际情况,一楼只有上行按钮,五楼只有下行按钮,中间三层具有上下行按钮,共八个按键输入,输出控制五层楼的轿厢外门电机,故具有五个门控制输出,八个按键状态输出。

使用74138三-八译码器将输入的所在楼层信息译成八个按键状态的控制信息,其逻辑真值表如下:

FLOORC FLOORB FLOORA Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7
0 0 0 0 1 1 1 1 1 1 1
0 0 1 1 0 1 1 1 1 1 1
0 1 0 1 1 0 1 1 1 1 1
0 1 1 1 1 1 0 1 1 1 1
1 0 0 1 1 1 1 0 1 1 1
1 0 1 1 1 1 1 1 0 1 1
1 1 0 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1 0

各个按键与输入的ARRIVE、U/D逻辑关系满足:(以Y2为例)

ARRIVE U/D Y2 DONE
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 0
1 0 0 0
1 0 1 0
1 1 0 1
1 1 1 0

该模块的输出DOOR逻辑上等于各个按键子模块输出的DO

电路如下所示:

updownkey_circuit

该模块整体仿真波形如下:

updownkey_simulation

图中以第三层的上下行按键为例,在电梯没有到达三层时按下上下行按键,可见电梯不会进行开关门动作,并且将按键状态存储。在电梯到达三层时,由于电梯运行方向为上行(U/D=1),此时只判断上行方向的按键(KEYSTATE4),进行开门动作并将按键状态复位。电梯在三层的时候若运行方向改变为下行(U/D=0),此时进行开门动作,但由于同时在三层再次按下下行键故按键的按下状态一直持续到按键松开为止而,开门动作一直持续到楼层发生变化。可见,该模块设计符合实际电梯运行的逻辑。

floorchoice模块设计

电梯轿厢内的楼层选择仍选择用上述的按键模块,电路逻辑与updownkey模块的设计类似,其中keyinput模块满足:

  1. KEYDOWN=KEY;
  2. DONE=Y’ARRIVE’。

Floorchoice模块同时控制轿厢门电机的运动:

DOOR=DO1+D2+DO3+DO4+DO5;

电路设计如下所示:

floorchoice_circuit

该模块整体仿真波形如下:

floorchoice_simulation

图中以一层与二层的按键选择为例,在电梯到达之前,根据输入将按键状态进行保存。在电梯到达相应楼层时进行开门动作并将对应按键复位。

时钟电路设计

10fenpin 模块设计

由于该电梯输入时钟频率为10kHz,故设计一个十分频电路将输入的时钟进行十分频,用于输出1Hz,10Hz,100Hz,1kHz等频率的时钟用于各个模块工作需要。使用74190十进制计数器作为分频核心模块,其逻辑真值表如下:

QD QC QB QA CO
0 0 0 0 0
0 0 0 1 0
0 0 1 0 0
0 0 1 1 0
0 1 0 0 0
0 1 0 1 1
0 1 1 0 1
0 1 1 1 1
1 0 0 0 1
1 0 0 1 1

电路设计如下所示:

10fenpin_circuit

timescale模块设计

使用上述10fenpin模块构建多频率输出的timescale模块用于提供各个模块的时钟信号。模块原理同异步计数器的设计原理,电路图如下所示:

timescale_circuit

系统决策电路设计

ENCODE_LE模块设计

由于8-三编码器74148是高位优先编码器,根据电梯上下楼层排序的需要,在下行时需要对输入进行低位优先编码,故以编码器74148为核心设计一个五-三低位优先编码器;设计原理是先将输入进行倒序处理,模块输入与74148芯片接口如下:

IN4 0N
IN3 1N
IN2 2N
IN1 3N
IN0 4N

根据上表可以对输入的低位进行优先编码,但由此导致了输出与输入的错位,使用门电路对输出进行校正,使输入IN0=1时,输出编码A2=0;A1=0;A3=0;真值表如下所示:

A2N A1N A0N A2 A1 A0
1 1 1 1 0 0
1 1 0 0 1 1
1 0 1 0 1 0
1 0 0 0 0 1
0 1 1 0 0 0

此外当外界没有输入时,A2=1,A1=1;A0=1;

电路设计如下所示:

encode_le_circuit

仿真波形如下图所示:

encode_le_simulation

nextfloor模块设计

使用上述构建的ENCODE_LF模块与高位优先编码器74148搭建电梯的核心决策模块nextfloor,该模块根据按键的输入以及当前电梯所在的楼层输出电梯即将进行的动作,输入输出列表如下:

KEYSTATE1~KEYSTATE8(上下行按键选择) OPEN(开门信号)
CHOICE1~CHOICE5(目标楼层选择) RUN(电梯运行信号)
FLOORA~FLOORC(当前电梯的位置) DIR(电梯运行方向)
CLK

使用高位优先编码器对输入的KEYSTATE以及CHOICE进行高位优先编码,输出其中的按键的最大值并使用数值比较器7485将键值与当前电梯所处的楼层进行比较决定电梯是否继续运行,设U=1表示电梯上行方向上有按键按下,且键值大于当前楼层;U=0 表示电梯上行方向没有键值大于当前楼层的按键按下;设D=1 表示电梯下行方向有键值小于当前楼层的按键按下;D=0表示电梯下行方向没有键值小于当前楼层的按键按下;电梯是否继续运行的判断值RUN应该满足RUN=U+D;

而电梯运行的方向DIR与U/D关系的真值表如下:

U D DIR DIR*
0 0 0 X
0 0 1 X
0 1 0 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 0
1 1 1 1

当U/D均为0时需要对电梯的运行方向进行进一步的判断,U/D为零一般出现在第一次按下上下行按键时出现,此时电梯位置与按键所在楼层一致且没有其他按键按下,故设UE=1表示电梯所在位置有上行方向的按键按下且没有其他按键选择;DE=1表示电梯所在位置有下行方向的按键按下且没有其他按键选择;

此时RUN=0,DIR与UE/DE的关系如下:

UE DE DIR DIR*
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 0
1 1 1 1

开门信号OPEN=RUN’DE

电路设计如下图所示:

next_floor_circuit

电机电路设计

motion模块设计

由于本课题所使用的轿厢电机设定为四线三相步进电机,故需要根据输入的运行方向以及开门信号输出相应的三相电压的变化,电机正转时运行逻辑为A-B-C-A,反转时逻辑为A-C-B-A。使用双JK触发器74113构建三进制触发器,其计数顺序为00-01-10-00。

Q2*Q1*的卡诺图如下所示:

Q2 Q1 0 1
0 01 10
1 00 XX

​ 电机控制输出的逻辑真值表如下所示:

RUN U/D Q2Q1 A B C
0 X X 0 0 0
1 0 00 1 0 0
1 0 01 0 1 0
1 0 11 0 0 1
1 1 00 1 0 0
1 1 01 0 0 1
1 1 10 0 1 0

此外根据题目要求,每两个楼层之间电机运行时间为20s,故使用十进制计数器74190与二进制计数器74161构成二十进制计数器。

电路设计如下所示:

motion_circuit

doormotor模块设计

在电梯到达目标楼层之后,电梯需要控制门电机依次执行以下动作:开门1s—停止7s—关门1s;其中在关门1s时间内根据电梯实际运行方向判断相应的按键输入,如上行时上行按键按下或者下行时下行按键按下则门重新打开,或者在门关闭时遇到障碍物也重新打开门。由分析可知,以上三种门重新打开的情况只需要归结为一个复位开门的指令给门电机控制模块即可。

由于本课题的门电机选择直流电机,故只需要输出MOTOR1/MOTOR2控制电机的正反转。使用三个74161十六进制计数器搭建900进制计数器,输入100Hz时钟信号控制。在0s时启动MOTOR1,关闭MOTOR2,此时直流电机正转,在1s时关闭MOTOR1,同时保持MOTOR2关闭,此时直流电机不转,在8s时保持MOTOR1关闭,启动MOTOR2,此时直流电机反转,9s时关闭MOTOR2,同时输出电机关门完成信号。****

电路逻辑真值表如下:

RUN Q9~Q0 MOTOR2 MOTOR1 DONE
0 XXXXXXXXXX 00 1
1 0000000000 01 0
1 0001100100 00 0
1 1100100000 10 0
1 1110000100 00 1

电机运行复位,即计数清零端CLRN’真值表如下:

RUN MOTOR2 RESET CLRN
0 X X 0
1 0 X 1
1 1 0 1
1 1 1 0

则电路设计如下图所示:

doormotor_circuit

楼层计数电路设计

100counter模块设计

根据题目要求需要对各个楼层进行运行次数计数,考虑到运行次数可能比较多,故采用100进制计数模块,该模块是由两个74190十进制计数器构成的异步计数器,电路原理图如下所示:

100counter_circuit

5counter模块设计

楼层计数时为了节省数码管显示模块的数量,故增加对计数显示的选择按键,每按下一次按键显示的目标楼层自加1,从而实现用同一个对不同楼层计数的显示。由于该课题针对5层楼的电梯设计,故计数选择也是5进制的。为了节省芯片内部模块的资源,故设计该5进制模块用于计数选择。

电路设计如下:

5counter_circuit

仿真波形如下:

5counter_simulation

floorruncount模块设计

使用上述100进制计数器搭建每个楼层的运行次数计数模块,输入输出信号列表如下:

input output
FLOORA~FLOORC FHLED-楼层计数十位显示
DONE FLLED-楼层计数个位显示
KEYINPUT CLED-按键选择楼层显示

通过三八译码器将输入楼层信号译成五个楼层的选择信号,当DONE=1时该楼层计数增加1;设计原理updownkey模块类似。电路原理如下所示:

floorruncount_circuit

排气、照明、蜂鸣器电路设计

otherdevice模块设计

将题目要求的其他附属硬件要求整合在该模块中。该模块主要实现对电梯的照明排气、蜂鸣器的控制。根据题目要求可知蜂鸣器在电梯到达目标楼层时响起提示,在本设计中设置为响0.5s,故使用三个JK触发器构建满足以下真值表条件的计数器。

DONE Q2Q1Q0 Q2Q1Q0* BEE
1 XXX 000 0
0 000 001 1
0 001 010 1
0 010 011 1
0 100 101 1
0 101 110 1
0 110 110 0

BEE为蜂鸣器的总控制标志,与输入的FLOORA~FLOORC楼层信号配合决定各个楼层蜂鸣器的状态。

电路设计如下所示:

otherwise_circuit

数码管显示电路设计

display模块设计

根据题目要求,设计该模块用于轿厢内部以及电梯门外部的楼层信息显示,显示模块由一位数码管以及两个方向显示数码管构成,考虑到各个楼层的显示信息都是一致的,故只需要设计同一个信号输出端口即可。此外考虑到在设计中000表示第一层,100表示第五层,从人性化角度上应该做出如下转换:

FLOORC~FLOORA LEDC~LEDA
000 0001
001 010
010 011
011 100
100 101

电梯运行方向的显示真值表如下:

RUN DIR UP DOWN
0 X 0 0
1 0 0 1
1 1 1 0

电路设计如下所示:

display_circuit

整机电路设计以及原理说明

整机电路设计

根据第一节的系统设计框图将各个模块根据设计逻辑连接到一起,整体电路如下图所示:

system_circuit

原理说明

由于每个模块都各司其职,在第二节的设计中经过功能仿真保证了模块的功能实现。将各个模块的输入输出口对应相连即可实现第二章需要的功能。其中时钟模块输入为10KHz,输入各个频率信号到各模块,楼层计数模块输入信号为电梯轿厢电机运行结束的跳变信号,输出跳变之后的楼层信号到其他各个需要楼层信号的模块。此外核心决策模块,nextfloor主要根据按键的情况输出决策:RUN/DIR/OPEN 控制门电机以及轿厢电机的运行。因此将这些输出端口作为相关模块的输入。

性能测试及其结果

上下行按键测试

使用1KHz 的时钟信号,设置如下输入信号:

updown_1k_test

根据实际电梯运行的逻辑,由于首先按下的是上行按钮,故电梯在一楼会先开门,然后由于在开门过程中一次接收到来自DOWN2、DOWN3、UP2、DOWN4、DOWN5、UP3、UP4 的上下行按键信号,由于这些按键按下都是在电梯处于一楼开门过程发生的,因此电梯会对这些信息按照上下行的方向进行排序。一楼为上行优先,故排序结果为UP2、UP3、UP4、DOWN5、DOWN4、DOWN3、DOWN2,这意味着电梯会一次从一楼运行到五楼,再从五楼运行到二楼停止,在这过程中每一层楼都会开门一次,而且每次开门都会有一个提示音响起。

在电梯运行结束之后,保持运行方向的数据不变,电梯内的排气以及照明关闭。逻辑运行仿真图如下所示:

updown_test_system_logic

可见整个电梯运行逻辑符合现实运行的逻辑顺序。此外由于电梯在整个过程中在二楼开门次数为2 次,故根据楼层计数显示,二楼的计数次数为2次。而在楼层次数显示的选择按钮按下之前,系统显示的是1 楼的数据,开门之后一楼的运行次数为1.选择按钮按下之后,显示跳变为二楼的次数,此时为0 次;

情景模拟测试

初始状态下电梯停靠在一楼,并且电梯门关闭。此时在2 楼有人按下上行按键打算去五楼,而在他按下之后在4 楼有人按下下行按键打算去一楼,模拟输入如下所示:

scene_test_input

根据实际的运行逻辑,电梯在一楼不开门直接上行到二楼并开门,进入到电梯之后按下五楼的选择按键,在这过程中恰好四楼有人按下下行按键。电梯开始上行到五楼,进行开门动作,之后电梯下行到四楼开门,人进去之后按下一楼运行按键,电梯运行到一楼之后开门并停止。在楼层计数方面,先不输入选择信号,此时显示的是1 楼运行次数。根据设计原理,1楼的运行次数在电梯在一楼开门之后为由0 变为1。此后保持不变。

仿真结果如下,在该输入信号之下系统可以实现符合现实逻辑的输出。

scene_test_system_logic

遇到的问题以及解决方案

模块化编程的问题

由于刚接接触QuartusII 软件的设计,对模块化设计还是比较陌生的。但由于之前用c 语言编程的时候习惯用h 文件对各个子程序进行模块设计故在开始本次电梯设计的时候便碰到如何使用该软件进行模块设计的问题。

在查阅了相关资料之后总结以下几点:

  1. 设计流程:先建立BDF 文件进行电路设计,然后点击FILE 里面的Create Symbol File 即可生成该模块;
  2. 各个模块需要功能明确,模块名称以功能命名;
  3. 每个模块都有两个文件,包括bdf 以及bsf两个文件,这样两个文件的名称一定要一致,并且在设计完成之后不可删除bdf 文件,否则模块会出错;

仿真时间的设置

一般来说系统的仿真时间默认为1ms,所以在需要进行比较长的仿真就需要对系统的仿真时间进行修改。通过查阅资料可知具体操作为:点击EDIT菜单选择EndTime,将时间修改为需要的时间即可。

输出端口的合并

在仿真的时候,如果具有很多的输出端口,便会对同步观察波形产生一定的困难。如果有一些端口,如表示楼层的三个端口,则可以将其合并显

示为10 进制的数。

操作为:选择需要合并的端口,点击右键Group,并命名即可。这样会大大缩减端口量,也便于观察。

关于Timing 跟Functional 仿真的区别

在仿真中一般选择Functional 进行仿真,有时错点为Timing 仿真之后波形图会变得出乎意料。主要原因是,Functional 仿真只是针对于功能的仿真,对时间要求不高。而Timing 仿真则是充分考虑了竞争冒险以及线延时等时间上的问题,故仿真的结果比较接近现实,更容易发现竞争冒险的问题。

关于out of block的解决方案

由于所使用的模块为CPM240T系列的芯片,该芯片限制用户最多只能使用240个block,在设计的时候通过compile的filter中的report可以查询实际使用的资源情况,包括每个模块包含的block信息等。在本次电梯设计中,由于项目比较复杂,故到后来即使出现了一些bug也不能通过编程解决。出现的问题包括:在选择楼层计数模块中原来按照100计数的模块由于该out of block的原因退而选择了40进制计数,每个子模块减少2个JK触发器。此外,该电梯在设计本身存在一个bug,也就是在关门1s内按下按键时可以恢复开门状态。但在设计的时候统一设计为按下任意门按键即可开门,无论是哪个楼层。该问题的解决方案是通过把一个或门改为相应的多个与或门即可,但由于block的限制,未能付诸实施。在本次的电梯设计中,通过多次对模块的简化,最终使用block数量为238个,使用率达99%。

关于降低block的使用率有以下几个方法:

  1. 降低IO口使用数量,由于QuartuesII本身具有很强的优化功能,故降低IO口的的使用数量可以有效的简化模块,使block使用率大幅度降低。例如原来使用200以上个block,但删除一个没必要的IO端口之后可以降低到100左右;
  2. 降低JK触发器的使用,因为每个JK触发器在计算上是一个block,因此从理论上降低一个触发器也就减少了一个block,这也是个人将计数从100进制降低到40进制的原因。
  3. 减少一些与或非门等门电路的使用,这个方法不一定凑效。因为系统本身优化的原因,有一些门电路实际上已经是被优化过了,存不存在其实没多大关系。但有一些没被简化过的,通过个人的简化可以降低block的使用。

关于按键初始状态的说明

初始设计为按键默认为低电平状态,在按下的时候出现高电平,但是由于PCB设计的原因后来改为初始状态为高电平,按下时低电平有效。PCB设计原来考虑CPLD芯片的引脚在初始状态应该为低电平,但实际为需要接入上拉电阻才能作为按键输入。否则一直保持低电平状态,并不会变为高电平。但由于设计的错误,最终只能外接上拉电阻,导致按键初始状态为高电平,按下时由于引脚接地而变为高电平。因此,在硬件固定之后只能通过改软件的设计来适应。故在本文中提及的功能不变而各个模块会出现一些出入。特此说明。

附录

设计文件中模块名称与对应的功能说明

模块名称 对应功能 备注
10fenpin.bsf 10分频电路
100counter.bsf 100进制计数器
display.bsf 轿厢以及电梯门口数码管显示
doormotor.bsf 门电机控制模块
ENCODE_LF.bsf 低位优先8-3编码器
floorchoice.bsf 轿厢内楼层选择按键输入
keyinput.bsf 按键输入模块
motion.bsf 电梯轿厢电机控制模块
otherdevice.bsf 蜂鸣器、排气、照明电路控制模块
timescale.bsf 时钟输入模块 输入1KHZ,输出10、100、1KHZ
nextfloor.bsf 电梯运行逻辑判断模块 判断是否运行、是否停层以及运行方向
updownkey.bsf 上下行按键输入模块
elevator.qpf 整机电路
floorruncount 楼层运行次数计数
5counter 5进制计数器
10counter 10进制计数器
4counter 4进制计数器

PCB制板电路原理图

整体电路原理

pcb_system

时钟电路

pcb_timer

电机电路

pcb_motor

按键输入

pcb_keyinput

数码管显示

pcb_led_num_display

楼层指示及蜂鸣器

pcb_floor_bee

PCB布线图

pcb_system_line

样板测试

pcb_demo_front

demo_test_1

demo_test_2

demo_test_3