主题
plc — PLC 数据交互
模块名:plc
Lua 与梯形图之间的桥梁,也是设备参数的总入口。它负责读写全部软元件(X/Y/M/S/T/C/D/R)、配置三个网口、访问远程设备,以及 RTC、持久化、编解码等系统功能。plc 是必加载模块,不需要在脚本里做任何声明。
以下三条通用约定适用于全章:
- 软元件:
plc.名称(地址)是读,plc.名称(地址, 值)是写,写入后返回写进去的值。 - 网络参数:
plc.名称()是读,plc.名称(值)是写。 ds/dsd/dsf/ms的地址是偏移量,不是绝对编号。plc.ds(13)访问的是 D8013,plc.ms(0)访问的是 M8000。
函数总览
位软元件
| 函数 | 作用 |
|---|---|
plc.x(integer, ...) | 输入继电器 X(0-255) |
plc.y(integer, ...) | 输出继电器 Y(0-255) |
plc.m(integer, ...) | 内部继电器 M(0-7679) |
plc.ms(integer, ...) | 特殊继电器 M8000 段(偏移 0-511) |
plc.s(integer, ...) | 状态继电器 S(0-4095) |
plc.ts(integer, ...) | 定时器触点(0-511) |
plc.cs(integer, ...) | 计数器触点(0-255) |
字软元件
| 函数 | 作用 |
|---|---|
plc.d(integer, integer, ...) | D 寄存器 16 位整数(0-7999) |
plc.dd(address) | D 寄存器 32 位整数(占 2 个 D) |
plc.df(integer, ...) | D 寄存器单精度浮点(占 2 个 D) |
plc.ds(integer, ...) | 特殊寄存器 D8000 段 16 位(偏移 0-511) |
plc.dsd(integer, ...) | 特殊寄存器 32 位(偏移 0-510) |
plc.dsf(integer, ...) | 特殊寄存器浮点(偏移 0-510) |
plc.tn(integer, ...) | 定时器当前值(0-511) |
plc.cn(integer, ...) | 计数器当前值(C0-C199 16 位,C200-C255 32 位) |
plc.r(address) | R 文件寄存器 16 位(0-32767) |
plc.rd(address) | R 寄存器 32 位整数(占 2 个 R) |
plc.rf(address) | R 寄存器单精度浮点(占 2 个 R) |
字符串
| 函数 | 作用 |
|---|---|
plc.dstr(integer, ...) | D 寄存器字符串(最多 32 个 D,64 字符) |
plc.rstr(address) | R 寄存器字符串(最多 32 个 R,64 字符) |
网络配置
远程设备
| 函数 | 作用 |
|---|---|
plc.get(string, integer, integer, integer) | 通过 UDP 向远程设备请求 D 寄存器 |
plc.put(string, integer, integer, integer) | 通过 UDP 把本地 D 寄存器写到远程设备 |
设备与系统
| 函数 | 作用 |
|---|---|
plc.plc_name | 读取或设置设备名 |
plc.led(mode) | 控制状态指示灯 |
plc.rtc_set(integer, integer, integer, integer, integer, integer, ...) | 设置 RTC 时钟 |
plc.sta_autochn | WiFi 射频自动校准开关 |
plc.lua_password(password_string) | 设置 Lua 脚本访问密码 |
plc.plc_password(password_string) | 设置梯形图保护密码 |
持久化与编解码
| 函数 | 作用 |
|---|---|
plc.kv_set | 写掉电不丢失的键值对 |
plc.kv_get | 读键值对 |
plc.base64_encode(string) | Base64 编码 |
plc.base64_decode(encoded_string) | Base64 解码 |
plc.aes_encode(string) | AES 加密(设备内置密钥) |
plc.aes_decode(encrypted_string) | AES 解密 |
plc.bite(data, bit_position) | 读写一个整数的指定位 |
plc.AI | 类型转换与命令式功能入口 |
云平台
plc.cloud_status—— 本机与云平台的连接状态(本页下方有完整说明)plc.cloud_bind/cloud_reg/cloud_publish/cloud_subscribe/cloud_compute也属于本模块,见 云平台通信。
短信(只在部分机型上有)
| 函数 | 作用 |
|---|---|
plc.sms_recv() | 注册"收到短信"回调 |
plc.sms_send(phone_number, message) | 发一条短信 |
这两个函数不是全机型可用,调用前务必先判空,见各自条目。
位软元件读写
7 个位软元件函数共用同一套约定:plc.名称(addr) 读回 0/1,plc.名称(addr, value) 写入并返回写后的 0/1。value 接受 boolean(true/false)或整数(非 0 为 ON)。地址超范围时读返回 0、写被忽略。
lua
plc.x(addr, [value]) --> 0 | 1
plc.y(addr, [value]) --> 0 | 1
plc.m(addr, [value]) --> 0 | 1
plc.ms(addr, [value]) --> 0 | 1
plc.s(addr, [value]) --> 0 | 1
plc.ts(addr, [value]) --> 0 | 1
plc.cs(addr, [value]) --> 0 | 1| 函数 | 元件 | 地址范围 | 说明 |
|---|---|---|---|
plc.x | 输入继电器 X | 0-255 | 物理输入点,可写但通常只读 |
plc.y | 输出继电器 Y | 0-255 | |
plc.m | 内部继电器 M | 0-7679 | M8000 以上用 plc.ms |
plc.ms | 特殊继电器 | 偏移 0-511 | plc.ms(0) = M8000,部分位系统写保护 |
plc.s | 状态继电器 S | 0-4095 | |
plc.ts | 定时器触点 | 0-511 | 定时器溢出线圈状态 |
plc.cs | 计数器触点 | 0-255 |
示例
lua
plc.y(0, 1) -- Y0 置 ON
local run = plc.m(10) -- 读 M10
if plc.ts(5) == 1 then -- T5 到时
plc.y(0, 0)
end说明
- 地址按十进制解析,
plc.x(10)就是第 10 号输入点,不做八进制换算。(八进制换算只发生在cloud_bind里"X10"这类字符串地址上。)
字软元件读写
字软元件同样是 1 参读、2 参写,写入返回写进去的值。32 位类型占用两个连续寄存器,规划地址时应避免相邻数据重叠。
lua
plc.d(addr, [value]) --> integer -- 16 位有符号
plc.dd(addr, [value]) --> integer -- 32 位有符号,占 D(addr)、D(addr+1)
plc.df(addr, [value]) --> number -- 单精度浮点,占 2 个 D
plc.ds(addr, [value]) --> integer -- D8000 偏移,16 位
plc.dsd(addr, [value]) --> integer -- D8000 偏移,32 位
plc.dsf(addr, [value]) --> number -- D8000 偏移,浮点
plc.tn(addr, [value]) --> integer -- 定时器当前值
plc.cn(addr, [value]) --> integer -- 计数器当前值
plc.r(addr, [value]) --> integer -- R 文件寄存器 16 位
plc.rd(addr, [value]) --> integer -- R 32 位,占 2 个 R
plc.rf(addr, [value]) --> number -- R 浮点,占 2 个 R| 函数 | 数据类型 | 占用 | 地址范围 |
|---|---|---|---|
plc.d | 16 位整数 | 1 个 D | 0-7999 |
plc.dd | 32 位整数 | 2 个 D | 0-7998 |
plc.df | 单精度浮点 | 2 个 D | 0-7998 |
plc.ds | 16 位整数 | 1 个 | 偏移 0-511(D8000-D8511) |
plc.dsd | 32 位整数 | 2 个 | 偏移 0-510 |
plc.dsf | 单精度浮点 | 2 个 | 偏移 0-510 |
plc.tn | 16 位整数 | 1 个 | 0-511 |
plc.cn | 16/32 位整数 | — | C0-C199 按 16 位,C200-C255 按 32 位 |
plc.r | 16 位整数 | 1 个 R | 0-32767 |
plc.rd | 32 位整数 | 2 个 R | 0-32766 |
plc.rf | 单精度浮点 | 2 个 R | 0-32766 |
示例
lua
plc.d(100, 1234) -- 写 D100
local temp = plc.df(200) -- 读 D200-D201 的浮点
plc.dd(300, 100000) -- 写 32 位整数到 D300-D301
local c = plc.cn(200) -- 读 C200(32 位计数器)
local special = plc.ds(13)-- 读 D8013字符串读写
把字符串按每个寄存器 2 字节的方式存入 D 或 R 区。
lua
plc.dstr(addr, [str]) --> string
plc.rstr(addr, [str]) --> string参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | addr | integer | 是 | — | 起始寄存器编号 |
| 2 | str | string | 否 | — | 省略为读取;提供为写入。最多 32 个寄存器(64 字符) |
返回值
| 类型 | 说明 |
|---|---|
| string | 读取或写入的字符串 |
示例
lua
plc.dstr(300, "Hello") -- 写字符串到 D300 起
local name = plc.dstr(300) -- 读回说明
- 每个寄存器存 2 个字符,遇到值为 0 的高字节视为字符串结束。
网络配置
三个网口(STA=WiFi 客户端、AP=WiFi 热点、ETH=以太网)的参数读写。0 参数为读、1 参数为写,写入返回新值。IP/掩码/网关既接受点分字符串也接受整数,读出为点分字符串;DHCP 读出为 0/1。
lua
plc.sta_dhcp([v]) plc.eth_dhcp([v]) --> 0 | 1
plc.sta_ip([v]) plc.ap_ip([v]) plc.eth_ip([v]) --> string
plc.sta_mask([v]) plc.ap_mask([v]) plc.eth_mask([v]) --> string
plc.sta_gateway([v]) plc.ap_gateway([v]) plc.eth_gateway([v]) --> string
plc.sta_ssid([v]) plc.sta_password([v]) --> string
plc.ap_ssid([v]) plc.ap_password([v]) --> string参数
下面 15 个函数共用同一套参数约定:不传参数是读,传 1 个参数是写。
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | 值 | string | integer | boolean | 否 | — | DHCP 开关传整数或布尔;IP / 掩码 / 网关传点分字符串;SSID / 密码传字符串。省略即为读取 |
返回值
| 类型 | 说明 |
|---|---|
| string | IP / 掩码 / 网关 / SSID / 密码:读出当前保存的值,写入后返回写入的值 |
| integer | DHCP 开关:0 关闭、1 开启 |
示例
lua
plc.eth_dhcp(0)
plc.eth_ip("192.168.1.100")
plc.eth_mask("255.255.255.0")
plc.eth_gateway("192.168.1.1")
print("以太网 IP:", plc.eth_ip())说明 —— 下面这几条对全部 15 个函数都成立,各函数条目里只写差异
- 写入只是把值存进参数区(掉电不丢),不会立刻改变正在运行的网络。 生效时机每条函数各自写明,共同点是:改完要重启(或重新联网)才看得出结果,不要在运行中反复改。
- 软 PLC 模拟器里这 15 个函数是空实现:不报错,但读回来是
nil、写入没有任何效果。它们只在设备上有意义。脚本要兼顾模拟器时先判空:local ip = plc.eth_ip(); if ip then ... end。 - IP / 掩码 / 网关一律传点分字符串。 整数形式按设备内部的字节顺序解释(最低位那个字节才是第一段),和常见的
0xC0A8xxxx写法正好相反 —— 传进去会得到一个首尾颠倒的地址,且不会报错。 - 地址写错了不报错,会被存成一个奇怪的地址。 解析不出来的字符串(
"abc"、"300.1.1.1"、"192.168.1.")会存成255.255.255.255;少写一段的简写会被自动补全("192.168.1"被当成192.168.0.1)。写完立刻读一次,读回的不是您填的那个值就说明没被接受。 - 传既非数字也非字符串的参数(
nil、true、table)时行为未定义:IP 类会把一个不确定的值写进参数区,DHCP 类一律按"开启"处理 —— 所以plc.sta_dhcp("0")是打开 DHCP 而不是关闭。 - 一次调用传两个及以上参数时什么都不写(也不报错),别把
plc.sta_ip(a, b)当成批量设置。 - SSID / 密码最长 31 个字符。 超长的写入不报错、也确实存进去了,但之后无论是函数读取还是设备开机取用,都会退回出厂默认值 —— 表现为"改了没生效"。写完立刻读一次即可判断有没有被接受。
plc.sta_dhcp
lua
plc.sta_dhcp() --> 0 | 1 -- 读
plc.sta_dhcp(1) --> 0 | 1 -- 写:1 开启,0 关闭WiFi 客户端要不要用 DHCP 自动取地址。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | enable | integer | boolean | 否 | — | 省略为读。0 / false 关闭,非 0 / true 开启;其它类型一律按开启处理 |
返回值
| 类型 | 说明 |
|---|---|
| integer | 0 固定 IP,1 DHCP。写入时返回写入后的值 |
说明
- 出厂默认是开启。
- 只有关闭后,
plc.sta_ip/plc.sta_mask/plc.sta_gateway保存的值才会被真正配到网卡上;开启时这三个函数读到的是路由器下发的地址。 - 生效时机:设备连上路由器的那一刻读取本开关,改完要重启或让 WiFi 重连一次。
实用例程
lua
-- 宁夏设备监控脚本 - 基于nx20250901.md
-- 功能:采集纺织机数据并通过MQTT发送
--配置plc wifi
plc.ap_ssid("")
plc.sta_ssid("<设备ID或凭据>")--wifi账号
plc.sta_password("<设备ID或凭据>!")--wifi密码
plc.sta_dhcp(1)--开启wifi的DHCP
plc.sta_autochn(1)--开启天线校准
local table_result = plc.AI(
{
cmd="set",
data={
cmdtype="set_cloud",
name="JDD",
pass="<设备ID或凭据>",
enable=true
}
}
)--设置云服务把上面的地址、主题、引脚替换成你项目里的即可。
plc.sta_ip
lua
plc.sta_ip() --> string -- 读
plc.sta_ip("1.1.1.1") --> string -- 写WiFi 客户端的地址。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | ip | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的地址。DHCP 开启时这就是路由器实际分配到的地址 |
示例
lua
-- 固定 IP 部署:关 DHCP,配好三项,再重启
plc.sta_dhcp(0)
plc.sta_ip("192.168.1.100")
plc.sta_mask("255.255.255.0")
plc.sta_gateway("192.168.1.1")说明
- DHCP 开着时,设备每次拿到地址都会把它写回参数区,所以您之前设置的固定值会被顶掉。要固定 IP 必须先
plc.sta_dhcp(0)。 - DHCP 开着但 3 秒内没拿到地址时,设备会回落到这里存的值(存的是
0.0.0.0时不回落)—— 这算是断网时的兜底,不是 bug。 - 生效时机:下一次连上路由器时下发,改完重启确认。
plc.sta_mask
lua
plc.sta_mask() --> string -- 读
plc.sta_mask("255.255.255.0") --> string -- 写WiFi 客户端的子网掩码。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | mask | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的掩码 |
说明
- 与
plc.sta_ip同一套规则:DHCP 开启时会被路由器下发的值覆盖,只在plc.sta_dhcp(0)时生效。
plc.sta_gateway
lua
plc.sta_gateway() --> string -- 读
plc.sta_gateway("192.168.1.1") --> string -- 写WiFi 客户端的网关。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | gateway | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的网关 |
说明
- 与
plc.sta_ip同一套规则:DHCP 开启时会被路由器下发的值覆盖。 - 网关写错的表现是"能连上路由器、同网段之间 ping 得通,但上不了云、连云一直失败",因为跨网段的数据包没有去处。
plc.eth_dhcp
lua
plc.eth_dhcp() --> 0 | 1 -- 读
plc.eth_dhcp(1) --> 0 | 1 -- 写:1 开启,0 关闭以太网口要不要用 DHCP 自动取地址。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | enable | integer | boolean | 否 | — | 省略为读。0 / false 关闭,非 0 / true 开启;其它类型一律按开启处理 |
返回值
| 类型 | 说明 |
|---|---|
| integer | 0 固定 IP,1 DHCP。写入时返回写入后的值 |
说明
- 出厂默认是关闭(用固定 IP),和 WiFi 那边相反。
- 生效时机:网线链路重新起来(拔插网线)或重启时读取本开关,写入本身不会让网口重新配址。
plc.eth_ip
lua
plc.eth_ip() --> string -- 读
plc.eth_ip("1.1.1.1") --> string -- 写以太网口的地址。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | ip | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的地址。DHCP 开启时这就是路由器实际分配到的地址 |
示例
lua
plc.eth_dhcp(0)
plc.eth_ip("192.168.1.100")
plc.eth_mask("255.255.255.0")
plc.eth_gateway("192.168.1.1")说明
plc.eth_ip()读回0.0.0.0有两种可能:这台机型没有以太网口(值恒为0.0.0.0,写进去也只是存在参数区、永远不会生效),或者这个值确实被写成了 0。先看机型有没有网口再判断。- 与
plc.sta_ip同样是「DHCP 拿到地址就回写参数区」,要固定 IP 先plc.eth_dhcp(0)。 - DHCP 开着但 3 秒内没拿到地址时,回落到这里存的值。
- 生效时机:网线拔插一次或重启。
实用例程
lua
signalFailSecond = Unsigned(plc.rd(10),32), --通讯故障时长
data =
{
{
identity = "<设备ID或凭据>", --参数标识
name = "<名称>", --名称
value = Unsigned(plc.rd(0),32), --对应值
unit = "<名称>", --单位
dataType = "0" --数据类型:0-数字,1-字符串
},
}
}
send_data = json.encode(torigin) --json格式转
rev_data=http.post(twinhu,send_data,plc.eth_ip()) --发送数据
print(rev_data)
end
if plc.m(2)==1 then --报警数据发送
plc.m(2,0)
plc.m(1,0)
Bnumber = Bnumber+1
plc.rd(105,Bnumber)
local torigin_A = --建JSON表
{
versionNo = 1.0, --版本号
boxId = plc.dsd(37), --box号
dssn = Bnumber, --发送ID序号把上面的地址、主题、引脚替换成你项目里的即可。
plc.eth_mask
lua
plc.eth_mask() --> string -- 读
plc.eth_mask("255.255.255.0") --> string -- 写以太网口的子网掩码。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | mask | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的掩码 |
说明
- 读写与生效时机同
plc.eth_ip(含"没有网口的机型读回0.0.0.0"这一条)。
plc.eth_gateway
lua
plc.eth_gateway() --> string -- 读
plc.eth_gateway("192.168.1.1") --> string -- 写以太网口的网关。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | gateway | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的网关 |
说明
- 读写与生效时机同
plc.eth_ip。
plc.ap_ip
lua
plc.ap_ip() --> string -- 读
plc.ap_ip("1.1.1.1") --> string -- 写本机热点自己的地址,也就是您的手机 / 上位机连上这个热点后访问设备用的地址。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | ip | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的热点地址;出厂默认 192.168.150.1 |
说明
- 这是热点自己那一侧的地址,改它会改变访问设备的入口,改完连上热点的电脑也要重新拿地址。
- 不受 DHCP 开关影响:
plc.ap_ip/plc.ap_mask/plc.ap_gateway三项直接配到热点上,连进来的设备由设备的 DHCP 服务分配地址。 - 生效时机:重启(WiFi 初始化时一次性配好)。
plc.ap_mask
lua
plc.ap_mask() --> string -- 读
plc.ap_mask("255.255.255.0") --> string -- 写本机热点侧的子网掩码。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | mask | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的掩码 |
说明
- 读写与生效时机同
plc.ap_ip。改掩码要和plc.ap_ip、plc.ap_gateway一起改到同一个网段,否则连上热点也访问不到设备。
plc.ap_gateway
lua
plc.ap_gateway() --> string -- 读
plc.ap_gateway("1.1.1.1") --> string -- 写本机热点侧的网关。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | gateway | string | 否 | — | 省略为读,填了是写;点分十进制字符串 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的网关;出厂默认与热点地址相同(192.168.150.1) |
说明
- 读写与生效时机同
plc.ap_ip。热点是给本地直连用的,一般不需要改这一项。
plc.ap_ssid
lua
plc.ap_ssid() --> string -- 读
plc.ap_ssid("LP-1") --> string -- 写本机发出的热点名。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | ssid | string | 否 | — | 省略为读,填了是写;最长 31 个字符 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的热点名 |
说明
- 出厂热点名因机型而异(有
lp,也有带设备后缀的形式),以实际搜到的为准。 - 置空后重启:部分机型会自动生成一个
lpplc-XXXXXX的名字并写回,另一些会保持为空;两个 WiFi 名都为空时 WiFi 可能整体关闭。要关热点,建议改成一个好认的名字,别用空串。 - 生效时机:重启。
实用例程
lua
-- 宁夏设备监控脚本 - 基于nx20250901.md
-- 功能:采集纺织机数据并通过MQTT发送
--配置plc wifi
plc.ap_ssid("")
plc.sta_ssid("<设备ID或凭据>")--wifi账号
plc.sta_password("<设备ID或凭据>!")--wifi密码
plc.sta_dhcp(1)--开启wifi的DHCP
plc.sta_autochn(1)--开启天线校准
local table_result = plc.AI(
{
cmd="set",
data={
cmdtype="set_cloud",
name="JDD",
pass="<设备ID或凭据>",
enable=true
}把上面的地址、主题、引脚替换成你项目里的即可。
plc.ap_password
lua
plc.ap_password() --> string -- 读
plc.ap_password("ab123456") --> string -- 写本机热点的密码。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | password | string | 否 | — | 省略为读,填了是写;最长 31 个字符 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的热点密码;热点从未设置过时读到出厂默认密码 |
说明
- 密码少于 8 个字符(包括置空)会让热点直接变成不加密的开放网络,任何设备都能连进来,且函数不会报错、返回值看起来正常。这是最容易造成现场安全事故的一条,改完请确认长度 ≥ 8。
- 生效时机:重启。
plc.sta_ssid
lua
plc.sta_ssid() --> string -- 读
plc.sta_ssid("车间WiFi") --> string -- 写设备要连接的 WiFi 名字。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | ssid | string | 否 | — | 省略为读,填了是写;最长 31 个字符 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的 WiFi 名;没配置过时为空串 "" |
说明
- 空串 = 不连接任何路由器,设备不会去连 WiFi。想改密码别忘了名字也要一致(路由器改了 WiFi 名,设备就再也连不上,表现是设备离线)。
- 超长(>31 字符)写入会被接受,但读回和开机实际用的值都会退回默认(空串),等于设备变成不连 WiFi。
- 生效时机:重启。
实用例程
lua
-- 宁夏设备监控脚本 - 基于nx20250901.md
-- 功能:采集纺织机数据并通过MQTT发送
--配置plc wifi
plc.ap_ssid("")
plc.sta_ssid("<设备ID或凭据>")--wifi账号
plc.sta_password("<设备ID或凭据>!")--wifi密码
plc.sta_dhcp(1)--开启wifi的DHCP
plc.sta_autochn(1)--开启天线校准
local table_result = plc.AI(
{
cmd="set",
data={
cmdtype="set_cloud",
name="JDD",
pass="<设备ID或凭据>",
enable=true
}
}把上面的地址、主题、引脚替换成你项目里的即可。
plc.sta_password
lua
plc.sta_password() --> string -- 读
plc.sta_password("pwd123456") --> string -- 写设备连接 WiFi 用的密码。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | password | string | 否 | — | 省略为读,填了是写;最长 31 个字符 |
返回值
| 类型 | 说明 |
|---|---|
| string | 当前保存的 WiFi 密码;从未设置过时读到出厂默认密码 |
说明
- 密码错了不会有任何提示:
plc.sta_ssid()仍返回您写的名字,但设备一直连不上路由器。排查设备离线时,这一项和plc.sta_ssid一起核对。 - 超长(>31 字符)写入不报错,但读回和开机实际用的值都会退回出厂默认密码。
- 生效时机:重启。
实用例程
lua
-- 宁夏设备监控脚本 - 基于nx20250901.md
-- 功能:采集纺织机数据并通过MQTT发送
--配置plc wifi
plc.ap_ssid("")
plc.sta_ssid("<设备ID或凭据>")--wifi账号
plc.sta_password("<设备ID或凭据>!")--wifi密码
plc.sta_dhcp(1)--开启wifi的DHCP
plc.sta_autochn(1)--开启天线校准
local table_result = plc.AI(
{
cmd="set",
data={
cmdtype="set_cloud",
name="JDD",
pass="<设备ID或凭据>",
enable=true
}
}
)--设置云服务把上面的地址、主题、引脚替换成你项目里的即可。
plc.cloud_status
lua
plc.cloud_status() --> table读一次本机与云平台的连接状态,用来回答"配了云服务但连不上,到底卡在哪一步"。
参数
无。
返回值
| 类型 | 说明 |
|---|---|
| table | 总是返回一个表,四个字段见下表;未连接时也会正常返回,不会返回 nil |
返回的表:
| 字段 | 类型 | 说明 |
|---|---|---|
linked | boolean | 是否已经登录上云平台 |
wait_state | string | 已登录为 "established",否则为 "closed" |
hb_sec | integer | 距上一次登录/心跳成功过了多少秒;本次上电以来从未连上过时为 -1 |
link_detail | string | 当前配置的云地址和端口,形如 地址:端口 |
示例
lua
local st = plc.cloud_status()
if not st.linked then
print("未连云,目标是 " .. st.link_detail .. ",上次心跳 " .. st.hb_sec .. " 秒前")
end说明
- 只读,不会触发连接、也不会重连。
link_detail是配置值,不代表这个名字解析得出来、这个端口连得通;网络没通时它照样有内容。- 判断口径:
linked == false且hb_sec == -1→ 本次上电从没连上过,查地址 / 账号 / 网络;linked == false且hb_sec在涨 → 连过之后断了,查链路稳定性;linked == true但云端看不到数据 → 问题在绑定与上报,见 云平台通信。 - 云服务总开关没开时(设备不发起连接),这里读到的就是未连接状态。
plc.sms_recv
lua
plc.sms_recv(function(number, msg) ... end) --> 无返回值注册一个"收到短信时"的回调函数。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | callback | function | 是 | — | 收到短信时被调用,收到两个参数:发件号码、短信内容 |
返回值
无返回值。
说明
- 这个函数不是全机型可用:目前只有 4G 网关机型(RDA8910 平台那一族,如 LP8910、LP8913)的固件里有实现;
LP32xx系列 ESP32 机型根本没有注册这个函数,plc.sms_recv取到的是nil,直接调用会报attempt to call a nil value。软 PLC 模拟器里它注册了但是空实现,调用不报错、也永远不会有回调。 - 调用前先判机型,别让整脚本被一个
nil打断:
lua
if plc.sms_recv then
plc.sms_recv(function(number, msg)
print("短信来 " .. number .. " : " .. msg)
end)
else
print("本机不支持短信")
end- 回调是在设备收到短信时异步执行的,不在您调用的那一行里跑;回调内部报错只会打印出错误信息,不会中断程序。
- 先在您手上的机型上确认再写进交付脚本:
print(plc.sms_recv, plc.sms_send)两个都打印出function:才算支持。
plc.sms_send
lua
plc.sms_send(number, msg) --> 无返回值发一条短信。函数名就是常规拼写 sms_send(不是 sms_sned,全站没有注册过带那个拼写的函数)。
机型可用性差别很大,交付前务必先在手上的机型上探一次:
| 平台 | 短信函数可用性 |
|---|---|
| RDA8910 4G 网关机型 | ✅ 有 sms_recv / sms_send |
| 软 PLC 模拟器 | ✅ 有 |
| ESP32 全系机型 | ❌ 没有 |
| STM32F103 网口版 / 750 / H750 | ❌ 没有 |
在没注册的机型上 plc.sms_send 取到 nil,调用即 attempt to call a nil value。 判据同 sms_recv 节:print(plc.sms_recv, plc.sms_send),两个都打 function: 才可用。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | number | string | 是 | — | 接收方手机号码 |
| 2 | msg | string | 是 | — | 短信内容 |
返回值
无返回值 —— 发没发出去不能从返回值判断。
说明
- 两个参数都必须是字符串(可转成字符串的值除外),少传或传
nil会直接抛出 Lua 错误,脚本中断。 - 机型可用性与
plc.sms_recv相同:只有 4G 网关机型(RDA8910 平台那一族)有实现;LP32xx系列 ESP32 机型没有注册这个函数(取到nil,调用即报错),软 PLC 模拟器里是空实现(调用不报错、也不会真的发出短信)。 - 因为没有返回值,验证只能靠收端手机看是否收到;现场用报警类短信时建议同时
plc.cloud_publish一份,别把短信当唯一通路。
lua
if plc.sms_send then
plc.sms_send("13800138000", "D100 超温报警")
endplc.get
lua
plc.get(ip, remote_addr, local_addr, len)通过 UDP 向远程 LPPLC 设备发起一次「读 D 寄存器」请求,把远端数据写回本地 D 区。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | ip | string | 是 | — | 远程设备 IP |
| 2 | remote_addr | integer | 是 | — | 远程起始 D 编号 |
| 3 | local_addr | integer | 是 | — | 本地起始 D 编号 |
| 4 | len | integer | 是 | — | D 寄存器数量,最大 255 |
返回值
无返回值。
说明
- 异步 UDP 请求:本函数只把读请求发出去,远端回包后才把数据写进本地
local_addr起始的 D 区,不在调用内同步返回数据。UDP 不保证可靠,丢包时本轮不更新。 - 目的端口固定 25388,对方 LPPLC 开机常开、无需任何设定即可应答,也不限制同时被几台读写。
- 只能访问 D 区(D0-D7999);超出范围的地址读回 0。
len在协议里只占 1 个字节,填超过 255 会被静默截断(填 300 实际只传 44 点),固件不报错。- 需要网口 / WiFi 已就绪;两台设备要在同一局域网,UDP 单播穿不了 NAT。跨网段跨地区请改用云服务数据交换。
- 【Linux / RDA8910 版】该平台固件未处理读回应包,
plc.get收不回数据,只有plc.put可用。
实用例程
lua
timer1=timer.start(12000,function() --读前端水位高度"192.168.1.100" PLC内D100到本PLC D110 寄存器内
plc.get ("192.168.1.100",100,110,1)
print("<名称>",plc.d(110))
end )
--modbus采集的传感器数据(D100-199用于采集和数据处理下游水位D100 (地址为1)上游水位D110 (地址2) 电流值 D120(地址3) 电压值 D130(地址4) 每一个间距10个寄存器位,方便浮点数等转换用;
--上游水位WL_H 单位: m \ 下游水位WL_L 单位: m \ 电流 I (大写) 单位:A \电压:V 单位:伏 \功率 P (大写) 单位:KW \
--电折水流量为Q_D 单位 :m3/s
i_1=1
i_8=1
i_24=1
Q_1H = 0
Q_8H = 0
Q_24H= 0把上面的地址、主题、引脚替换成你项目里的即可。
plc.put
lua
plc.put(ip, remote_addr, local_addr, len)通过 UDP 把本地 local_addr 起始的 len 个 D 寄存器写到远程设备。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | ip | string | 是 | — | 远程设备 IP |
| 2 | remote_addr | integer | 是 | — | 远程起始 D 编号 |
| 3 | local_addr | integer | 是 | — | 本地起始 D 编号 |
| 4 | len | integer | 是 | — | D 寄存器数量,最大 255 |
返回值
无返回值。
说明
- 与
plc.get同一套协议(UDP 25388),限制也一样:只能写 D 区、一次最多 255 点、要在同一局域网内。 - 对方不回执:写成功与否无法从返回值判断,要确认就过一会用
plc.get把那几个 D 读回来核对。
实用例程
lua
mqtt.publish(HomeMqtt,"<设备ID或凭据>/Status",json.encode(doorStatus),0,1)--设置为保留消息
end
end
statusTimer= timer.start(500,refreshDoorStatus)
-----------------状态反馈处理结束--------------------------
x=modbus_tcp_server.start(502,1) --创建一个modbus-tcp服务,用于外部连接过来同步时间等
---------------------开始向主机反馈状态----------------------------------
local SheFang
local Ding
local WarnReset
local Warning
function StatusTo()
if SheFang~= plc.d(16) then
SheFang=plc.d(16)
plc.put("192.168.1.100",31,16,1)---发送设防状态给后门
plc.put("192.168.1.100",34,16,1)---发送设防状态给右前门
end
if Ding~= plc.m(7) then
Ding = plc.m(7)
local DingTo=
{
IsOn=plc.m(7)==1
}
mqtt.publish(HomeMqtt,"Home/Ding/Status",json.encode(DingTo),0,1)--推送叮铛状态
end
if Warning~= plc.m(18) then --M18是设防状态把上面的地址、主题、引脚替换成你项目里的即可。
plc.plc_name
lua
plc.plc_name() --> string -- 读
plc.plc_name(name) --> string -- 写读取或设置设备名。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | name | string | 否 | — | 省略为读取当前设备名;提供为设置,最长 32 字节 |
返回值
| 类型 | 说明 |
|---|---|
| string | 读取时返回当前设备名;设置成功返回新名,失败返回空串 "" |
实用例程
lua
function isYearGreaterOrEqualTo2024()
local currentYear = tonumber(os.date("%Y", os.time())) -- 提取当前年份
return currentYear >= 2024
end
-- MQTT配置参数
mqttHost = "192.168.1.100"
mqttPort = 1883
username = "BWJ"
password = "<设备ID或凭据>"
telemetryTopic = "v1/devices/me/telemetry"
DeviceName = "ZJG-TD-01"
plc.plc_name(DeviceName)--设置设备名称
-- 建立MQTT客户端
mqttClient = mqtt.creat(mqttHost, mqttPort, DeviceName, username, password)
-- 注册MQTT连接成功回调函数
mqtt.reg(mqttClient, mqtt.CONNECTED, function()
print("MQTT Connected <设备ID或凭据>")
end)
-- 注册MQTT网络断开事件把上面的地址、主题、引脚替换成你项目里的即可。
plc.led
lua
plc.led(mode)控制状态指示灯。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | mode | integer | 是 | — | 0=熄灭,1=常亮,其它值(含 2)=交回系统自动控制 |
返回值
无返回值。
plc.rtc_set
lua
plc.rtc_set(timestamp) --> true | 无
plc.rtc_set(year, mon, day, hour, min, sec) --> true | 无设置设备 RTC 时钟。支持传 Unix 时间戳(1 个参数),或年月日时分秒(6 个参数)。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | timestamp / year | integer | 是 | — | 1 参模式为 Unix 秒;6 参模式为年 |
| 2-6 | mon day hour min sec | integer | 6 参模式必填 | — | 月、日、时、分、秒 |
返回值
| 类型 | 说明 |
|---|---|
| boolean | 成功返回 true;参数个数不是 1 或 6、或时间戳换算失败时不返回值 |
示例
lua
plc.rtc_set(2026, 8, 14, 10, 30, 0)
-- 或
plc.rtc_set(os.time())plc.sta_autochn
lua
plc.sta_autochn(enable)开关 WiFi 射频自动校准。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | enable | integer | 是 | — | 非 0 开启,0 关闭 |
返回值
无返回值。
实用例程
lua
-- 宁夏设备监控脚本 - 基于nx20250901.md
-- 功能:采集纺织机数据并通过MQTT发送
--配置plc wifi
plc.ap_ssid("")
plc.sta_ssid("<设备ID或凭据>")--wifi账号
plc.sta_password("<设备ID或凭据>!")--wifi密码
plc.sta_dhcp(1)--开启wifi的DHCP
plc.sta_autochn(1)--开启天线校准
local table_result = plc.AI(
{
cmd="set",
data={
cmdtype="set_cloud",
name="JDD",
pass="<设备ID或凭据>",
enable=true
}
}
)--设置云服务
function isYearGreaterOrEqualTo2024()
local currentYear = tonumber(os.date("%Y", os.time())) -- 提取当前年份
return currentYear >= 2024
end
-- MQTT配置参数
mqttHost = "192.168.1.100"把上面的地址、主题、引脚替换成你项目里的即可。
plc.lua_password
lua
plc.lua_password(password)设置 Lua 脚本的访问保护密码。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | password | string | 是 | — | 保护密码 |
返回值
无返回值。
plc.plc_password
lua
plc.plc_password(password)设置梯形图程序的保护密码。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | password | string | 是 | — | 保护密码 |
返回值
无返回值。
plc.kv_set
lua
plc.kv_set(key, value) --> boolean写入一条掉电不丢失的键值数据。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | key | string | 是 | — | 键名 |
| 2 | value | string | 是 | — | 值,按字节串存储,可含 \0 |
返回值
| 类型 | 说明 |
|---|---|
| boolean | 是否写入成功 |
示例
lua
plc.kv_set("site_id", "workshop-A")plc.kv_get
lua
plc.kv_get(key) --> true -- 读到了
plc.kv_get(key) --> false, string, integer -- 没读到读取 plc.kv_set 存入的键值数据。单次最多读 256 字节。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | key | string | 是 | — | 键名 |
返回值
| 类型 | 说明 |
|---|---|
| boolean | 是否读取成功 |
| string, integer | 仅在失败时追加返回缓冲区内容和长度 |
说明
plc.base64_encode
lua
plc.base64_encode(str) --> stringBase64 编码。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | str | string | 是 | — | 原始字节串 |
返回值
| 类型 | 说明 |
|---|---|
| string | Base64 字符串 |
plc.base64_decode
lua
plc.base64_decode(str) --> table | nilBase64 解码,结果放在一个 table 里。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | str | string | 是 | — | Base64 字符串 |
返回值
| 类型 | 说明 |
|---|---|
| table | { len = 数据长度, str = 解码后的字节串 } |
| nil | 内部内存分配失败时返回 nil |
示例
lua
local enc = plc.base64_encode("Hello LPPLC")
local dec = plc.base64_decode(enc)
print(dec.len, dec.str)说明
- 需要纯字符串返回值的场景更推荐
encoder.tobase64/encoder.frombase64。
plc.aes_encode
lua
plc.aes_encode(str) --> string用设备内置密钥做 AES 加密。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | str | string | 是 | — | 明文 |
返回值
| 类型 | 说明 |
|---|---|
| string | 密文字节串 |
说明
- 密钥由设备固化,脚本无法指定,模式固定为 CBC。要自带密钥、自选 ECB / CBC / CTR,用
crypto模块, 但它只在部分机型上提供(LP3232、LP3288(ESP32-S3 平台),LP8910、LP8911、LP8912、LP8913、LP8915、LP8916、LP8922(4G 平台),LP2300、LP2323(STM32H750 平台),以及上位机的内置软设备与软 PLC 模拟器);没有该模块的机型仍只能用它。详见加密模块。 - 长度不是 16 的整数倍时,只有前面向下取整到 16 倍数的部分被加密,尾部字节原样保留明文; 不足 16 字节则整段不加密、原样返回。 所以这两个函数不是传输加密,只能对定长或自己补齐到 16 倍数以上的数据做混淆; 变长报文请自行补零/加分隔后再加密,并在对端按同样规则还原。
plc.aes_decode
lua
plc.aes_decode(str) --> string对 plc.aes_encode 的结果解密。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | str | string | 是 | — | 密文 |
返回值
| 类型 | 说明 |
|---|---|
| string | 明文 |
plc.bite
lua
plc.bite(data, order) --> 0 | 1 -- 读某一位
plc.bite(data, order, value) --> integer -- 写某一位,返回修改后的整数对一个整数按位读写。常用于把 16 个开关量打包进一个 D 寄存器。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | data | integer | 是 | — | 被操作的整数,按 32 位处理 |
| 2 | order | integer | 是 | — | 位序号,从 0 起。>= 32 时读返回 0、写不改变 |
| 3 | value | boolean | number | 否 | — | 传入即为写位:真置 1、假置 0 |
返回值
| 类型 | 说明 |
|---|---|
| integer | 读时返回该位的 0/1;写时返回修改后的整数 |
示例
lua
-- 把 D100 的第 3 位置 1
plc.d(100, plc.bite(plc.d(100), 3, 1))
-- 判断 D100 的第 5 位
if plc.bite(plc.d(100), 5) == 1 then print("bit5 ON") endplc.AI
lua
plc.AI(value) --> converted -- 类型转换
plc.AI(cmd_table) --> result_table -- 命令模式一个多用途入口。传入普通值时做智能类型转换;传入含 cmd 字段的 table 时执行内置命令。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | value | any | 是 | — | 见下面两种模式 |
类型转换模式
| 输入 | 返回 |
|---|---|
| string | 能解析成整数 → integer;能解析成浮点 → number;"true"/"false" → boolean;否则原样返回 string |
| number | 转成字符串(浮点会去掉尾部多余的 0) |
| boolean | "true" / "false" |
| nil | "nil" |
不含 cmd 的 table | "[table]" |
| function / userdata / thread | "[function]" / "[userdata]" / "[thread]" |
命令模式
传入 { cmd = "命令名", data = 载荷 },返回 { cmd = 命令名, errno = 错误码, errmsg = 错误信息, data = 结果 },errno 为 0 表示成功,未知命令返回 -1。
ESP32 固件支持的命令:
| cmd | 作用 |
|---|---|
"echo" | 原样回显 data,用于连通性自检 |
"ShowMe" | 返回 WiFi 相关信息 |
"set" | 设置设备参数 |
"config" | 批量部署配置,用于一次性下发整机参数 |
示例
lua
print(plc.AI("123")) -- 123(integer)
print(plc.AI("3.14")) -- 3.14(number)
print(plc.AI(true)) -- "true"
local r = plc.AI({ cmd = "echo", data = "ping" })
print(r.errno, r.data) -- 0 ping说明
"line convert"(插值转换)和"kalman filter"(卡尔曼滤波)两个命令只在 Windows / Linux 上位机版本里编译,ESP32 固件不含,调用会返回errno = -1。
实用例程
lua
-- 宁夏设备监控脚本 - 基于nx20250901.md
-- 功能:采集纺织机数据并通过MQTT发送
--配置plc wifi
plc.ap_ssid("")
plc.sta_ssid("<设备ID或凭据>")--wifi账号
plc.sta_password("<设备ID或凭据>!")--wifi密码
plc.sta_dhcp(1)--开启wifi的DHCP
plc.sta_autochn(1)--开启天线校准
local table_result = plc.AI(
{
cmd="set",
data={
cmdtype="set_cloud",
name="JDD",
pass="<设备ID或凭据>",
enable=true
}
}
)--设置云服务
function isYearGreaterOrEqualTo2024()
local currentYear = tonumber(os.date("%Y", os.time())) -- 提取当前年份
return currentYear >= 2024
end
-- MQTT配置参数
mqttHost = "192.168.1.100"
mqttPort = 1883把上面的地址、主题、引脚替换成你项目里的即可。
例程
每个例程都是可直接下载运行的完整脚本:注册完定时器后脚本就结束,固件自动进入消息泵。 API 只用本章已文档化的函数;统一模板「场景 / 完整代码 / 要点 / 验证方法 / 注意事项」。
例程 1:位元件读写 —— 用 X/Y 和 M 做梯形图与 Lua 的握手
适用:LP3201 / LP3202 / LP3203 / LP3222 / LP3232 / LP3288 / 软PLC模拟器 | 依赖模块:plc timer | 难度:★☆☆
场景:梯形图算得了高速、确定性的逻辑,Lua 擅长通信和字符串。两侧分工时要有一套约定好的信号位:这里 X0 让 Lua 干活、Lua 干完置 M10、梯形图收到 M10 就去清 X0 侧的锁存。这样谁也不会抢同一个点。
完整代码(可直接下载运行):
lua
-- 握手约定:X0 = 请求,M10 = Lua 已处理;梯形图看到 M10 就复位自己的请求条件
local last_req = 0
timer.start(200, function()
local req = plc.x(0) -- 读物理输入 X0(0/1)
if req == 1 and last_req == 0 then -- 上升沿
plc.d(300, plc.d(300) + 1) -- 计一次数到 D300
plc.y(0, 1) -- 点亮输出 Y0
plc.m(10, 1) -- 通知梯形图:已处理
print("已处理第", plc.d(300), "次请求")
elseif req == 0 and last_req == 1 then
plc.y(0, 0)
plc.m(10, 0) -- 请求撤销,握手位跟着复位
end
last_req = req
end)要点:
- 七个位元件(X/Y/M/MS/S/TS/CS)共用同一套约定:1 参读、2 参写,写入返回写后的
0/1。 value可以传true/false也可以传整数,非 0 即 ON。- 地址是十进制:
plc.x(10)是第 10 号输入点,不做八进制换算。 plc.ts(5)/plc.cs(3)能直接读定时器/计数器触点,不用去翻他们的当前值寄存器。- 地址超范围不报错:读返回
0、写被静默忽略 —— 所以「写了没反应」先查地址范围(见注意事项)。
验证方法:
- 下载运行后让 X0 接通一下再断开:日志打印
已处理第 1 次请求,Y0 短暂吸合,D300 变为 1。 - 上位机「在线监视」里看 M10 随请求一起置 ON / 复位(握手位真的在动)。
- 再通断几次 X0:D300 逐次 +1,不多不少(上升沿只算一次)。
- 故意用超范围地址(比如
plc.m(99999, 1)):不报错但也不生效 —— 记住这个"静默失败"手感。
注意事项:
- X0 抖动会被重复计数:程序里必须像上面那样自己存"上一拍状态"做上升沿。
- 梯形图和 Lua 写同一个 Y?约定同一时刻只有一侧写,另一侧只读,否则谁也说不清最后那个值是谁给的。
- 位元件读取返回
0/1整数,判断用== 1;if plc.m(10) then在未置位时也是真值。
例程 2:16 位 / 32 位 / 浮点 / 字符串 —— 四种字数据一次讲清
适用:同上 | 依赖模块:plc | 难度:★★☆
场景:现场计数器值超过 32767、温度是 25.3 这种小数、要给下位屏送一串文字 —— 对应的分别是 dd(32 位整数)、df(浮点)、dstr(字符串)。这一段把四种写法的落点和地址占用一次性摆清楚,照着抄就不会错。
完整代码(可直接下载运行):
lua
-- 地址规划:D100=温度(浮点占 D100-D101),D110=产量(32位占 D110-D111),
-- D120=计数(16位),D130=屏标题(字符串占 D130 起)
plc.df(100, 25.3) -- 浮点写 D100-D101(必须用 df)
plc.dd(110, 1234567) -- 32 位整数(超过 32767 就不能用 d)
plc.d(120, 32767) -- 16 位有符号整数,上限 32767
plc.dstr(130, "Line-A") -- 字符串,每寄存器 2 字符,这里占 3 个 D
timer.start(2000, function()
local t = plc.df(100)
local cnt = plc.dd(110)
local n = plc.d(120)
local s = plc.dstr(130)
print(string.format("温度=%.1f 产量=%d 计数=%d 标题=%s", t, cnt, n, s))
end)要点:
- 32 位和浮点没有属性式写法:
plc.DD110/plc.DF100读出来是nil而且不报错,一律用plc.dd()/plc.df()。 plc.d(addr, v)是 16 位有符号(±32767),更大的数必须升级为plc.dd(占两个连续 D)。- 32 位类型占两个寄存器,规划地址时要留出空位:D100 放浮点就别再把别的数据写到 D101。
plc.dstr每个寄存器装 2 个字符,上限 32 个寄存器(64 字符),遇到 0 高字节认为字符串结束。- 定时器当前值用
plc.tn(n)、计数器用plc.cn(n)(C200 以上是 32 位)。
验证方法:
- 下载后每 2 秒日志打印一行含四个值的字符串,逐个对得上。
- 上位机把 D100 / D101 按浮点格式查看才是 25.3(按整数看是另一串数字,别以为写错了)。
- 试着写成
plc.DF100读一次:日志里温度变成 nil —— 这就是「属性式写法不生效」的真实现象。 - 再往 D101 写一个值,回头看 D100 的浮点是否被破坏(直观看到地址重叠的后果)。
注意事项:
- 用
plc.d写过 32767 的值会静默溢出;该用dd的地方用了d,读出来是负数。 - 浮点读到几万这种离谱数字,多半是字序问题(见 com_modbus 的
set_float_abcd)。 - 地址超范围照样不报错(读
0、写忽略),调试时先确认范围。
例程 3:定时采集 + 超温联锁 + 结果搬到另一台设备
适用:同上(需两台设备同网段)| 依赖模块:plc timer | 难度:★★☆
场景:本机的梯形图/模拟量算出结果后,一方面本地做联锁保护(超温就切断输出),一方面通过 UDP 把整段 D 区同步给同网段的另一台 LPPLC —— 这是多台设备分工干活时最常见的一跳。
完整代码(可直接下载运行):
lua
timer.start(2000, function()
local temp = plc.df(100) -- 读浮点温度
local run = plc.m(0) -- 读运行允许标志(梯形图给)
if run == 1 and temp > 80 then
plc.y(0, 1) -- 超温联锁:切断/报警
print("超温报警", temp)
else
plc.y(0, 0)
end
-- 把本地 D200-D209 共 10 个寄存器搬到远端 D100 起
plc.put("192.168.1.50", 100, 200, 10)
end)要点:
plc.put(ip, remote_addr, local_addr, len)是本机主动发的一次 UDP 写,参数是"远端起始地址、本端起始地址、长度",顺序别写反。plc.get(ip, remote_addr, local_addr, len)是反向:向远端要数据、写回本地 D 区。- 周期任务用
timer.start驱动,不要写主循环 —— 会和 modbus / MQTT 的回调抢同一条消息队列。 plc.put没有返回值,成功与否只能在对端读回来核对。
验证方法:
- 两台设备同网段、对端 IP 改成本地址,下载运行。
- 本机写一组已知值进 D200-D209(上位机写入),2 秒内对端 D100-D109 应出现同样的数值。
- 本机把 D100 / D101 的浮点值改成 81 → Y0 吸合、日志打印
超温报警;改回常温值 → Y0 断开。 - 拔掉网线:
plc.put静默失败、对端数据停在最后一帧 —— 依赖 UDP 的链路要自己在应用层做超时判断和报警。
注意事项:
plc.put/plc.get基于 UDP,丢包不重传也无返回;关键数据要在应用层自己做确认和补发。plc.y(0, 1)是联锁的目的地,别让梯形图也写同一个 Y —— 会互相拉扯。- 搬一整段数据前先确认地址范围与数据宽度(32 位占两个寄存器,别只搬一半)。
注意事项
- 32 位类型(
dd/df/dsd/dsf/rd/rf)占两个连续寄存器,与 16 位数据混用时应注意避免地址重叠。 - 软元件地址超范围不会报错:读返回
0,写被静默忽略。调试时先确认地址在有效范围内。 - 网络参数改完只写进参数区,一般要重启(或重新联网)才生效,不要在运行中频繁改;写错也不报错,改完一律读回来核一遍(规则见本章开头「网络配置」一节)。
plc.ap_password填少于 8 个字符会让本机热点变成不加密的开放网络,函数本身不报错。plc.kv_get的返回值约定有问题(见该函数说明),新代码请优先用fdb或ini做持久化。
函数速查表
下表列出本库全部函数与方法(含尚未单独成节的),点「说明」可跳转到对应小节。签名按通用记法:括号内按顺序列全参数,方括号里的可以省略(不传走默认值),... 表示还可继续传同类参数;h: 开头的是对象方法,先用库级函数拿回句柄再冒号调用。
| 方法与签名 | 作用 | 说明 |
|---|---|---|
plc.aes_decode(encrypted_string) | Lua接口AES解密函数 | 本文开头 |
plc.aes_encode(string) | Lua接口AES加密函数 | 本文开头 |
plc.AI(…) | — | 本文开头 |
plc.ap_gateway(integer, ...) | — | 本文开头 |
plc.ap_ip(integer, ...) | — | 本文开头 |
plc.ap_mask(integer, ...) | — | 本文开头 |
plc.ap_password(string, ...) | — | 本文开头 |
plc.ap_ssid(string, ...) | — | 本文开头 |
plc.base64_decode(encoded_string) | Lua接口Base64解码函数 | 本文开头 |
plc.base64_encode(string) | Lua接口Base64编码函数 | 本文开头 |
plc.bite(data, bit_position) | 位操作函数 | 本文开头 |
plc.cloud_bind(bind_table) | 云服务绑定函数 | 本文开头 |
plc.cloud_compute(json_string) | 云服务计算函数 | 本文开头 |
plc.cloud_publish(...) | 云服务数据发布函数 | 本文开头 |
plc.cloud_reg(message_type, callback_function) | 云服务注册函数 | 本文开头 |
plc.cloud_status(…) | 只读标量,跨任务读按既有惯例不加锁。 | 本文开头 |
plc.cloud_subscribe(...) | 云服务数据订阅函数 | 本文开头 |
plc.cn(integer, ...) | — | 本文开头 |
plc.cs(integer, ...) | — | 本文开头 |
plc.d(integer, integer, ...) | — | 本文开头 |
plc.dd(address) | PLC DD寄存器读写函数 | 本文开头 |
plc.df(integer, ...) | — | 本文开头 |
plc.ds(integer, ...) | — | 本文开头 |
plc.dsd(integer, ...) | — | 本文开头 |
plc.dsf(integer, ...) | — | 本文开头 |
plc.dstr(integer, ...) | — | 本文开头 |
plc.eth_dhcp(integer, ...) | — | 本文开头 |
plc.eth_gateway(integer, ...) | — | 本文开头 |
plc.eth_ip(integer, ...) | — | 本文开头 |
plc.eth_mask(integer, ...) | — | 本文开头 |
plc.get(string, integer, integer, integer) | — | 本文开头 |
plc.kv_get | — | 本文开头 |
plc.kv_set | — | 本文开头 |
plc.led(mode) | LED控制函数 | 本文开头 |
plc.lua_password(password_string) | Lua密码设置函数 | 本文开头 |
plc.m(integer, ...) | — | 本文开头 |
plc.ms(integer, ...) | — | 本文开头 |
plc.plc_name | — | 本文开头 |
plc.plc_password(password_string) | PLC密码设置函数 | 本文开头 |
plc.put(string, integer, integer, integer) | — | 本文开头 |
plc.r(address) | PLC R寄存器读写函数 | 本文开头 |
plc.rd(address) | PLC RD寄存器读写函数 | 本文开头 |
plc.recv_sms() | 短信接收函数 | 跳转 |
plc.rf(address) | PLC RF寄存器读写函数 | 本文开头 |
plc.rstr(address) | PLC R字符串寄存器读写函数 | 本文开头 |
plc.rtc_set(integer, integer, integer, integer, integer, integer, ...) | — | 本文开头 |
plc.s(integer, ...) | — | 本文开头 |
plc.send_sms(phone_number, message) | 短信发送函数 | 跳转 |
plc.sms_recv() | 短信接收函数 | 本文开头 |
plc.sms_send(phone_number, message) | 短信发送函数 | 本文开头 |
plc.sta_autochn | — | 本文开头 |
plc.sta_dhcp(integer, ...) | — | 本文开头 |
plc.sta_gateway(integer, ...) | — | 本文开头 |
plc.sta_ip(integer, ...) | — | 本文开头 |
plc.sta_mask(integer, ...) | — | 本文开头 |
plc.sta_password(string, ...) | — | 本文开头 |
plc.sta_ssid(string, ...) | — | 本文开头 |
plc.tn(integer, ...) | — | 本文开头 |
plc.ts(integer, ...) | — | 本文开头 |
plc.x(integer, ...) | — | 本文开头 |
plc.y(integer, ...) | — | 本文开头 |
plc.recv_sms
- 作用:短信接收函数
- 调用形态:
plc.recv_sms()(库级函数) - 参数:无参数
- 返回:无
- 可用机型:软 PLC 模拟器 / 上位机
plc.send_sms
- 作用:短信发送函数
- 调用形态:
plc.send_sms(phone_number, message)(库级函数) - 参数:2 个参数:第 1 个为字符串(必填)、第 2 个为字符串(必填)
- 返回:无
- 可用机型:软 PLC 模拟器 / 上位机