我一直在研究一种用Python从PLC传感器获取数据的解决方案,我能够使用cpppo计算出语法等,这对于以假定的序列化方式从标记循环中获取数据来说非常有效。
为了测试这个新的python cpppo解决方案,我将运行python逻辑的机器通过vpn隧道连接到一个plc,并让它poll一个特定的标记/传感器。此标记还通过另一个通过以太网连接到本地机器网络的非python解决方案进行轮询和记录。
问题
有没有人知道我可以用一种方式重新编写下面的代码,这种方式我可以强迫它在一秒钟内轮询3次甚至4次还有什么其他的原因吗?
通过贡献“这个”,我说的是“其他”或“非python”方法似乎在一秒钟内3次记录来自同一个标记的轮询响应,而python cpppo解决方案似乎只记录了每秒最多2次的轮询记录,因此时不时地丢失一个权重值,当一秒钟内有3个权重值时,有时只有每秒2次,所以不总是一秒钟3个值,但有时一秒钟有3个值。
数据
返回的传感器数据用方括号括起来,但以克表示重量,精度为十进制,下面是原始数据的一个小样本。
[610.5999755859375]
[607.5]
[623.5999755859375]
[599.7999877929688]
[602.5999755859375]
[610.0]
Python代码
注意:python逻辑会将传感器的轮询值写入csv文件,但会根据系统日期和时间通过
datetime.now()
生成并插入时间戳记录,但在此之前,我会将值转换为字符串,然后使用str(x).replace('[','').replace(']','')
函数从每个str()
的迭代值中去掉方括号。from cpppo.server.enip.get_attribute import proxy_simple
from datetime import datetime
import time, csv
CsvFile = "C:\\folder\\Test\\Test.csv"
host = "<IPAddress>"
while True:
x, = proxy_simple(host).read("<TagName>")
with open(CsvFile,"a",newline='') as file:
csv_file = csv.writer(file)
for val in x:
y = str(x).replace('[','').replace(']','')
csv_file.writerow([datetime.now(), y])
#time.sleep(0.05)
问题和测试结果
当我将python捕获的csv文件记录与来自标记的其他非python捕获方法的记录进行比较时,python生成的csv记录有时甚至经常丢失。
值得注意的细节(以防万一)
这两个系统之间存在第二个或更少的时间戳差异,因为它们在捕获时生成时间戳。
这个特定的传感器可以在一秒钟内吐出三个值,但并不总是如此;有时一秒钟内吐出一个值,有时一秒钟内吐出两个值,或一秒钟内吐出一个值。
我认为另一个方法使用java,但是这段代码不能用来比较逻辑。
我使用的是python版本
3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Intel)]
和windows 10。结果
python方法csv(缺少相关的
606.6
值)2018-04-12 13:56:42.249408,610.5999755859375
2018-04-12 13:56:42.909309,607.5
2018-04-12 13:56:43.559472,623.5999755859375
2018-04-12 13:56:44.259771,599.7999877929688
2018-04-12 13:56:44.910270,602.5999755859375
2018-04-12 13:56:45.541044,610.0
其他方法csv结果(包含
606.6
值)12/04/2018 13:56:41,610.6
12/04/2018 13:56:42,607.5
12/04/2018 13:56:42,623.6
12/04/2018 13:56:43,606.6
12/04/2018 13:56:43,599.8
12/04/2018 13:56:44,602.6
12/04/2018 13:56:44,610
问题说明:python没有捕获
12/04/2018 13:56:43,606.6
记录,而它是从另一个系统记录的。我怀疑这是由于每个逻辑有一些微小的延迟,因为与其他非python捕获的文件相比,我只看到它缺少值。 最佳答案
代码的关键部分是:
while True:
x, = proxy_simple(host).read("<TagName>")
with open(CsvFile,"a",newline='') as file:
for val in x:
# ...
在伪代码中:
forever:
create proxy
open output file
process values from proxy
你提到传感器可能每秒产生3个值。如果您查看
read()
的实现,它所做的就是设置一个新的reader对象并从中产生所有值。你可能认为你的代码是这样运行的:
创建代理
打开输出文件
过程值
转到3
但事实上,它可能是这样运行的:
创建代理
打开输出文件
过程值
转到1
每次调用
read()
,它都会产生当时所知道的值它不会等待任何新值的到来。尝试以下重构:
source = proxy_simple(host)
with open(CsvFile,"a",newline='') as file:
while True:
for message in source.read("<TagName>"):
for val in message:
# ...
原始代码中的另一个错误是:
x, = proxy_simple(host).read("<TagName>")
如果
read()
返回多个值,则只使用第一个值这就是为什么我在上面建议的代码中有两个for
循环。然后,您将只在每次程序运行时打开输入和输出一次,而不是每次消息打开一次。