modbus读取威纶通寄存器
问题
威纶通MT6103IP触摸屏,没有网口,有1个RS485接西门子200PLC,空余RS232.
设备是废气吸附处理系统,放在车间西边2楼平台,每天人去手录1天的数据。
想将记录的数值传递到车间东边的办公室,车间中间跨越100来米,想低成本实现。
传递9个数值。
需要解决的问题
- MT6103IP不支持串口透传,帮助里面的地址映射都用不上。
那就自己做个映射,使用宏定时执行,将s7-200的寄存器读到触摸屏的本地寄存器。
macro_command main()
int a[9]={0}
short b[9]={0}
GetData(a[0], "SIEMENS S7-200", VD, 700, 9)
LOWORD(a[0], b[0])
LOWORD(a[1], b[1])
LOWORD(a[2], b[2])
LOWORD(a[3], b[3])
LOWORD(a[4], b[4])
LOWORD(a[5], b[5])
LOWORD(a[6], b[6])
LOWORD(a[7], b[7])
LOWORD(a[8], b[8])
SetData(b[0], "Local HMI", LW, 20, 9)
end macro_command
需要注意从200PLC读的数据是双字,LW是单字,要做一个低位字节读取,温度不大于1000,不会丢失数据
- 网络连接
车间有20米高,走网线人力成本高;走无线AP对射可以。
想使用Lora无须多关心可视,而且Lora已经很便宜了。
塔石181新版也支持了modbus主动轮询,但是固件升级需要寄回原厂操作,不方便。
lora组网,恢复原厂设置,两端节点,框选的设置一样即可,默认2400速率,传递18字节数据也够用。
模块工作模式,选透明。
python进行modbus通信
利用线程,每30秒轮询1次。
#!/usr/bin/env python
# coding: utf-8
from pymodbus.client.sync import ModbusSerialClient
from pymodbus.exceptions import ModbusIOException,InvalidMessageReceivedException
from datetime import datetime
import time
import threading
import taos
class MyData(threading.Thread):
def __init__(self):
super().__init__()
self._stop = threading.Event()
# 串口
self._client=ModbusSerialClient(method='rtu',port="com7",
stopbits = 1, bytesize = 8, parity = 'E' ,
baudrate= 9600)
# tbos
self._conn = taos.connect(host="cmms", user="root", password="taosdata", config="/etc/taos")
self._c1 = self._conn.cursor()
self._c1.execute('use ac')
def stop(self):
self._stop.set()
def close_serial():
_client.close()
def stopped(self):
return self._stop.isSet()
def read(self,unit,fa):
try:
# unit是站号、站点地址
rr = self._client.read_holding_registers(20, 9, unit=unit)
data=rr.registers.copy()
data.append(fa)
dt=datetime.now()
sql='%d,%d,%d,%d,%d,%d,%d,%d,%d,%d' %tuple(data)
sql = '\'%s\',%s' % (dt, sql)
print('data:' + sql + '\n')
self._c1.execute('insert into t values(%s) ' % sql)
except AttributeError:
pass
except ModbusIOException:
print('远端%d,无反应' % unit)
except InvalidMessageReceivedException:
print('远端%d,信息错误' % unit)
def run(self):
while True:
if self.stopped():
return
self.read(0x01, 2)
# sleep
time.sleep(30)
# In[47]:
if __name__ == '__main__':
a=MyData()
a.start()
代码在Jupyter Notebook里测试,而后下载成py。
存储与现实
数据库选用时序数据库TDengine,在github下载ubuntu版,ubuntu跑在PVE虚拟机里。
数据显示,使用Grafana。
注意ubuntu的时区要选到北京。Grafana设置里的时区也选这个。
时间不对不出曲线,光标放在panel上可以看到时间为NAN。
数据的query 譬如 select ts, a from ac.t where factory = 2
ac.t表示数据库ac里的表t。
成绩
原触摸屏投资得以保留,无须更换MT8071IE这种高级屏。
如果利用现有电脑硬件,只需配置3个Lora进行自组网(共2个数据点上传,1个接电脑)。
硬件成本300元,试验与程序花了3个工作日的零碎时间。
如果,grafana突然没数据了,检查是不是数据库的数据值、格式变化了。
昨天的错误是,工厂分类的值填了1,但是query里按2筛选,结果就是grafana拿不到新的数据。