基于python和simulink实现控制器对被控对象的远程实时控制
一、 简介
本文以python作为控制器,在simulink中搭建被控对象模型。技术点涉及python与simulink的数据交互、matlab实时仿真技术、python的数据可视化、增量式PID算法的编写等。有别于平时课上simulink仿真实验的模型和控制器同处一处,且仿真时间与CPU真实时间不同步。笔者将控制器和被控对象分离,实现远程的实时控制,与此同时也为硬件在环 / 半实物仿真提供了简单思考。
二、simulink模型展示
利用RTsync实时仿真块实现simulink仿真时间与真实时间的同步,UDP Receive和UDP Send模块用于与python的数据交互。
三、控制器的实现
import socket
import struct
import time
import matplotlib.pyplot as plt
import numpy as np
import os
def main():
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
localaddr = ("127.0.0.1", 54321)
client_addr = ("127.0.0.1", 8082)
udp_socket.bind(localaddr)
count = 0
u,error,error0,delt_u=0,0,0,0
kp=5
ki=0.2
data_collect = []
path = './'
print("Please open the Simulink file under the current working directory")
print("The program is waiting until you run the Simulink file.")
while count<201:
recv_data = udp_socket.recvfrom(1024)
recv_msg = recv_data[0] ##bytes类型
send_addr = recv_data[1]
recv_msg_decode = struct.unpack("d", recv_msg)[0] ##float类型
data_collect.append(recv_msg_decode)
print("Number from MATLAB %s is : %s" % (send_addr, str(recv_msg_decode)))
count += 1
##================做控制运算===================
sp=1
error=sp-recv_msg_decode
print(error)
delt_u=kp*(error-error0)+ki*error ## kp=7 ki=1
u=u+delt_u
error0=error
send_data = u
send_msg_code = struct.pack('<d', send_data) ##Byte类型
server.sendto(send_msg_code, client_addr) ##向matlab发送数据
print(count)
print("--------------------------------------------------------")
# Close the udp socket.
udp_socket.close()
# ------------------------------------ Visualization -----------------------------------------------
# Set the time axis, 30 is the simulation end time that can be modified by user.
index = list(np.linspace(0, 30, (len(data_collect))))
print(len(data_collect))
plt.plot(index, data_collect)
plt.title("Signal Received from Simulink")
plt.xlabel("Time")
plt.ylabel("Received Data")
plt.savefig(os.path.join(path, 'data_figure.png'), dpi=600)
print("Close the figure to restart.")
plt.show()
if __name__ == "__main__":
main()
四、结果曲线
五、完整资源地址