matplotlib嵌入tkinter并绘制动态图片,数据来源读取西门子plc
程序员文章站
2022-03-09 20:17:09
...
import numpy as np
from tkinter import *
from tkinter import messagebox
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
# 创建画布需要的库
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import snap7
import struct
import time
import math
from rope_length_2_point_position import RopeLength2APointPosition
depth = -29700
def GetBytesString(dbListContent, dbListType):
bytesString = bytes()
for i in range(len(dbListContent)):
bytesString += struct.pack('>' + dbListType[i], dbListContent[i])
## >表示大端模式,西门子plc使用大端模式
fmt = '>'
for i in dbListType:
fmt += i
## 验证字节串转换是否正确
restore = struct.unpack(fmt, bytesString)
return bytesString
# 抛物线动态绘制函数
def drawImg():
global fig
fig = plt.figure(figsize=(6.5, 7), edgecolor='blue')
global ax
ax.clear()
# xy 轴等比例
ax.set_aspect(1)
ax.set_xlim(-10000, 10000)
ax.set_ylim(-40000, 20000)
global aPointXHis
global aPointYHis
global aPointXHis_left
global aPointYHis_left
global myplc
draft = 3000
diameter = 1000
dt = 1
# 读臂架角度
data = myplc.read_area(0x84, 1, 88, 4)
theta = snap7.util.get_real(data, 0)
# 读取转速值
data = myplc.read_area(0x84, 2, 20, 4)
rollerLiftSpeed = snap7.util.get_real(data, 0)
data = myplc.read_area(0x84, 2, 24, 4)
rollerCloseSpeed = snap7.util.get_real(data, 0)
# 读钢丝绳长
data = myplc.read_area(0x84, 1, 92, 4)
liftRopeLength = snap7.util.get_real(data, 0)
data = myplc.read_area(0x84, 1, 100, 4)
closeRopeLength = snap7.util.get_real(data, 0)
deltaLiftTurns = rollerLiftSpeed * dt
deltaCloseTurns = rollerCloseSpeed * dt
liftRopeLength += + deltaLiftTurns * diameter * math.pi
closeRopeLength += + deltaCloseTurns * diameter * math.pi
xa, ya, xb, yb, xc, yc, xd, yd = RopeLength2APointPosition(liftRopeLength, closeRopeLength, theta, draft)
if ya > depth:
pumpOilPressure = 999
if xa < -333:
pumpOilPressure = 9999
xa = -330
else:
pumpOilPressure = 0
if xa < 0:
xa = 0
# 写钢丝绳长度值 theta alpha draft
dbListContent_init = [liftRopeLength]
## 在这个list中输入数据类型,h 是short的缩写, f 是struct库中对单精度浮点数的缩写,对应plc的Real型; >表示大端模式,西门子plc要用大端模式
dbListType_init = ['f']
bytesString_init = GetBytesString(dbListContent_init, dbListType_init)
# 第三个参数表示要写入的变量的起始偏移量
myplc.write_area(0x84, 1, 92, bytesString_init)
# 写钢丝绳长度值 theta alpha draft
dbListContent_init = [closeRopeLength]
## 在这个list中输入数据类型,h 是short的缩写, f 是struct库中对单精度浮点数的缩写,对应plc的Real型; >表示大端模式,西门子plc要用大端模式
dbListType_init = ['f']
bytesString_init = GetBytesString(dbListContent_init, dbListType_init)
# 第三个参数表示要写入的变量的起始偏移量
myplc.write_area(0x84, 1, 100, bytesString_init)
# 写液压泵压力
dbListContent_init = [pumpOilPressure]
## 在这个list中输入数据类型,h 是short的缩写, f 是struct库中对单精度浮点数的缩写,对应plc的Real型; >表示大端模式,西门子plc要用大端模式
dbListType_init = ['h']
bytesString_init = GetBytesString(dbListContent_init, dbListType_init)
# 第三个参数表示要写入的变量的起始偏移量
myplc.write_area(0x84, 1, 60, bytesString_init)
aPointXHis.append(xa)
aPointYHis.append(ya)
aPointXHis_left.append(-xa)
aPointYHis_left.append(ya)
outlineX = [xb, xc, xa, xb, xd, -xd, -xb, -xa, xc, -xb]
outlineY = [yb, yc, ya, yb, yd, yd, yb, ya, yc, yb]
ax.plot(outlineX, outlineY)
# 画点
pointSize = 10
for ii in range(len(aPointXHis)):
ax.scatter(aPointXHis[ii], aPointYHis[ii], c=['r'], s=pointSize)
ax.scatter(aPointXHis_left[ii], aPointYHis_left[ii], c=['r'], s=pointSize)
canvas.draw()
global afterHandler
afterHandler = root.after(1000, drawImg)
def ClearPlot():
global aPointXHis
global aPointYHis
global aPointXHis_left
global aPointYHis_left
aPointXHis.clear()
aPointYHis.clear()
aPointXHis_left.clear()
aPointYHis_left.clear()
root = Tk()
root.title("tkinter + Matplotlib")
root.geometry('700x750')
Label(root).place(x=0, y=0, width=700, height=50)
Button(root, text='清空', command=ClearPlot).grid(row=3, column=2, columnspan=3)
## s7 client
myplc = snap7.client.Client()
myplc.connect('192.168.0.2', rack=0, slot=2) # 建立连接,TIA看ip 机架 插槽
if myplc.get_connected():
print('Connect succeed!')
# 创建一个容器, 没有画布时的背景
frame1 = Frame(root, bg="#ffffff")
frame1.place(x=5, y=50, width=690, height=700)
# plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
fig = plt.figure(figsize=(6.5, 7), edgecolor='blue')
ax = fig.add_subplot(111)
# xy 轴等比例
ax.set_aspect(1)
# 定义刻度
ax.set_xlim(-10000, 10000)
ax.set_ylim(-40000, 20000)
canvas = FigureCanvasTkAgg(fig, master=frame1)
canvas.draw()
# 显示画布
canvas.get_tk_widget().place(x=0, y=0)
i = 0
# 定义存储坐标的空数组
aPointXHis = []
aPointYHis = []
aPointXHis_left = []
aPointYHis_left = []
drawImg()
def on_closing():
root.after_cancel(afterHandler)
answer = messagebox.askokcancel("退出", "确定退出吗?")
if answer:
plt.close('all')
root.destroy()
else:
root.after(1000, drawImg)
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
import math
import time
r2d = 180 / math.pi
t0 = time.time()
def RopeLengthToPullryHeight(liftRopeLength, closeRopeLength, theta, draft):
mastRightPointHeight = 6629.5953
mastLength = 26402.2989
mastLiftRollerDis = 3754.9623
mastCloseRollerDis = 6146.4088
mastLiftRollerVerticalAngle = 18 * math.pi / 180
mastCloseRollerVerticalAngle = 37 * math.pi / 180
theta = theta * math.pi / 180
pulleyTimes = 5
theta2 = (math.pi / 2 - theta) + mastLiftRollerVerticalAngle
mastRightLiftRopeLength = math.sqrt(mastLength * mastLength + mastLiftRollerDis * mastLiftRollerDis - 2 * mastLength * mastLiftRollerDis * math.cos(theta2))
theta3 = (math.pi / 2 - theta) + mastCloseRollerVerticalAngle
mastRightCloseRopeLength = math.sqrt(mastLength * mastLength + mastCloseRollerDis * mastCloseRollerDis - 2 * mastLength * mastCloseRollerDis * math.cos(theta3))
mastLeftLiftRopeLength = liftRopeLength - mastRightLiftRopeLength
mastLeftCloseRopeLength = closeRopeLength - mastRightCloseRopeLength
liftPulleyHeight = mastRightPointHeight + mastLength * math.sin(theta) - draft - mastLeftLiftRopeLength
ropeLengthDifference = mastLeftCloseRopeLength - mastLeftLiftRopeLength
pulleyHeightDifference = ropeLengthDifference / pulleyTimes
closePulleyHeight = liftPulleyHeight - pulleyHeightDifference
return liftPulleyHeight, closePulleyHeight
def PulleyPositionToAPointPoistion(yd, yc):
# A点->抓斗尖端 B点->撑杆和抓斗连接点 C点->闭斗滑轮 D点->提升滑轮
# g->D点到中线距离减去C点到中线的距离
g = 598.8471
# b->DB杆长度
b = 5542.6942
# d->CB杆长度
d = 3020.8448
# a->AC杆长度
a = 3968.9751
# e->AB杆长度
e = 3399.4051
theta2 = math.acos((a * a + d * d - e * e) / (2 * a * d))
theta2_d = theta2 * r2d
theta4 = math.atan(g / (yd - yc))
theta4_d = theta4 * r2d
c = math.sqrt(g * g + (yd - yc) * (yd - yc))
theta3 = math.acos((c * c + d * d - b * b) / (2 * c * d))
theta3_d = theta3 * r2d
theta1 = math.pi - theta4 - theta3 - theta2
theta1_d = theta1 * r2d
ya = yc - a * math.cos(theta1)
xa = a * math.sin(theta1)
thetaCDB = math.acos((c * c + b * b - d * d) / (2 * c * b))
thetaBD = thetaCDB - theta4
xb = b * math.sin(abs(thetaBD))
yb = yd - b * math.cos(thetaBD)
xc = 0
xd = 598.8471
l_AB = math.sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb))
l_AC = math.sqrt((xa - xc) * (xa - xc) + (ya - yc) * (ya - yc))
l_BC = math.sqrt((xb - xc) * (xb - xc) + (yb - yc) * (yb - yc))
l_BD = math.sqrt((xb - xd) * (xb - xd) + (yb - yd) * (yb - yd))
print("xa={}, ya={}, open angle={}, time{}".format(xa, ya, theta1_d*2+9.57, time.time()-t0))
return xa, ya, xb, yb, xc, yc, xd, yd
def RopeLength2APointPosition(liftRopeLength, closeRopeLength, theta, draft):
liftPulleyHeight, closePulleyHeight = RopeLengthToPullryHeight(liftRopeLength, closeRopeLength, theta, draft)
if (liftPulleyHeight - closePulleyHeight) > 7770:
closePulleyHeight = liftPulleyHeight - 7770
xa, ya, xb, yb, xc, yc, xd, yd = PulleyPositionToAPointPoistion(liftPulleyHeight, closePulleyHeight)
return xa, ya, xb, yb, xc, yc, xd, yd
if __name__ == "__main__":
# # liftPulleyHeight, closePulleyHeight = RopeLengthToPullryHeight(30469, 70661)
# liftPulleyHeight, closePulleyHeight = RopeLengthToPullryHeight(39893, 58094, 45, 3000)
# print(liftPulleyHeight, closePulleyHeight)
#
# print("pulley dis: ", liftPulleyHeight - closePulleyHeight)
liftPulleyHeight = 7329.006270710412
closePulleyHeight = liftPulleyHeight - 7770
print("pulley dis: ", liftPulleyHeight - closePulleyHeight)
PulleyPositionToAPointPoistion(liftPulleyHeight, closePulleyHeight)