使用Python作为上位机实现汇川EASY300实验:PLC与传感器连接实时数据展示及曲线绘制,数据保存至MYSQL数据库
目录
引言
一、产品特点
二、应用场景
三、产品系列
四、市场评价
实验要求
PLC配置
确定PLC的网络配置
确定PLC的通信协议
IO端口映射
GL20-4AD模块配置和参数设置
PYTHON上位机
数值转换
MYSQL数据库创建数据表
QT主程序
引言
汇川EASY系列PLC是一款全场景紧凑型小型PLC,其设计理念来源于真实的使用场景和用户“痛点”,旨在为用户提供易用、高效、可靠的自动化解决方案。以下是对汇川EASY系列PLC的详细介绍:
一、产品特点
- 易实现运动控制和过程控制:
- 四核处理器带来卓越性能,实现纳秒级指令处理速度。
- 32轴高速总线控制,支持同步运动,实现复杂工艺。
- 集成免调试自整定PID算法,快速响应、精准调节,轻松控制温度、压力、流量。
- 易选型、易扩展:
- 全系列8个机型,满足严苛体积、多轴运控、温度控制、通信组网等中小型自动化设备需求。
- 支持扩展卡和模块扩展,特定场景支持2个扩展卡槽,适配通信/模拟量/数字量等。
- 本地扩展GL20系列刀片式IO,采用Push-in端子,免工具接线,节省空间和时间。
- 易互联、易组网:
- 本地集成多种工业网络通信协议,轻松对接数据采集系统和周边设备。
- 支持扩IP模块,实现设备内外网隔离,无需修改设备内部网络配置即可接轨上位系统。
- 双网口设计,省网线省交换机,便捷组网可级联。
- 易编程、模块化:
- 完全自主化的编程软件,持续迭代易用性功能,符合工程师应用习惯。
- 支持ST语言编程,工程师可轻松编写复杂算法和逻辑。
- 支持功能块封装,工艺算法复用;支持离线调试和联合离线仿真,提高编程效率,缩短项目调试周期。
二、应用场景
汇川EASY系列PLC适用于多种应用场景,包括但不限于:
三、产品系列
汇川EASY系列PLC包括多个子系列,如EASY300系列和EASY500系列等,每个系列都有其特定的应用场景和优势:
四、市场评价
汇川EASY系列PLC在市场上受到了广泛的关注和好评。其卓越的性能、易用的特性和广泛的应用场景使得它成为中小型自动化设备领域的热门选择。同时,汇川技术作为国产PLC的领军企业之一,其产品的质量和售后服务也备受用户信赖。
综上所述,汇川EASY系列PLC是一款功能强大、易于使用、灵活扩展、高效互联的全场景紧凑型小型PLC。它能够满足用户对中小型自动化设备的各种需求,为自动化行业的发展贡献自己的力量。
实验要求
实验需要分别测量输入端和输出端压力流量温度,上位机实时显示传感器值,每个量的波形曲线显示,数据保存到MYSQL数据库
编程软件AutoShop是汇川小型PLC的专用上位机软件,它提供了友好的编程和调试环境,支持多种编程语言,并具备丰富、强大的通讯和控制功能。
PLC配置
确定PLC的网络配置
确认PLC的IP地址:确保PLC已经配置了有效的IP地址,以便它可以通过以太网与你的网络中的其他设备通信。
检查网络设置:验证PLC的网络设置(如子网掩码、网关等)是否正确,并确保它与你的网络兼容。
确定PLC的通信协议
确定PLC使用的通信协议,如Modbus TCP、Ethernet/IP、Profinet等。选择使用Python作为上位机进行通信。例如,对于Modbus TCP,使用pymodbus
库。
IO端口映射
对于直接连接到PLC的IO模块或远程IO模块,需要在PLC程序中设置IO映射,以便将特定的物理IO端口映射到PLC内部的逻辑地址或寄存器上
GL20-4AD模块配置和参数设置
对于4-20mA的输入,需要设置相应的输入通道为电流输入模式,使能通道以接收4-20mA(对应0-20000)的模拟量输入,可根据具体需求修改
PYTHON上位机
数值转换
根据购买的传感器量程转换,将PLC返回的数据解析为实际值,这里转换有些误差,有更好的转换方法欢迎指出
# 压力转换
def convert_value(raw_value):
return (raw_value / 20000) * 4
# 流量转换
def convert_value_2(raw_value):
return (raw_value / 20000)* 120
# 温度转换
def convert_value_3(return_value):
return -50 + (return_value / 20000) * (200 - (-50))
MYSQL数据库创建数据表
# MySQL数据库
conn = pymysql.connect(user='root', password='123456', host='localhost', database='plc')
cursor = conn.cursor()
cursor.execute("DROP TABLE IF EXISTS sensor_data")
CREATE TABLE sensor1_data(
id INTEGER PRIMARY KEY AUTO_INCREMENT,
time_stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
input_pressure FLOAT,
input_flow FLOAT,
input_temperature FLOAT,
output_pressure FLOAT,
output_flow FLOAT,
output_temperature FLOAT
)
cursor.execute(createTab)
QT主程序
使用PYQT显示六个传感器实际值到界面,绘制实时曲线并保存到MYSQL数据库
class PlotWindow(QMainWindow):
def __init__(self):
super().__init__()
# 连接PLC
self.plc_ip = '192.168.1.2'
self.plc_port = 502
self.client = ModbusTcpClient(self.plc_ip, port=self.plc_port)
# 设置主窗口
self.setWindowTitle('波形曲线据显示')
self.setGeometry(800, 300, 1200, 1000)
# 创建绘图部件
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.canvas = FigureCanvas(Figure())
layout = QVBoxLayout(self.central_widget)
layout.addWidget(self.canvas)
# 初始化图表
self.fig = self.canvas.figure
self.axs = self.fig.subplots(3, 2)
self.lines = []
self.labels = ['Input Pressure', 'Output Pressure', 'Input Flow', 'Output Flow', 'Input Temperature',
'Output Temperature']
self.x = np.arange(100)
self.y = np.zeros((6, 100))
self.values = np.zeros(6)
for i in range(3):
for j in range(2):
ax = self.axs[i, j]
ax.set_xlim(0, 100)
ax.grid(True)
ax.set_ylabel(self.labels[i * 2 + j])
ax.set_xlabel("Time")
line, = ax.plot(self.x, self.y[i * 2 + j])
self.lines.append(line)
self.axs[0, 0].set_ylim(0, 4000)
self.axs[0, 1].set_ylim(0, 4000)
self.axs[2, 0].set_ylim(-50, 200)
self.axs[2, 1].set_ylim(-50, 200)
self.axs[1, 1].set_ylim(10, 120)
self.axs[1, 0].set_ylim(10, 120)
# 启动一个线程用于读取PLC数据
self.plc_thread = threading.Thread(target=self.read_plc_data)
self.plc_thread.start()
# 定时器更新图表
self.timer = self.fig.canvas.new_timer(interval=100)
self.timer.add_callback(self.update_plot)
self.timer.start()
# 传感器数据界面
self.data_window = QWidget()
self.data_window.setWindowTitle('传感器值')
self.data_window.setGeometry(400, 300, 400, 1000)
layout = QVBoxLayout(self.data_window)
self.labels = []
for i in range(6):
label = QLabel()
self.labels.append(label)
layout.addWidget(label)
self.data_window.show()
def update_plot(self):
for i in range(6):
data = self.y[i]
data[:-1] = data[1:]
data[-1] = self.values1[i]
line = self.lines[i]
line.set_data(self.x, data)
self.axs[i // 2, i % 2].relim()
self.axs[i // 2, i % 2].autoscale_view(True, True, True)
line.set_color('r')
line.set_linewidth(2.0)
self.fig.canvas.draw()
def read_plc_data(self):
while True:
if self.client.connect():
addresses = [100, 101, 102, 103,104, 105]
count = 1
new_values = []
for address in addresses:
response = self.client.read_holding_registers(address, count, unit=1)
if response.isError():
print(f"读取寄存器数据时发生错误:{response}")
else:
new_values.append(response.registers[0])
self.values = new_values
value0_raw=self.values[0]
print(value0_raw)
print(self.values[2])
# print(self.values[1])
if value0_raw<0:
value0_raw=0
value1 = convert_value(self.values[0])
# value1 = convert_value(value0_raw)
value2 = convert_value_2(self.values[1])
value3 = convert_value_3(self.values[2])
value4 = convert_value(self.values[3])
value5 = convert_value_2(self.values[4])
value6 = convert_value_3(self.values[5])
self.values1 = [value1, value4, value2, value5, value3, value6]
sql = ("INSERT INTO sensor1_data "
"(TIME, InputPressure,InputFlow, InputTemperature,OutputPressure, OutputFlow, "
"OutputTemperature) "
"VALUES (%(TIME)s, %(InputPressure)s, %(InputFlow)s, %(InputTemperature)s, %(OutputPressure)s,"
"%(OutputFlow)s,%(OutputTemperature)s)")
data = {
'TIME': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'InputPressure': str(value1),
'InputFlow': str(value2),
'InputTemperature': str(value3),
'OutputPressure': str(value4),
'OutputFlow': str(value5),
'OutputTemperature': str(value6)
}
cursor.execute(sql, data)
conn.commit()
labels_text = [
f'输入侧压力: {value1:.2f} MPa',
f'输入侧流量: {value2:.2f} m³/h',
f'输入侧温度: {value3:.2f} °C',
f'输出侧压力: {value4:.2f} MPa',
f'输出侧流量: {value5:.2f} m³/h',
f'输出侧温度: {value6:.2f} °C'
]
font = QFont()
font.setPointSize(20)
for i in range(6):
self.labels[i].setFont(font)
self.labels[i].setText(labels_text[i])
# 关闭连接
self.client.close()
else:
print("无法连接到PLC")
time.sleep(0.1)
作者:passion更好