第一篇:FPGA编程经验
整个verilog中是以module为编写基本单元的,module不宜过大,目标是实现一些基本功能即可,module的层次不宜太深,一般3-5层即可,给module划分层次原则:实现最基本功能的为底层module,然后中层是调用这些基本module,实现大的功能,最高层是系统级模块,统筹各大块之间端口连接,时序关系等。
在module内部编写中,最基本块是initial,always,以及assign块(此外还有一些UDP原语,在行为级暂且不谈),其他语句都要包含在这些块里面。这其中,initial块是不可综合语句,可以用来编写testbench,这里面的内容在程序运行时只执行一次;assign语句是在不用寄存器的情况下直接编写组合逻辑;always块是最常用的块,其语法格式是always @(*);其中括号里称为敏感列表,即对于组合逻辑而言,必须是所实现逻辑的所有输入变量,意思是当组合逻辑的每一个变量发生变化,结果立刻发生变化(这与实际情况一致,对于任何组合逻辑,输入变化,输出立刻变化)。对于时序逻辑,常为
always@(posedge/negedge clk),指在时钟上升沿/下降沿到来时,输出才根据那一时刻的输入来决定输出结果。
编程思想:
这一部分是我的心得体会,一般讲verilog的书肯定不会讲这个,因为这部分感觉的东西比较多,完全靠理解应用,没什么固定模式,呵呵,玄了点。不废话了,开始切入正题。Verilog归根到底还是编程,同时它是对电路的编程,所以就可以利用这两个特点,充分利用高级语言编程(例如C)的思想和数字电路的知识,就会很大程度上帮助你。首先牢记,编写verilog依据的是时间轴,根据时间顺序确定各种信号何时进入你的电路,可以在编写时先把几个主流信号(即贯穿于整个系统的信号,比如数据流信号)用always写出来,这些信号就是你的基准,其他控制信号根据所处的位置在介入这些主流信号,分别用 always
模块写入。这样,这种时间轴顺序跟C的编程思想就一致,在编写这种顺序性信号时,带着C的思想,基本就容易的多。同时,verilog有个很重要的电路特点,就是在每一时刻,同时会有多个电路有信号(即在运行),这样就必须从传统的顺序语言中跳出来(跳出C的思想),然后进入数字电路的思想,即你的编程要时刻跟实际电路模型联系到一起,比如A<=B,C<=A,即可以想象成两个D触发器,其中C的输入就是A的输出,这样当时钟沿到来时,两个D触发器同时运行,B的值就给了A,而A的输出就给了C,不考虑电路延时,就可以认为二者在时间轴的同一时刻运行成功,A在此时刻的值为B,C 在此时刻的值就是A前一时刻的值。这里只是举了简单的例子,但是时间轴的思路、高级语言编程思想和数字电路模型化思想以及这几个思想的转换对于编程来说帮助很大,帮你在编程时头脑时刻冷静,即使有很多信号,也会让你从全局把握整个电路,避免头脑一团糟。
关于复用:
复用对于硬件设计来说,尤为重要,在实现功能的前提下,电路比的就是主频和资源,而资源的减少思路就是复用。比如多次调用一个子函数A,如果直接写,在结构上就是这个子函数电路块A的复制,电路完成后就会看到你调用了几次A函数,你的结构中就有几个一模一样的A电路,当你的A电路本身资源很大,而且你调用的次数很多时,就很少有FPGA能装的下了。这当然跟我们的思想不符,我们只是想让整个电路中只有一块电路A,只不过把A电路在不同时刻用了几次而已,这时就要用到电路复用的思想。电路复用并不神秘,简单来讲,就是把控制端放在A电路两边,用计数器之类的东西,控制在时间轴的不同时刻把值写入A和从A输出端读取值。补充一点,对于电路的同步,计数器是一个很好的东西,因为本身计数器资源并不很大,用它来对于相差多个周期的信号进行同步,非常实用。但是,当信号相差的时间过于大,计数器的计数规模
就变的不可接受,这时就要用到状态机划分状态的方法进行同步了。有了同步,复用就变得简单的多。
关于task:
这是前段时间论坛里讨论比较热的东西。语法上说,task是比always低个等级,即task必须在always里面调用,task本身可以调用 task,但不能调用module(module的调用是与always,initial,assign语句并列的,所以在这些语句中均不能直接调用 module,只能采用给module端口送值的方法达到调用的目的)。Task有什么用呢,个人觉得,用task来封装大的逻辑语句不错,使代码显得简单明了,这个对于testbench尤为有用,但在实际电路中用处不大,因为顺序调用task对于电路来说就是电路块的复制,顺序多次调用就是多次复制电路,资源会成倍增加,不能达到电路复用的目的,同时用task封装的纯逻辑代码会使得电路的周期变大,主频降低,不利于为了提高主频而采用的大逻辑切分的方法!
第二篇:LabVIEW FPGA编程小结
LabVIEW FPGA编程小结
NI PXI-7813R为FPGA卡,板卡上引出4个端口,每个端口有40路引脚,共160路DIO,使用LabVIEW FPGA模块进行编程控制。当FPGA程序复杂度变大或是使用的DIO端口数增多时,可能面临的主要问题包括FPGA空间不够用以及实际循环时间过长等。之前编写的 FPGA程序示意图如下,采集循环与输出循环独立,均采用控件形式与RT程序通讯,两块板卡均使用了近120路DIO口。基于7813R板卡编程实践及涉及到的几个瓶颈问题,简要做了一下总结:
1)使用FIFO还是使用控件?
FPGA与RT通讯时,常用的方法是使用读写FIFO或是使用输入输出控件。这两者的特点是:
a)两者在速度上无明显差别。这是建立在不使用For循环的基础上的,但实际中FIFO通常都要配合For循环来使用,For循环相当于串行操作,当同类端口较多时,使用for将导致循环时间变长,故运行速度上FIFO并没有多少优势。b)FIFO使用合理时不丢数,而控件不能保证。
通过配置FPGA与RT中读写FIFO的超时以及FIFO大小,读写方式等手段,通常可保证FIFO传递数据不丢数(可能要经过多次尝试);而使用控件则可能会有丢数的情况。当不严格要求每次while循环都不丢数时,可考虑使用控件,例如对DO输出的配置,用户可能很久才会去配置一次,而且配置后不会要求马上生效,稍微晚几个循环周期(us级)再使配置生效也不会有很大影响,这种时候使用读取控件值是合理的。c)FIFO可使用的数据类型有限,而控件几乎无限制。
就7813R而言,FIFO只能传递指定的几种类型的数据,而使用控件时,可使用包括簇数组在内的自定义控件。
所以,还是根据实际需要来选择吧,虽然这句话跟没说一样~ 2)用不用For循环?
端口较多时,很容易就遇到连续几个都是要求采集脉宽的,而另外连续几个要求采集电平即可。这时候很自然想到使用For循环对多个端口一起进行操作,例如下图:
如上面所说,使用FOR循环相当于使端口操作(上图中所说的操作是指将采集到的布尔转成U32数值)变为串行;另外,要使用For,通常就得配合数组操作,例如上图中创建数组等,这样就更加导致循环时间变长。当发现循环时间不满足使用要求时,这种处理方法可能就不能使用了,每一路单独处理就省掉了创建数组及For,节省了循环时间,但这样又使重复代码变多,工作量加大。
3)怎么使用子VI?
输出脉冲时,脉冲的产生可以封装成一个子VI,供多路端口进行使用;采集脉宽时,脉宽采集可以封装成一个子VI供多路端口进行调用。然而,默认情况下,子VI的执行是串行的(因为并没有设置VI属性为“可重入执行”),子VI在同一时间内只能被一路端口所占用,可能导致的结果是循环时间变长,精度降低。如果设置子VI为可重入执行,又可能导致FPGA空间占用率过高,编译无法通过。我想到的一种折中的办法是:使用几个程序框图一样的子VI(功能完全一样,将子VI多另存为几个所生成)来代替原先一个子VI,替换之后,相当于减少了串行运行的子VI数量,循环用时减少明显。下图中使用6个子VI A,如果用2个B与2个C替换其中的4个A,循环时间可能减少为原来的1/3。
While循环方式1:子VI A子VI A子VI A子VI A子VI A子VI AWhile循环方式2:子VI A子VI A子VI B子VI B子VI C子VI C
4)精打细算
这一点可能只会在FPGA空间不够用时才会被重视,下图是逻辑片不够用时导致的FPGA编译失败错误:
因此,当资源有限时,尽量使用能满足使用要求的最小长度的数据类型来实现,能使用U16满足要求的坚决不用U32!另一方面,暂时还没有发现数据类型变长时对FPGA循环运行时间产生明显影响。
5)循环延时考虑
脉冲输出及采集均需要根据实际循环时间来计算,若参与运算的值不是实际的循环时间,输出或采集的结果自然不会准确。例如可配置脉冲或电平输出的端口,若输出电平,其算法简单,所需时间较少,而配置为脉冲输出时,算法复杂。配置为单路脉冲输出可能不会有明显的影响循环时间,但当多路脉冲一起输出时,可能影响到循环时间增加1~2us甚至更长。故实际配置循环时间时,需按照可能的最复杂算法进行运行测试,并依此来设置循环时间,以保证循环时间的确定性已经算法运算的正确性。
总而言之,设计时还是应该根据实际需要,综合考虑数据完整性、FPGA板卡资源大小、循环时间等因素,已达到满意效果。
第三篇:编程经验
1.当性能遇到问题时,如果能在应用层进行计算和处理,那就把它从数据库层拿出来。排
序和分组就是典型的例子。在应用层做性能提升总是要比在数据库层容易的多。就像对于MySQL,sqlite更容易掌控。
2.关于并行计算,如果能避免就尽量避免。如果无法避免,记住,能力越大,责任越大。
如果有可能,尽量避免直接对线程操作。尽可能在更高的抽象层上操作。例如,在iOS中,GCD,分发和队列操作是你的好朋友。人类的大脑没有被设计成用来分析那些无穷临时状态——这是我的惨痛教训所得。
3.尽可能简化状态,尽可能局部本地化,适用至上。
4.短小可组合的方法是你的好朋友。
5.代码注释是危险的,因为它们很容易更新不及时或给人误导,但这不能成为不写注释的理由。不要注释鸡毛蒜皮的事情,但如果需要,在某些特殊地方,战略性的长篇注释是需要的。你的记忆会背叛你,也许会在明天早上,也许会在一杯咖啡后。
6.如果你认为一个用例场景也许“不会有问题吧”,它也许就是一个月后让你在发布的产品
中遭受惨痛失败的地方。做一个怀疑主义者,测试,验证。
7.有疑问时,和团队中所有相关人交流。
8.做正确的事情——你通常会知道这指的是什么。
9.你的用户并不傻,他们只是没有耐心理解你的捷径。
10.如果一个开发人员没有被安排长期的维护你们开发的系统,对他保持警惕。80%的血、汗、泪水都是在软件发布后的时间里流的——那时你会变成一个厌世者,但也是更聪明的“行家”。
11.任务清单是你的好朋友。
12.主动让你的工作更有乐趣,有时这需要你付出努力。
13.悄无声息的崩溃,我仍然会为此从噩梦中惊醒。监控,日志,警报。清楚各种的假警报
和不可避免的感觉钝化。保持你的系统对故障的敏感和及时警报。
14.复杂是大敌。
第四篇:基于VHDL编程FPGA的地铁自动售票机
地铁自动售票机
一、设计要求
1、功能描述
用于模仿地铁售票自动售票,完成地铁售票的核心控制功能。
2、功能要求
售票机有两个进币孔,一个是输入硬币,识别的范围是一元硬币;一个是纸币,识别的范围是一元、两元、五元、十元、二十元。乘客可以连续多次投入钱币。乘客 一次只能选择一个出站口,购买车票时,乘客先选出站口,有六个出站口可供选择,再选择所需的票数,然后投币,投入的钱币达到或者超过所需金额时,售票机自 动出票,并找零。本次交易结束后,等待下一次交易。在选择出站口、所需票数以及在投币期间,乘客可以按取消键取消操作,钱币自动退出。
二、实验分析
1、买票时,乘客按下开始键,售票机进入站台选择程序,乘客选择出站口后,可以按取消键重新选择,否则售票机自动进入票数选择程序,同样这时可以按下取消键重新开始选择出站口以及票数。
2、当选择好出站口以及所需票数时,乘客可以投硬币或者用纸币,当所投的钱币总额大于或者等于票价时,售票机自动出票以及找零。期间,可以按下取消键重新开始选择,并退出所有的钱币。
3、乘客若还没选择出站口或者票数,就投币或者使用纸币,售票机会自动退出所有的钱币。
4、有六个站台可供乘客选择,每个乘客最多可以买3张票,六个站台编号为1到6,票价从2元依次递增到7。
三、系统流程图
四、程序源代码 LIBRARY IEEE;USE IEEE.std_logic_1164.ALL;USE IEEE.std_logic_arith.ALL;USE IEEE.std_logic_unsigned.ALL;ENTITY metrosell IS PORT(clk:in std_logic;startselect:in std_logic;sure:in std_logic;save your forward step(s)coin1y:in std_logic;pmoney1y:in std_logic;pmoney2y:in std_logic;pmoney5y:in std_logic;pmoney10y:in std_logic;money pmoney20y:in std_logic;money cancel:in std_logic;number:in std_logic_vector(3 downto 0);the tickets platform:in std_logic_vector(3 downto 0);want to reach moneystorage:out std_logic;acceptmo:out std_logic;stamp:out std_logic;--set the clock signal--start to select the platform--this button is to--1 yuan coin
--1 yuan paper money--2 yuan paper money--5 yuan paper money--10 yuan paper--20 yuan paper--cancel the forward step(s)--choose the number of--choose the platform you--to store the money--accept the money--stamp outgate charge:out std_logic_vector(3 downto 0);--the mount of charge,up to 15 yuan chargegate:out std_logic--charge outgate);END metrosell;ARCHITECTURE sell OF metrosell IS type state_type is(initial_type,selectp_type,selectnum_type,insert_type,stamp_type,charge_type);--define six types signal state:state_type;--define a shared state BEGIN main:process(clk,state,startselect,platform,number,coin1y,pmoney1y,pmoney2y,pmoney5y,pmoney10y,pmoney20y,cancel,sure)variable univalence :integer range 0 to 7;--the univalence of the ticket variable total_money :integer range 0 to 21;--the price of the ticket(s)variable selectp_alr:std_logic;--the flag of select platform type variable selectnum_alr:std_logic;--the flag of select number type variable stamp_alr:std_logic;--the flag of the stamp gate variable charge_alr:std_logic;--the flag of the charge gate variable money_reg:integer range 0 to 21;--the mount of money put in variable coin1y_f:std_logic;--the flag of one yuan coin variable pmoney1y_f:std_logic;--the flag of one yuan paper money variable pmoney2y_f:std_logic;--the flag of two yuan paper money variable pmoney10y_f:std_logic;--the flag of ten yuan paper money variable pmoney20y_f:std_logic;--the flag of twelve yuan paper money variable pmoney5y_f:std_logic;--the flag of five yuan paper money variable charge_reg:integer range 0 to 15;
begin if(rising_edge(clk))then case state is when initial_type => variables univalence:=0;selectp_alr:='0';selectnum_alr:='0';stamp_alr:='0';charge_alr:='0';money_reg:=0;total_money:=0;coin1y_f:='0';pmoney1y_f:='0';pmoney2y_f:='0';pmoney5y_f:='0';
--the register of charge--initialize some pmoney10y_f:='0';pmoney20y_f:='0';moneystorage<='0';stamp<='0';charge_reg:=0;charge<=“0000”;acceptmo<='0';chargegate<='0';if(startselect='1')then state<=selectp_type;end if;when selectp_type => if(selectp_alr='0'and cancel='0')then--choose the platform if(platform=“0001”)then univalence:=2;selectp_alr:='1';elsif(platform=“0010”)then univalence:=3;selectp_alr:='1';elsif(platform=“0011”)then univalence:=4;selectp_alr:='1';elsif(platform=“0100”)then univalence:=5;selectp_alr:='1';elsif(platform=“0101”)then univalence:=6;selectp_alr:='1';elsif(platform=“0110”)then univalence:=7;selectp_alr:='1';elsif(platform=“0000”)then univalence:=0;selectp_alr:='0';else null;end if;elsif(selectp_alr='1'and cancel='1')then state<=initial_type;elsif(selectp_alr='1'and sure='1')then state<=selectnum_type;end if;when selectnum_type =>--you can buy at most 3 tickets if(selectnum_alr='0'and cancel='0')then--choose the number of tickets if(number=“0001”)then if(univalence=2)then total_money:=2;selectnum_alr:='1';elsif(univalence=3)then total_money:=3;selectnum_alr:='1';elsif(univalence=4)then total_money:=4;selectnum_alr:='1';elsif(univalence=5)then total_money:=5;selectnum_alr:='1';elsif(univalence=6)then total_money:=6;selectnum_alr:='1';elsif(univalence=7)then total_money:=7;selectnum_alr:='1';elsif(univalence=0)then total_money:=0;selectnum_alr:='0';else null;end if;end if;
if(number=“0010”)then if(univalence=2)then total_money:=4;selectnum_alr:='1';elsif(univalence=3)then total_money:=6;selectnum_alr:='1';elsif(univalence=4)then total_money:=8;selectnum_alr:='1';elsif(univalence=5)then total_money:=10;selectnum_alr:='1';elsif(univalence=6)then total_money:=12;selectnum_alr:='1';elsif(univalence=7)then total_money:=14;selectnum_alr:='1';elsif(univalence=0)then total_money:=0;selectnum_alr:='0';else null;end if;end if;if(number=“0011”)then if(univalence=2)then total_money:=6;selectnum_alr:='1';elsif(univalence=3)then total_money:=9;selectnum_alr:='1';elsif(univalence=4)then total_money:=12;selectnum_alr:='1';elsif(univalence=5)then total_money:=15;selectnum_alr:='1';elsif(univalence=6)then total_money:=18;selectnum_alr:='1';elsif(univalence=7)then total_money:=21;selectnum_alr:='1';elsif(univalence=0)then total_money:=0;selectnum_alr:='0';else null;end if;end if;elsif(selectnum_alr='1'and cancel='1')then state<=initial_type;elsif(selectnum_alr='1'and sure='1')then state<=insert_type;end if;when insert_type => moneystorage<='1';if(money_reg
when 2 => charge<=“0010”;when 3 => charge<=“0011”;when 4 => charge<=“0100”;when 5 => charge<=“0101”;when 6 => charge<=“0110”;when 7 => charge<=“0111”;when 8 => charge<=“1000”;
end case;end if;
when 9 => charge<=“1001”;when 10 => charge<=“1010”;when 11 => charge<=“1011”;when 12 => charge<=“1100”;when 13 => charge<=“1101”;when 14 => charge<=“1110”;when 15 => charge<=“1111”;when others => charge<=“0000”;end case;if(charge_reg>0 and charge_alr='0')then chargegate<='1';charge_alr:='1';elsif(charge_reg=0 and charge_alr='0')then chargegate<='0';charge_alr:='1';else state<=initial_type;end if;end process main;END sell;
五、波形仿真
1、乘客按下开始按钮,进入选站台模式,选择二号站台,按下确定键,再选择票数为2张,按下确定键,售票机钱箱关闭,投入一张两元和五元纸币(对顺序没有要求),此时钱币总额大于票价,出两张票并找零一元。之后系统进入初始化状态。具体仿真如图 1 仿真1
图 1 仿真1
2、测试cancel键,当乘客按正确的操作完成选站台时,按下取消键,再重新选择,如图 2 cancel仿真,仿真波形如下。
图 2 cancel仿真
3、还是测试cancel键,当乘客选择好票数时,按下cancel键,然后重新选择两张单价为七块钱的六号站台票,投入一张20元和5元,找零六元。仿真波形如图 3 cancel仿真2
图 3 cancel仿真2
4、乘客选择五号站台,两张票,然后先后投入一元纸币,两元纸币,一元纸币,五元纸币,然后按下取消键,售票机自动放出所有的钱币。仿真如图 4 cancel仿真3。
图 4 cancel仿真3
六、心得体会
在我的设计中,有一个moneystorage信号量用于控制储存钱币箱的开与关,这个设计主要考虑到当乘客要求退币时,最好不是从售票机中取出投入的钱数,然后退还,设置了这个开关,就可以在按下取消键时,直接从储存钱币箱中退出钱币。
还有,乘客选择的站台以及票数,在售票机内部会自动将这两个信号传给出票系统,从而自动出票,以上写的程序只是让系统知道怎样收钱以及找零。
这次实验总体上来说比六人抢答器简单,但是因为这个售票机完全是自己写的,所以也不是想象中的那么简单。这也让我看出,要完全自己去做一件东西不是简单的,特别是要考虑很全面,还是要发一些时间的。
第五篇:PLC编程经验详谈
PLC编程经验详谈
(晴天)2009-3-17 13:31:00
------------------
PLC程序调试步骤
人的脑力是有限的,并且记事情也有时间性。过了N天就会忘记每次修改的原因,为什么要加这条指令,为什么要删除这个网络,让自己以后看自己以前编写的程序时都会很困惑。做到以下步骤,对所有程序理解与修改会有很大帮助的。
1、把原有程序另存一个, 在另存的程序上作修改。文件命名一个主要的程序名称,标注第几次修改,并加上修改的日期,最好是在文件名外加上简要的修改标题。例如: 《 捆扎程序5(06.10.23翻板步进电机加条件)》
2、用.doc文件记录修改的年月日。
3、在日期下面记录修改程序的步骤,增加或是删除了哪些指令等。并在程序的编辑条注释中做记录,以备下次修改。
4、在.doc文件中详细记录修改程序的原因,所出现的故障现象是什么,故障是如何排除的。
5、在.doc文件中标注修改后所现用的程序全名,包括日期与简要的修改标题。
6、把过时与现用的程序用,过时文件夹与现用文件夹分开整理,按日期排列。
这样每次所作的修改就有了详细的档案,便于以后的程序修改。现用的程序是标有最近日期的程序。
这样的工作步骤同时也适用于电气图纸的修改
PLC编程经验
弄通有关PLC程序设计理论是重要的。没有这方面的理论准备或指导,仅靠在实践中摸索,简单的问题还好办。复杂的就不好办了。不仅无从下手,而且花了很多时间与精力,也难编出效率较高、质量也较高的程序,常常是事倍功半。
但是,编程的具体实践,以及在这个实践中得来的知识或技能,即经验,也是重要的。没有经验,仅有理论,既无法深刻理解理论,又无法灵活应用理论。这正如学数学,如仅了解一些定理或记住一些公式,没有作相应的练习,肯定是学不好的。更不用说,任何理论也都只是经验的总结,归根到底也都有是来自实践。
1、经验积累
经验有别人的,也有自己的,都很重要。前者要靠细心学习,后者要靠用心积累,都要在一定的时间与必要的精力。
别人的经验有上了书的或登载在杂志上的。有的是细心学习别人的,但多数是我自己的经验。所有的例子都经我测试过,都经实践证明是可行的。我想,别的书本或杂志上介绍的也会是这样的。所以学习这样杨功的经验是必要的。
还有就是你同事的经验,也是值得学习。这种经验离你很“近”,很易借鉴。
自己的经验则是最重要的。要在自己的实践中,积累自己的经验。同时,最好在学别人的经验时,也能亲自作些测试,能使自己也有类似的经历,进而把这些经验变成自己的。这也是自己经验的重要积累。
还有一些失败的经验,这往往是不会公开的,但这些经验也要学习,也要积累。
经验的积累要用自己的脑记,更要用电脑记。最好作些分类,建立一个自用的程序库,以便于随时引用。
2、经验升华
经验还有待升华。升华有三个层次:
最低的层次就是建立一个典型的程序库,供今后再用。若程序复杂,还可建一些功能块,或子程序,以便以后引用。
其次,要总结出有效算法。如单按钮起停程序库等。
最高层次的升华是把经验上升到理论的高度,为丰富PLC程序设计理论作贡献。我想,随着PLC使用的普及与提高,是会有越来越多从经验中升华出来的,而又能用以指导实践的PLC编程理论的。
3、经验应用
经验积累、经验升华都是为了应用。经验应用有三方面:
1)用作工程设计模板。设计新系统时,选用一个或几个与现设计工程类似的,已取得成功的工程,作样板进行设计。这既可减轻设计的工作量,又增加设计的成功率。这也是信息可重用的一大好处。
2)用作程序设计参考。在无成功的工程可作样板时,在新设计的逻辑中,仍有相当一部分控制逻辑,可采用或借用已有典型逻辑,这也可减少设计的工作量,增加设计的成功率。
3)用作算法设计参考。在既无样板可参照,又无典型可采用时,还可运用过去的一些成功的算法。
经验是宝贵的,但是经验特别是个人经验,总是有限的。所以,经验的应用也还要与编程理论相结合PLC现场工程师工作指南
一、出发前的准备
从事PLC的技术支持的人,如果是要到现场开始进行系统调试,无论是对OEM客户,还是对一个过程控制的系统集成,都要在事先做好一些准备工作。就像一个“驴友”出行前,要更换自己的服装尤其是鞋子,带好水、食品,还要准备在野外的一些防身用品,如果是过夜的话,还要有帐篷、手电筒等一样,作为一个职业的PLC技术支持工程师,也有不少的东西是要准备的。
首先要安排自己的行程计划和衣食住行。如果是需要住宿的话,那么如何定机票、酒店(旅馆、招待所),这里就不多说了。如果时间很长(如超过一个月),为了省钱,就要考虑在当地租房子了,尤其是出发的是一个小组,而不是一个人的时候。衣食住行,这些问题与普通的旅行是一样的,虽然这些问题对你完成任务的影响力并不亚于你的专业水平。想
象一下,你到了现场,因为食物中毒导致一个星期拉痢疾的情况会对工作造成什么样的影响,就知道该准备那些东西了。通常,有经验的自动化公司的行政部门会为工程师考虑好这些情况,但是,作为工程师自己一定要进行确认,看看是否所有的事情都已经安排好了。
安顿好了衣食住行的后,要准备自己的工具。作为PLC的现场调试工程师,并不需要很多的调试工具。但是,一个螺丝刀、一台万用表,还是必备的。另外,如果要与现场的仪表传感器进行系统联调的时候,还要有一台信号发生器来模拟现场仪表的信号,以确定当发生问题时,现场的信号是完好的。还有,一台结实的手提电脑,是你编程和调试的必需的工具。虽然这些工具你可以要求用户准备好,但是,作为一个职业的PLC工程师,如果连这几样工具都没有,会被用户怀疑你的职业水平的。其它的一些仪器仪表,如果需要的话,你可以向公司或者客户提出来,让他们提前准备,比如,示波器、稳压电源等等。毕竟这些不那么通用的仪器,通常是不可能随身携带或备用的。
有一些常被忽视的小东西,你准备了之后一定有用的。如,电气胶带、热缩套管、打火机(你吸烟的话自然会有,没有别人也会有),束线带、还有,如果现场接线已经完成了,要准备好一些与信号线相同的电缆,和一些固定基座的螺丝。你可能怀疑要这些做什么用,相信我,带上这些,虽然有些只值几分钱,但到了现场后,可能会节约你一天甚至几天的时间,尤其是你去的地方是在一个偏远的山区的时候。虽然在发货的时候厂家都有螺丝钉,但是到了现场什么都有可能发生,如果螺丝钉不够(而这是每次都必然发生的),会引起许多问题。
除了以上的东西,就是这次调试所要带的备品备件了。虽然现场的货物清单可能会已经考虑了备品备件的问题,但为了应付万一的情况,有些备件你最好还是自己要随身携带。首先是PLC的基板(有的成为机架)、电源、CPU模块,因为这些是一台PLC能够工作的基础,如果现场只有一套系统,那么这些模块就只有一个,假如没有备分的话,一旦出现故障,你的所有的工作都必须停下来。因此最好带上一套。
其它的I/O模块和通讯模块,如果现场只有一个的,你都要考虑在多带一个。对于那些现场已经有两块以上的模块,你就不用考虑自己带了。
二、设计交底工作
如果系统设计不是你自己做的,那么在出发前,就要与系统的设计人员进行充分的沟通,对于不清楚和不明白的地方,一定要弄清楚,确保自己清晰地理解了要完成的工作目标,和设计者的意图。不要轻易否定设计者的方案,也不要轻易地说别人那里设计得不行。
但是,因为你是从事现场的工程师,因此,也不必过于迷信设计者。你可以提出自己的建议。比如,PLC的机架和CPU模块和I/O模块的搭配原则,可能有时候,设计师不知道你所用的 PLC的机架有4槽、6槽和8槽,甚至12槽的,因此,也许全部都选了8槽的,而导致了几个槽的空缺,你可以建议它修改为4槽或6槽的。
方案设计中,最容易出问题的地方是通讯,现场调试最麻烦的地方也是通讯,所以对于通讯的部分,你必须清晰了解系统的框架结构,并且对需要进行通讯的东西在出发前就要全部进行一遍调试,而且要确认其中的所有需要通讯的模块是可以通讯的。比如,操作台电脑、触摸屏、PLC、变频器、其它的PLC、一些智能仪表和仪器,如果这些东西需要通讯的话,你必须要确认它们相互之间是可以通讯的,如果你不确认的话,就要与厂家联络,并亲自再试一次。如果PLC的节点数较多,要考虑距离和厂家CPU的限制。
如果系统较大,远程单元、本地机架数量、每个机架的模块数量的限制,并非出于系统功能和技术上的限制,而是由于使用规范性的限制。在系统硬件组态时,要考虑这些模块的搭配作用。
对于电源模块的配置,一个资深的工程师应该能够做出比较合理的搭配。例如,电源模块通常有5A和10A的分别,如果模块较少,可以选用功率小的电源模块,如果模块较多,则应该选用大功率的电源模块。而一般,如果现场仪表需要PLC也供应24V直流电源而不是采用外部电源供电(如RTU)的情景,通常CPU所在的机架上选用大功率的电源比较合理。
此外,在I/O模块的安装时,根据不同的系统,通常同型号的模块放置在一起。但是,如果对于输出模块与输入模块形成回路的,则可以将一个回路的参量所涉及的模块放置在一个机架上(或一个CPU所控制的机架上)比较合理。有的设计师在设计的时候不会考虑这一点,你可以调整过来。
在选型的时候,因为各种PLC都有大型、中型、小型的分别,这些分别主要是由CPU模块的性能不同造成的。在实际上,并非一定大型的功能就是合适的。除了价格方面的考量之外,主要是,如果控制点数不多,小型的CPU模块完全可以胜任,则小型的CPU反而比大型的CPU模块工作还要可靠一些。因为,小型的CPU所涉及的资源少,而大型CPU的资源多,在程序执行中,为处理那些程序不需用到的资源时,也要分配时间去处理,这样不仅造成资源的浪费,可能在程序处理上不及小型CPU可以更单纯和稳定地工作。
在设计交底的过程中要指出的是,对于设计中的任何变更,你只能提建议,而不是擅自做修改。因为,你的职责是按照设计施工,而不是设计,因此,对于任何你发现的不合理的东西,你可以提出意见,但必须要等到设计变更确认书下到你手里后,你才能按照变更后的设计工作,尽管这个变更可能是你的意见。还有,即使最初的设计也是你做的,你在变更后,也要通知客户,并取得客户的书面同意。
三、装机步骤
到了现场后,进行系统安装前,需要考虑安装环境是否满足PLC的使用环境要求,这一点可以参考各类产品的使用手册。但无论什么PLC,不都能装设在下列场所:含有腐蚀性气体之场所,阳光直接照射到的地方,温度上下值在短时间内变化急遽的地方,油、水、化学物质容易侵入的地方,有大量灰尘的地方,振动大且会造成安装件移位的地方。
如果必须要在上面的环境使用,则要为PLC制作合适的控制箱,采用规范和必要的防护措施。如果需要在野外极低温度下使用,可以使用有加热功能的控制箱。如何做这些防护箱或控制箱,各制造商和和资格的系统集成商将会为客户提供相应的供应和设计。
在使用控制箱时,在控制箱内OpenPLC安装的位置要注意如下事项:控制箱内空气流通是否顺畅(各装置间须保持适当的距离),变压器、马达控制器、变频器等是否与PLC保持适当距离,动力线与信号控制线是否分离配置,组件装设之位置是否利于日后之检修,是否需预留空间,供日后系统扩充使用。
除了上述注意事项之外,还有其它注意事项要留意。
首先比较重要的是静电的隔离。静电是无形的杀手,但可能因为不会对人造成生命危险,所以许多人常常忽视它。在中国的北方、干燥的场所,人体身上的静电都是造成静电损坏电子组件的因素。虽然你被静电打到的话,只不过是轻微的酥麻,但这对PLC和其它任何电子器件就足以致命了。
要避免静电的冲击有下列三种方式:在进行维修或更换组件时,请先碰触接地的金属,以去除身上的静电;不要碰触电路板上的接头或是IC接脚;电子组件不使用时,请用有隔离静电的包装物,将组件放置在里面。想象PLC里的元器件是一个娇嫩的婴儿,而那些静电会导致这个婴儿死亡,你就会更容易以正确的态度对待这个问题了。
基座安装(RACK)时,在决定控制箱内各种控制组件及线槽位置后,要依照图纸所示尺寸,标定孔位,钻孔后将固定螺丝旋紧到基座牢固为止。在装上电源供应模块前,必须同时注意电源线上的接地端有无与金属机壳连结,若无则须接上。接地不好的话,会导致一系列的问题,静电、浪涌、外干扰,等等。由于不接地,往往PLC也能够工作,因此,不少经验不足的工程师就误以为接地不那么重要了。这就像登山的时候,没有系上保护缆绳一样,虽然你正常前进的时候,保护缆绳没有任何作用,但一旦你失足的时候,没有那根绳子,你的生命就完结了。PLC的接地,就相当于给PLC系上保护缆绳。
在I/O模块安装时,须注意如下事项:I/O模块插入机架上的槽位前,要先确认模块是否为自己所预先设计的模块;I/O模块在插入机架上的导槽时,务必插到底,以确保各接触点是紧密结合的;模块固定螺丝务必锁紧;接线端子排插入后,其上下螺丝必须旋紧。由于现场的变压器、电机等影响,多少会有振动,如果这些螺丝钉松动了,会导致模块从机架中松开