欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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)

 

上一篇: 杨辉三角代码

下一篇: 墨汁