跳转至

LUA脚本

1.1 本章简介

本章将介绍下载在控制器中运行的程序:Lua脚本程序。用户想要使用脚本程序,需要了解相应的语法,以及下载运行步骤。本章将一一介绍。

为了实现运控工艺实现灵活以及脱机运行,使用Lua脚本升级替换运动程序脚本。脚本程序的特点:易开发、独立、实时、并行。

1. 面向原型的编程语言,语法与C类似, 易于开发和调试。

2. 运动程序能够脱离主机在运动控制器上独立执行,主机能够将CPU资源分配给其它任务,从而将主机从繁琐的运动逻辑管理中解放出来。当然,如果需要,主机仍然可以在任何时候向控制器发送指令,即使运动控制卡器的运动程序正在执行。

3. 运动控制器上执行脚本程序由于不需要通过总线和主机进行频繁的数据交换,因此具有更高的实时性。和在主机上执行的应用程序不同之处在于,脚本程序对GTN指令调用不必再通过PC总线,因此具有更高的执行效率。逻辑指令平均执行速度小于0.3微秒/指令,GTN指令平均执行速度约为50微秒/指令。

4. 支持多任务,每个核允许多达8个脚本程序在运动控制器上同时执行。

提示

详细说明和测试可参考MotionStudio。

1.2 Lua脚本的使用

1.2.1 编写脚本

用户编写脚本程序时应遵照Lua语法及“1.4 Lua语法”中的说明,否则有可能编译不通过。

脚本程序可以和应用程序一样调用GTN指令。用户可查阅“5 可用程序指令”知道哪些指令可以在运动程序中调用。

1.2.2 指令列表

嵌入式Lua脚本功能指令列表

指令 说明
GTN_ClearMp 清除运动程序相关信息。
GTN_DownLoadFileMP 下载运动程序脚本。
GTN_BindMP 运动程序和task绑定。
GTN_RunMP 启动线程。
GTN_StopMP 终止线程。
GTN_SetPublicInt32VarValueMP 设置注册整型变量值。
GTN_GetPublicInt32VarValueMP 读取注册整型变量值。
GTN_SetPublicFloat64VarValueMP 设置注册浮点型变量值。
GTN_GetPublicFloat64VarValueMP 读取注册浮点型变量值。
GTN_DownloadAxisRefMP 下载轴相关参数。
GTN_UploadAxisRefMP 获取轴相关参数。

1.2.3 下载

使用GTN_DownLoadFileMP指令将文件下载到控制器,每个核最多可下载24个非同名文件,同名文件会覆盖原有文件。超过最大文件限制时会下载失败,需调用GTN_ClearMp清理已下载文件。

1.2.4 绑定线程

每个核可同时执行8个程序,需要使用GTN_BindMP将文件绑定到对应线程才可以执行该线程。

1.2.5 启动和停止

绑定线程后,可使用GTN_RunMP启动线程,以及GTN_StopMP停止线程。

1.2.6 注册变量

每个核具有50000个整型以及50000个浮点型数组变量用于线程间以及和上位机进行数据交互。

上位机可通过GTN_SetPublicInt32VarValueMPGTN_SetPublicFloat64VarValueMP写入变量,以及GTN_GetPublicInt32VarValueMPGTN_GetPublicFloat64VarValueMP读取变量。

代码中可直接使用GI(整型) 以及 GR(浮点型)调用数组。例:

实例:
GR[1] = 1;
a = GI[1];

1.2.7 轴参数

上位机可通过GTN_DownloadAxisRefMPGTN_UploadAxisRefMP直接向控制器内读写轴参数,脚本中可作为对象直接调用。例:

实例:
    core = 1;
    axis = 1;
    axis_ref = MC_AxisRef(core, axis);
    axis_ref.vel = 1;
    vel = axis_ref.vel;

1.3 lua语法

1.3.1 数据类型

lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。

当前可用类型分别为:nil、boolean、number、string、userdata、function 和 table。

Lua可用的数据类型

数据类型 描述
nil 只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean 包含两个值:false和true。
number 表示双精度类型的实浮点数。
string 字符串由一对双引号或单引号来表示。
function 由 C 或 Lua 编写的函数。
userdata 表示任意存储在变量中的C数据结构。
table Lua中的表(table)是一个"关联数组"(associative arrays)。
数组的索引可以是数字、字符串或表类型。
table的创建是通过"构造表达式"来完成,简单构造表达式是{},用来创建一个空表。

1. 字符串(String)

字符串是由数字、字母、下划线组成的一串字符。字符串可以使用以下三种方式来表示:

(1) 单引号间的一串字符。

(2) 双引号间的一串字符。

(3) [[ 与 ]] 间的一串字符。

实例:
string1 = "Lua" --> Lua
string2 = 'Lua' --> Lua
string3 = [["Lua"]] --> "Lua"

转义字符的含义及对应的ASCII码值

转义字符 意义 ASCII码值(十进制)
\a 响铃(BEL)。 007
\b 退格(BS) ,将当前位置移到前一列。 008
\f 换页(FF),将当前位置移到下页开头。 012
\n 换行(LF) ,将当前位置移到下一行开头。 010
\r 回车(CR) ,将当前位置移到本行开头。 013
\t 水平制表(HT) (跳到下一个TAB位置)。 009
\v 垂直制表(VT)。 011
\ 代表一个反斜线字符。 092
' 代表一个单引号(撇号)字符 ''\ '。 039
" 代表一个双引号字符。 034
\0 空字符(NULL)。 000
\ddd 1到3位八进制数所代表的任意字符。 三位八进制
\xhh 1到2位十六进制所代表的任意字。 二位十六进制

2. 数组(Array)

一维数组实例:
    array = {"Lua", "Tutorial"}
    -- 数组索引从1开始
    for i= 0, 2 do
    print(array[i]) --> nil, Lua, Tutorial
    end
多维数组实例:
    -- 初始化数组
    array = {}
    for i=1,3 do
    array[i] = {}
    for j=1,3 do
    array[i][j] = i*j
    end
    end
    -- 访问数组
    for i=1,3 do
    for j=1,3 do
    print(array[i][j])
    end
    end

3. 表(Table)

实例:
    -- 初始化表
    mytable = {}

    -- 指定值
    mytable[1]= "Lua"

    -- 移除引用
    mytable = nil
    -- lua 垃圾回收会释放内存

1.3.2 运算符

运算符是一个特殊的符号,用于告诉解释器执行特定的数学或逻辑运算。Lua提供了以下几种运算符类型:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 其他运算符

1. 算术运算符

下表列出了Lua语言中的常用算术运算符,设定A的值为10,B的值为 20:

算术运算符说明及实例

操作符 描述 实例
+ 加法 A+B输出结果30
- 减法 A-B输出结果-10
* 乘法 A*B输出结果200
/ 除法 B/A输出结果2
% 取余 B%A输出结果0
^ 乘幂 A^2输出结果100
- 负号 -A输出结果-10
// 整除运算符 5//2输出结果2

2. 关系运算符

下表列出了 Lua 语言中的常用关系运算符,设定A的值为10,B的值为20:

关系运算符说明及实例

操作符 描述 实例
== 等于,检测两个值是否相等,相等返回 true,否则返回 false (A==B)为false
~= 不等于,检测两个值是否相等,不相等返回 true,否则返回 false (A ~= B) 为 true
> 大于,如果左边的值大于右边的值,返回true,否则返回false (A > B)为false
< 小于,如果左边的值大于右边的值,返回 false,否则返回 true (A < B)为true
>= 大于等于,如果左边的值大于等于右边的值,返回 true,否则返回 false (A >= B)返回false
<= 小于等于,如果左边的值小于等于右边的值,返回 true,否则返回 false (A <= B) 返回 true

3. 逻辑运算符

下表列出了 Lua 语言中的常用逻辑运算符,设定 A 的值为 true,B 的值为 false:

逻辑运算符说明及实例

操作符 描述 实例
and 逻辑与操作符。 若 A 为 false,则返回 A,否则返回 B (A and B) 为 false
or 逻辑或操作符。 若 A 为 true,则返回 A,否则返回 B (A ~= B) 为 true
> 大于,如果左边的值大于右边的值,返回true,否则返回false (A or B) 为 true
not 逻辑非操作符。与逻辑运算结果相反,如果条件为 true,逻辑非为 false not(A and B) 为 true

4. 位运算符

下表列出了 Lua 语言中的常用位运算符,设定 A 的值为1,B 的值为 0:

位运算符说明及实例

操作符 描述 实例
& 按位与运算符 A & B 为 0
| 按位或运算符 A | B 为 1
~ 按位异或运算符 A ~ B 为 1
>> 右移运算符 A >> 1 为 0
<< 左移运算符 A << 1 为 2
~ 按位非运算符 ~ A 为 0

所有的位操作都将操作数先转换为整数, 然后按位操作,其结果是一个整数。

对于右移和左移,均用零来填补空位。移动的位数若为负,则向反方向位移;若移动的位数的绝对值大于等于整数本身的位数,其结果为零 (所有位都被移出)。

5. 其他运算符

下表列出了 Lua 语言中的连接运算符与计算表或字符串长度的运算符:

其他运算符说明及实例

操作符 描述 实例
.. 连接两个字符串 a..b, 其中 a 为 "Hello " , b 为 "World", 输出结果为 "Hello World"
# 一元运算符,返回字符串或表的长度 #"Hello" 返回 5

1.3.3 变量

变量在使用前,需要在代码中进行声明,即创建该变量。Lua 变量有三种类型:全局变量、局部变量、表中的域。未使用 local 显式声明为局部变量的变量全部为全局变量,即使是语句块或函数内。局部变量的作用域为从声明位置开始到所在语句块结束。变量的默认值均为 nil。

1.3.4 循环

Lua 语言提供了以下几种循环处理方式:

Lua的循环类型

循环类型 描述
while 循环 在条件为 true 时,让程序重复地执行某些语句。执行语句前会先检查条件是否为 true。
for 循环 重复执行指定语句,重复次数可在 for 语句中控制。
repeat...until 重复执行循环,直到 指定的条件为真时为止。
循环嵌套 可以在循环内嵌套一个或多个循环语句(while do ... end;for ... do ... end;repeat ... until;)。

循环控制语句用于控制程序的流程, 以实现程序的各种结构方式。Lua 支持以下循环控制语句:

Lua的循环控制语句

循环类型 描述
break语句 退出当前循环或语句,并开始脚本执行紧接着的语句。
goto 语句 将程序的控制点转移到一个标签处。

1. while循环

  • 格式
  • while(condition)
      do
          statements
      end
    
  • 说明
  • Statements(循环体语句)可以是一条或多条语句,condition(条件)可以是任意表达式,在 condition(条件)为 true 时执行循环体语句。

  • 实例
实例:
    a = 10
    while( a < 20 )
    do
    print(a) --> 10 ~ 19
    a = a + 1
    end

2. for循环

  • 格式
  • for var=exp1,exp2,exp3 do
    <执行体>
    end
    
  • 说明
  • var 从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var,并执行一次 “执行体”。exp3 是可选的,如果不指定,默认为1。

  • 实例
实例:
    -- 打印数组a的所有值
    a = {"one", "two", "three"}
    for i, v in ipairs(a) do
    print(i, v)
    end

    -- 打印10以内的奇数
    for i = 1, 10, 2 do
    print(i)
    end

3. repeat...until

  • 格式
  • repeat
        statements
    until( condition )
    
  • 说明
  • Condition(条件)在statements(循环体语句)末尾,每执行一次statements(循环体语句)进行一次判断。

  • 实例
实例:
    -- 变量定义
    a = 10
    -- 执行循环
    repeat
        print(a)
        a = a + 1
    until( a > 15 )

4. 循环嵌套

Lua 编程语言中允许循环中嵌入循环。

实例:
j = 2
for i= 2,10 do
    for j= 2, (i/j), 2 do
        if(not(i%j))
        then
            break
        end
        if(j > (i/j))then
            print("i 的值为:",i)
        end
    end
end

1.3.5 流程控制

Lua 提供了以下控制结构语句:

Lua控制结构语句

语句 描述
if语句 if语句由一个布尔表达式作为条件判断,其后紧跟其他语句组成。
if...else语句 if语句可以与else语句搭配使用, 在if条件表达式为false时执行else语句代码。
if 嵌套语句 可以在ifelse if中使用一个或多个ifelse if语句。

1. if语句

  • 格式
  • if(布尔表达式)
      then
          -- 在布尔表达式为 true 时执行的语句
      end
    
  • 说明
  • 在布尔表达式为 true 时会if中的代码块会被执行,在布尔表达式为 false 时,紧跟在 if 语句 end 之后的代码会被执行。false和nil为假,true 和非nil为真。Lua中 0 为 true。

  • 实例
实例:
-- 定义变量
a = 10;
-- 使用if语句
if( a < 20 )
then
    -- if条件为true时打印以下信息
    print("a 小于 20" );
end
    print("a 的值为:", a);

2. if...else 语句

  • 格式
  • if(布尔表达式)
      then
          -- 布尔表达式为true时执行该语句块
      else
          -- 布尔表达式为false时执行该语句块
      end
    
  • 说明
  • 在布尔表达式为 true 时会if中的代码块会被执行,在布尔表达式为 false 时,else 的代码块会被执行。

  • 实例
实例:
-- 定义变量
a = 100;
-- 检查条件
if( a < 20 )
then
    -- if条件为true时执行该语句块
    print("a 小于 20" )
else
    -- if条件为false时执行该语句块
    print("a 大于 20" )
end
print("a 的值为 :", a)

2. if嵌套语句

  • 格式
  • if( 布尔表达式 1)
      then
          -- 布尔表达式1为true时执行该语句块
          if(布尔表达式 2)
          then
              -- 布尔表达式2为true时执行该语句块
          end
      end
    
  • 实例
实例:
-- 定义变量
a = 100;
b = 200;
-- 检查条件
if( a == 100 )
then
    -- if条件为true时执行以下if条件判断
if( b == 200 )
then
    -- if条件为true时执行该语句块
    print("a 的值为 100 b 的值为 200" );
end
end
print("a 的值为 :", a );
print("b 的值为 :", b );

1.3.6 函数

1. 函数定义

  • 格式
  • Lua 编程语言函数定义格式如下:

    optional_function_scope function function_name( argument1, argument2..., argumentn)
          function_body
          return result_params_comma_separated
      end
    
  • 解析

optional_function_scope:该参数是可选的制定函数是全局函数还是局部函数,未设置该参数默认为全局函数,如果你需要设置函数为局部函数需要使用关键字 local。

function_name:指定函数名称。

argument1, argument2, ..., argumentn:函数参数,多个参数以逗号隔开,函数也可以不带参数。

function_body:函数体,函数中需要执行的代码语句块。

result_params_comma_separated:函数返回值,Lua语言函数可以返回多个值,每个值以逗号隔开。

2. 实例

  • 常用函数
  • function max(num1, num2)
      if (num1 > num2) then
          result = num1;
      else
          result = num2;
      end
      return result;
      end
    
  • 函数作为参数传递
  • myprint = function(param)
          print(param)
      end
      function add(num1,num2,functionPrint)
          result = num1 + num2
          -- 调用传递的函数参数
          functionPrint(result)
      end
      myprint(10)
      -- myprint 函数作为参数传递
      add(2,5,myprint)
    
  • 多返回值
  • function maximum (a)
          -- 最大值索引
          local mi = 1        
          -- 最大值               
          local m = a[mi]                 
          for i,val in ipairs(a) do
              if val > m then
                  mi = i
                  m = val
              end
          end
          return m, mi
      end
    
  • 可变参数
  • function add(...)
      local s = 0
          for i, v in ipairs{...} do --> {...} 表示一个由所有变长参数构成的数组
              s = s + v
          end
          return s
      end
      print(add(3,4,5,6,7)) --> 25
    

1.4 例程

例程
  1. Trap点位运动
  2. 插补运动

1.5 LUA支持的指令集

支持控制器Lua的指令列表

GTN_PrfTrap GTN_SetTrapPrm GTN_GetTrapPrm GTN_SetPos
GTN_GetPos GTN_SetVel GTN_Update GTN_MoveAbsolute
GTN_PrfJog GTN_SetJogPrm GTN_GetJogPrm GTN_PrfPt
GTN_PtClear GTN_PtData GTN_SetPtLoop GTN_GetPtLoop
GTN_PtSpace GTN_PtStart GTN_SetPtMemory GTN_GetPtMemory
GTN_PrfPvt GTN_PvtTablePercent GTN_PvtStart GTN_PvtStatus
GTN_GetClock GTN_GetClockHighPrecision GTN_GetSts GTN_ClrSts
GTN_GetPrfSts GTN_GetPrfMode GTN_GetPrfPos GTN_GetPrfVel
GTN_GetEncVel GTN_GetPrfAcc GTN_Stop GTN_AlarmOff
GTN_AlarmOn GTN_AxisOn GTN_AxisOff GTN_LmtsOn
GTN_LmtsOff GTN_ZeroPos GTN_SetPrfPos GTN_SetEncPos
GTN_GetEncPos GTN_SetPid GTN_GetPid GTN_SetVelLoopPid
GTN_GetVelLoopPid GTN_SetVelLoopKjff GTN_GetVelLoopKjff GTN_SetPrfTorque
GTN_GetAtlTorque GTN_SetMotionMode GTN_GetMotionMode GTN_SetAxisBand
GTN_SetEcatAxisMode GTN_SetEcatAxisPT GTN_SetEcatAxisPV GTN_GetEcatAxisAtlTorque
GTN_GetEcatAxisAtlCurrent GTN_SetStopDec GTN_SetPosErr GTN_GetAxisEncPos
GTN_GetAxisError GTN_GetDi GTN_GetDiEx GTN_GetDiRaw
GTN_GetDiReverseCount GTN_SetDiReverseCount GTN_SetDo GTN_SetDoEx
GTN_SetDoBit GTN_SetDoBitReverse GTN_SetDac GTN_GetDac
GTN_SetAuDac GTN_GetAuDac GTN_GetDiBit GTN_GetAdc
GTN_GetAdcValue GTN_GetAuAdc GTN_GetAuAdcValue GTN_GetAuDac
GTN_SetTerminalPermitEx GTN_GetTerminalPermitEx GTN_PosCompareStart GTN_PosCompareStop
GTN_PosCompareClear GTN_PosCompareStatus GTN_PosCompareStart GTN_PosCompareStop