Python 3.3 及以上版本自带 venv 模块,可以直接使用。
在你的项目目录下,运行以下命令来创建一个虚拟环境,这将在项目目录下创建一个名为 myenv 的文件夹,其中包含虚拟环境的所有文件:
python -m venv myenv
Windows:
myenv\Scripts\activate
macOS 和 Linux:
source myenv/bin/activate
在虚拟环境中,你可以使用 pip 来安装项目所需的库:
pip install requests
安装的库将只会影响当前虚拟环境,而不会影响系统的 Python 环境或其他项目。
为了确保你的项目依赖可以在其他环境中重现,你可以使用以下命令将当前环境的依赖写入 requirements.txt 文件:
pip freeze > requirements.txt
requirements.txt 文件将包含所有当前环境中的安装包及其版本信息。
在新的环境中,你可以使用 requirements.txt 文件来安装所需的所有依赖:
pip install -r requirements.txt
当你完成工作时,可以通过以下命令退出虚拟环境:
deactivate
使用虚拟环境进行Python开发可以有效地隔离项目依赖,避免版本冲突。通过创建和激活虚拟环境、安装依赖、冻结依赖并在新环境中重新安装依赖,可以确保你的项目在不同环境中具有一致的运行表现。
]]>下面举一个例子说明:
{attribute 'qualified_only'} // 必须先写类型名称再写属性名称 (例如 eColor.Red)
// {attribute 'strict'} //取消 'strict' 以允许转换 UDINT 数据类型
{attribute 'to_string'} // 运行字符串转换 (例如 TO_STRING(eColor.Red) = 'Red')
TYPE eColor :
(
Red := 16#FFFF0000,
Green := 16#FF00FF00,
Blue := 16#FF0000FF
Yellow := 16#FFFFFF00,
) UDINT; // 声明 UDINT 作为 int 整形类型
END_TYPE
// 定义一些变量
ColorVar1 : eColor;
ColorVar2 : eColor;
ColorName : STRING;
ColorValue : UDINT;
ColorVar1 := eColor.Green; // ColorVar1 = 16#FF00FF00
ColorName := TO_STRING(ColorVar1); // ColorName = 'Green';
ColorValue := TO_UDINT(ColorVar1); // ColorValue = 16#FF00FF00
ColorVar2 := 16#FF00FF00; // ColorVar2.Green
ColorName := TO_STRING(ColorVar2); // ColorName = 'Green';
ColorValue := TO_UDINT(ColorVar2); // ColorValue = 16#FF00FF00
ColorVar1 := ColorVar2 OR eColor.Red; // 按位相与得到 Yellow=16#FFFFFF00
ColorName := TO_STRING(ColorVar1); // ColorName = 'Yellow';
ColorValue := TO_UDINT(ColorVar1); // ColorValue = 16#FFFFFF00
以上示例列举了常用的 enum 类型可进行的数据交互方式。
eColor.Green
可以获取enum类型属性的值,并可以赋值给其他对应 enum 实例TO_STRING(ColorVar1)
可以转换获取 enum 实例当前值对应属性名称字符串
下载时出现此报警,原因是 task 任务中对 gou 的排序有问题,放在前面的 pou 中使用了后面 pou 才设定好的数据,需要重新排列 task 任务序列:
mc_power
mc_jog
等控制轴的功能块,一运行就报错 SMC_FB_CALLED_FROM_WRONG_TASK,可能是不同的 pou 放在了多个 task 任务中,循环中内部有了冲突,将所有的 pou 放在同一个 task 中就可以解决问题。
主要步骤为:
首先需要配置工控机啊 BIOS 设置,将一些超线程,电源管理等选项关掉:
关闭BIOS 中激活的所有节能选项
停用可能导致系统管理中断的所有内容
然后就可以安装 RTE,官网下载需要的 runtime 安装包,注意区分 x86 还是 x64 设备。我下载的是 **CODESYS Control RTE SL (×86Windows 实时)。
官网下载地址:http://store.codesys.cn/codesys/store/index.html
在工控机上解压并安装需要的 RTE runtime,基本都是直接下一步即可,期间注意选择带不带 softmotion:
Control RTE 文件路径:C:\Program Files\CODESYS\CODESYS Control RTE3
Control RTE 安装路径:C:\ProgramData\CODESYS\CODESYSControlRTEV3
支持的网卡:
Systems with Windows and CODESYS Control RTE (Real-time SoftPLC):
一般情况下 intel 的千兆网卡都可以安装 CmpEt1000Drv 驱动。
首先进入设备管理器,选择需要更新 codesys 驱动的网卡,右键选择更新驱动:
选择从本地查找驱动程序:
选择从磁盘安装,从 RTE 文件路径找到对应的驱动目录并安装:
右键选择 plc configuration:
在 components manager 中在最后一个空行中填入安装的驱动名称,这里我填的是 CmpEt1000Drv:
确定并重启 plc 即可完成网卡驱动的安装及配置。
在codesys 开发项目中进行以下操作。
以上就是 RTE runtime 版添加 ethercat master 主站的简单方法。
相关系统变量:
sinumerik one 及 840D sl 系统以上参数默认值为 1000,828D 系统默认值为 1000000。
]]>%f
默认小数位数 6 位,但实际只想显示 3 位小数,此时就需要将界面变量的占位符进行设置以满足需求。语法:
% <标记> <最小显示数字个数> <类型>
-
当定义最小显示数字个数时 居左显示,+
显示数据正负号,0
当定义最小显示数字个数时空缺位显示 0d
十进制, b
二进制, o
八进制, x
十六进制示例:
%-5d:最小显示位数5位,且居左对齐显示,例如数据值为123时:`123 `
%+d:显示数据正负号,例如数据值为123时:`+123`
%05d:最小显示位数5位,且空缺位显示0,例如数据值为234时:`00234`
%08b:显示8位数的二进制模式,例如数据值为255时:`11111111`
%04x:显示4位数的十六进制模式,例如数据值为15时:`000f`
语法:
% <标记> <最小显示数字个数> . <精度> f
-
当定义最小显示数字个数时 居左显示,+
显示数据正负号,0
当定义最小显示数字个数时空缺位显示 0%1.6f
示例:
%-12.9f:显示12位数字 9位小数,且居左显示
%+6.3f:显示6位数字3位小数,且显示正负号标记
%06.3f:显示6位数字3位小数,且空缺位补0显示
语法:
%t[ <text> <time in unit> <text> ]
示例:
// 定义一个时间变量并给其赋值
ltTimeSpan : LTIME := LTIME#1D2H3M4S5MS6US7NS;
在一个 label 中定义:
text variable 设置:PLC_PRG.ltTimeSpan
text 占位符设置:Time span: %t[d] d
输出结果:Time span: 1 d
可用的占位符:%t[d]
天,%t[dd]
两位数字的天,%t[H]
小时,%t[HH]
两位数字小时,%t[m]
分钟,%t[mm]
两位数分钟,%t[s]
秒,%t[ss]
两位数秒。
也可以组合起来使用:
TEXT 占位符设置:%t[Value: dd-HH:mm:ss:ms:us:ns]
输出结果:Value: 01-02:03:04:005:006:007
如果不定义 label 的 text variable 属性,则会输出系统当前时间。
语法:
%t[ <date and time unit> ]
和时间类型类似的用法,下面举例说明:
//定义一个 date 类型变量
dateBy : DATE := DATE#2021-02-12;
在一个 label 中定义:
text variable 设置:PLC_PRG.dateBy
text 占位符设置:Date: %t[yyyy-MM-dd dddd]
输出结果:Date: 2/12/2021 Friday
可用占位符:%t[yyyy] 年,%t[yy] 两位数年,%t[y]一位数年,%t[MMMM] 英文月份,%t[MMM]英文简写月份,%t[MM]月份,%t[ddddd] 一周的第几天,%t[dddd]英文周几,%t[dd]一个月的第几天,%t[jjj]一年中的第几天,
如果不定义 label 的 text variable 属性,则会输出系统当前日期。
语法:
%s
注意 PERSISTENT 类型变量必须定义在单独的 Persistent Variables 类型 object 才能生效。而不是通常的 GVL object。
RETAIN 可以在热重启后保持数据:
In a POU:
VAR RETAIN
iRem1 : INT;
END_VAR
*******************
In a GVL:
VAR_GLOBAL RETAIN
gvarRem1 : INT;
END_VAR
以下情况下 RETAIN 数据会被重置:
首先需要新建 Persistent Variables 类型 object 会放在 task 子目录下:
然后会自动创建 VAR_GLOBAL PERSISTENT RETAIN 类型全局变量文件。
PERSISTENT 可以在热重启和冷重启后保持数据:
VAR_GLOBAL PERSISTENT
iVarPers1 : DINT;
bVarPers : BOOL;
PLC_PRG.PERS: INT;
END_VAR
以下情况下 PERSISTENT 数据会被重置:
从 CODESYS V3.3.0.1 开始声明一个 VAR_GLOBAL PERSISTENT
等效于 VAR_GLOBAL PERSISTENT RETAIN
or VAR_GLOBAL RETAIN PERSISTENT
。
以下是各种变量定义模式下数据保持情况:
after online command | VAR | VAR RETAIN | VAR PERSISTENT |
Reset warm | x | x | |
Cold reset | x | ||
Reset origin | |||
Download | x | ||
Online Change | x | x | x |
Remanent Variables - RETAIN, PERSISTENT
REMANENT VARIABLES: RETAIN VS PERSISTENT RETAIN
基本格式如下:
% MyProgram
N10 G01 X100 Y100 F100 (comment)
N20 M8 G01 Z40 F20
N30 G03 X-100 R200 F100
N40 SubPrg{5}
规则:
N10
()
中可以定义注释{}
定义可用 G代码可以查询:DIN 66025 Fundamentals
语法:
N10 G4 T5 (停留5秒)
当 cnc 程序中编写一个 M 功能时,如 M8,在 SMC_Interpolator
功能块中的 wM
会输出调用的 M 功能编号 8,同时会在此功能块等待输入确认信号 bAcknM
为 true 并且清空 wM
信号,在此期间插补器会停留在原地等待。
如果需要在执行 M 功能的时候不中断当前正在进行的插补器动作,需要设置并执行 SMC_PreAcknowledgeM
功能块。但是如果M功能有传递参数 K L 等则不可激活此预完成功能,否则传递参数POU接收不到。
注意 M 功能编号中 65533–65535 是内部保留的,其他都是可以自定义的,包括 M30
。
如要执行下面 cnc 程序:
N15 G1 X10 F100
N20 M8
N21 G1 X50 F100
N30 M30
POU 代码加入如下:
VAR
fbIpo : SMC_Interpolator; //插补器功能块
fbPreAckM : SM3_CNC.SMC_PreAcknowledgeMFunction; //M 功能预完成功能 可不中断插补器动作 如果M功能有传递参数 则不可激活此功能
END_VAR
***************************************
IF fbIpo.wM = 30 THEN
fbIpo(bAcknM:=TRUE); //执行玩动作后触发完成信号
END_IF
fbPreAckM(bEnable:=TRUE,iM:=8,poqDataIn:=fbCheckVel.poqDataOut); //激活指定M功能预完成 如果M功能有传递参数 则不可激活此功能
IF fbIpo.wM = 8 THEN
gVars.lrR3 := 5; //M功能需要执行的动作
fbIpo(bAcknM:=TRUE); //执行玩动作后触发完成信号
END_IF
可以在 CNC 程序调用 M 功能时定义传递参数,供POU使用,使用关键词 K
L
即可。同时需要定义 SMC_GetMParameters
功能块获取到参数值,这里需要注意此功能块必须和 SMC_Interpolator
处于同一周期中,否则可能读取失败,建议同 SMC_Interpolator
定义在一个 POU 中。
带传递参数的 M 功能 CNC 程序示例如下:
N20 M8 K7
以上示例 POU 修改如下:
VAR
fbIpo : SMC_Interpolator; //插补器功能块
//fbPreAckM : SMC_PreAcknowledgeMFunction; //屏蔽
fbGetMPara : SMC_GetMParameters;
END_VAR
***************************************
//fbPreAckM(bEnable:=TRUE,iM:=8,poqDataIn:=fbCheckVel.poqDataOut); //屏蔽
IF fbIpo.wM = 8 THEN
gVars.lrR3 := fbGetMPara.dK;; //读取到 K 传递参数的数据
fbIpo(bAcknM:=TRUE); //执行玩动作后触发完成信号
END_IF
fbGetMPara(Interpolator:=fbIpo,bEnable:=TRUE);
有两种跳转方法,第一种是引用行号来跳转,可以定义从某一个程序段跳转到另一个程序段以及跳转的循环次数。第二种是通过自定义标记位来跳转,可以不用管行号,缺点是只能向后跳转以及不可循环跳转。
行号跳转语法:
G20 L K
L
定义需要跳转到的指定行号,K
定义跳转循环次数,当为 0 时停止跳转。当不写 K
时系统会模式使用内部变量计数。此功能需要配合赋值命令 G36
G37
使用。
使用内部变量计数示例:
N00 G36 D5 (设置内部变量初始为5 变量值为0时跳转关闭)
N10 G91 (增量模式)
N20 G01 X10 Y10 F100 (每个循环移动的距离)
N30 G37 D-1 (给内部变量值减1)
N40 G20 L20 (内部变量值没到0时返回继续循环 N20)
使用自定义变量计数的示例:
N00 G36 O$R1$ D5 (设置变量R1初始为5 变量值为0时跳转关闭)
N10 G91 (增量模式)
N20 G01 X10 Y10 F100 (每个循环移动的距离)
N30 G37 O$R1$ D-1 (给变量R1值减1)
N40 G20 L20 K$R1$ (变量R1值没到0时返回继续循环 N20)
G36
命令给变量赋值,G37
命令修改变量值。
此跳转命令有局限性,不可嵌套跳转,不可设置 K 值为常数,如:K2
写法是错误的。
自定义标记跳转:
N00 G20 L?4 (定义需要跳转到标记 4 只能索引到此程序后的标记 如果没有找到标记则程序停在此处)
N05 L!5 (定义标记位置5)
N10 G1 X100 F100
N20 G1 Y100 L!4 F100 (定义标记位置4)
L?
定义需要跳转到的目标标记,L!
定义目标标记位。索引数字可以是任意整数,目标标记 L!
可以和 G 代码一行也可以单独一行定义。
使用自定义标记跳转时需要注意只能跳转到后面的程序行。
可以通过 F
控制轴移动速度,E
控制加速度及减速度。
示例:
N10 G01 X100 Y50 F100 E10 E-20
注意 E
后面设置负数就是设置减速度。
支持定义自定义全局变量并在 cnc 程序中使用,通过 G36 G37 给变量赋值。
首先需要在 GVL 中对变量进行定义:
{attribute 'qualified_only'}
VAR_GLOBAL CONSTANT
wVarsCount : WORD:= 5;
END_VAR
VAR_GLOBAL
lrR1 : LREAL := 0;
lrR2 : LREAL := 0;
lrR3 : LREAL := 0;
strVar1 : STRING;
lrSpeed : SM3_CNC.SMC_M_PARAMETERS; // M functions custom transfer parameter
astVar : ARRAY[0..wVarsCount-1] OF SMC_SingleVar := [
(strVarName := 'R1', pAdr := ADR(lrR1), eVarType := SMC_VARTYPE.SMC_TYPE_LREAL),
(strVarName := 'R2', pAdr := ADR(lrR2), eVarType := SMC_VARTYPE.SMC_TYPE_LREAL),
(strVarName := 'R3', pAdr := ADR(lrR3), eVarType := SMC_VARTYPE.SMC_TYPE_LREAL),
(strVarName := 'STR1', pAdr := ADR(strVar1), eVarType := SMC_VARTYPE.SMC_TYPE_STRING),
(strVarName := 'SPeed', pAdr := ADR(lrSpeed), eVarType := SMC_VARTYPE.SMC_TYPE_USERDEF)
];
stVarList : SMC_VARLIST := (wNumberVars := wVarsCount, psvVarList := ADR(astVar));
END_VAR
然后再 POU 中的 SMC_ReadNCFile2
功能块指定 SMC_VARLIST
地址:
VAR
fbReadFile : SMC_ReadNCFile2;
END_VAR
************************************
fbReadFile(pvl := ADR(gVars.stVarList));
变量类型支持 int lreal string 等各种类型,cnc 程序中使用 GVL 里 strVarName
定义的名称。不支持定义 array 数组类型变量。
cnc 程序调用语法:
$<Variablenname>$
通过 $
包围变量名称即可,示例如下:
N50 G01 Y50 + $R2$ F300
G36
可以给变量赋值,G37
可以修改变量值:
N00 G36 O$R1$ D5 (设置变量R1初始为5)
N10 G37 O$R1$ D-1 (给变量R1值减1)
N20 G36 O$STR1$ D'NAME' (设置字符串变量初始)
N30 G37 O$STR1$ D'=MARCO' (给字符串变量值添加字符)
如果需要重启可保持型变量,需要将变量单独定义在 Persistent Variables 类型 object 中,具体参考:codesys 定义重启可保持型变量
子程序调用支持无参数和带参数传递的模式,传递参数类型支持:BOOL, LREAL, 和 STRING,且必须使用 SMC_ReadNCFile2
和 SMC_NCInterpreter
来解码程序。子程序文件扩展名必须是 .cnc
。
子程序存储路径需要在 SMC_ReadNCFile2
中指定,支持定义4个目录作为子程序索引:
VAR
aSubProgramDirs : ARRAY[0..4] OF STRING[174] := ['_cnc', ''];
fbReadFile : SMC_ReadNCFile2;
END_VAR
****************************
fbReadFile(aSubProgramDirs := aSubProgramDirs);
子程序框架语法如下:
SUBPROGRAM SUB_PROG_1{#VAR1:LREAL,#VAR2:STRING}
N20 G01 X#VAR1 Y#VAR1 F100
END_SUBPROGRAM
如果有传递参数则需要写在大括号 {}
中定义。井号 #
表示定义的局部变量名称,可在子程序中使用。
子程序调用方式如下:
SUB_PROG_1{} (无传递参数的子程序调用)
N55 SUB_PROG_1{$R3$,'ABC'} (有传递参数的子程序调用)
SMC_NCInterpreter
功能块中的 aActivePrograms : ARRAY[0..9] OF STRING
存储程序级嵌套,aActivePrograms[0]
存储当前运行程序名称,aActivePrograms[1]
存储即将调用的子程序名称。
想要支持更多的计数表达式,必须使用 SMC_ReadNCFile2
和 SMC_NCInterpreter
来解码程序。
常用的加减乘除三角函数都是支持的,注意需要使用大括号 {}
来控制计算层级。给变量赋值还是需要使用 G36 G37 实现。
示例如下:
N00 G36 O$STR1$ D CONCAT{'NAME','=MARCO'} (链接两个字符串)
N35 G36 O$R1$ D SIN{30/180*PI} (三角函数单位为弧度, PI 表示 3.1415926)
N36 G36 O$R2$ D SQRT{$R1$} * 3
N40 G01 X 100 / 3 * 2
支持的运算符号如下:
支持的运算功能如下:
上面介绍了如何定义全局变量,需要在 POU 中定义然后才能在 cnc 程序中使用。也可以定义在程序内部使用的局部变量,每个子程序内最多可以定义 21 个局部变量。
使用关键词 LET
定义变量,主程序中必须定义在程序最开头,子程序中必须定义在子程序名称下一行,不需要写 N 行号。
定义语法如下:
LET <FormalParam> [:= <InitialValue>]
<FormalParam> ::= <ParamName> : <ParamType>
<ParamName> ::= #[a-zA-Z0-9_]+
<ParamType> ::= LREAL | BOOL | STRING ; 字符串最大255字节
示例如下:
%VAR_TEST
LET #VAR1 : LREAL
LET #VAR2 : LREAL := 3
LET #VAR3 : LREAL := #VAR2 - 1
LET #VAR4 : BOOL := #VAR1 > #VAR2
LET #VAR5 : STRING
N00 G36 O#VAR5 D'TEST'
N05 G36 O$STR1$ D#VAR5
N10 X#VAR2 +100 Y#VAR3 +50 F100
N55 SUB_PROG_1{$R3$,'ABC'}
SUBPROGRAM SUB_PROG_1{#VAR1:LREAL,#VAR2:STRING}
LET #AAA : LREAL := 10
N10 G91
N20 G01 X#VAR1 + #AAA Y#VAR1 F100
END_SUBPROGRAM
以上就是 codesys 中使用 DIN 66025 标准编写 CNC 程序的基本语法及功能讲解,更多功能参考:CNC Language in DIN 66025
]]>不管是哪种模式下,codesys 本身运行的一个容器环境根目录是如下:
PlcLogic 文件夹是 POU 运行的根目录,所有 G 代码文件的索引都是以此目录为根目录的。在程序中定义路径地址的时候只需要写 POU 根目录的子路径即可。
在电脑上进行运动控制模拟时,如果需要调用外部G代码程序,模拟环境下的程序运行根目录为 C:\ProgramData\CODESYS\Simulation\PlcLogic\
。
将G代码程序文件放入上述目录下使用即可调用,如:
strFileName : STRING(120) := 'NCReadFromFile.txt';
一般可以新建一个子路径 _cnc
将程序都放入其中:
strFileName : STRING(120) := '_cnc/NCReadFromFile.txt';
注意每次重启 codesys IDE 会重置 C:\ProgramData\CODESYS\Simulation\PlcLogic\
目录,需要重新复制程序进来。
首先需要知道工控机安装的是什么类型的控制器:
information 菜单下可以查看当前控制器类型:
windows 下 codesys runtime 安装路径为:C:\ProgramData\CODESYS
,目录中包含所有已经安装的各种类型的控制器,每个控制器类型都有其单独目录:
进入需要的控制器目录后,就可以看到运行 codesys 的容器文件夹了:
这个文件夹就是 codesys 在控制器上的运行环境,
只需要将 G 文件放入 PlcLogic 文件夹下,同时 POU 中路径只需要定义此根路径的子目录即可。
也可以通过 IDE 在线传输文件到控制器指定目录:
The library "caa behaviour model, 3.5.19.0 (caa technical workgroup)" was created with the unknown compiler version "3.5.16.30"
的报错:但是我已经选择下载了缺失的库了,查询后发现是我的 codesys 版本过高,下载的对应库版本也高,而项目之前创建的时候可能是基于低版本库的,需要手动切换回对应版本的库即可。
library manager 下选择 placeholders 定位到报错的那个库:
双击后显示版本菜单,选择对应低版本的选项:
再次编译报错就会消失。
]]>