フィルターのクリア

matlab serialport in s-function error with Undefined function 'write' for input arguments of type 'string'

53 ビュー (過去 30 日間)
I have an RS232 communication device and I want to send two different data frames and receive the response in a single step. As far as I know, the serial send block in Simulink's Instrument Control Toolbox doesn't support this functionality. Therefore, I intend to implement this using serialport in an S-Function, but I've encountered some issues. First, here is the MATLAB script I tested, which works correctly.
serialObj = serialport("COM16",115200);
configureTerminator(serialObj,"CR/LF","CR/LF");
flush(serialObj);
dataframe1 = [0x53 0x07 0x01 0x01 0x64 0x60 0x00 0x56 0x45];
dataframe2 = [0x53 0x07 0x02 0x01 0x64 0x60 0x00 0x00 0x45];
write(serialObj,read_node1_pos,"uint8");
response = read(serialObj,13,"uint8");
write(serialObj,read_node2_pos,"uint8");
response = read(serialObj,13,"uint8");
serialObj.delete();
I converted it to an S-Function version, and the code is as follows:
% MySerialSend.m
function [sys,x0,str,ts,simStateCompliance] = GetMotorPos1(t,x,u,flag)
persistent serialObj
switch flag,
case 0,
[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes(serialObj);
case 3,
sys=mdlOutputs(t,x,u,serialObj);
case {1,2,4}
sys=[];
case 9,
sys=mdlTerminate(t,x,u,serialObj);
otherwise
DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
end
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes(serialObj)
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 2;
sizes.NumInputs = 0;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1; % at least one sample time is needed
sys = simsizes(sizes);
x0 = [];
str = [];
ts = [-1 0];
simStateCompliance = 'UnknownSimState';
if isempty(serialObj)
serialObj = serialport("COM16",115200);
configureTerminator(serialObj,"CR/LF","CR/LF");
flush(serialObj);
end
function sys=mdlOutputs(t,x,u,serialObj)
dataframe1 = [0x53 0x07 0x01 0x01 0x64 0x60 0x00 0x56 0x45];
dataframe2 = [0x53 0x07 0x02 0x01 0x64 0x60 0x00 0x00 0x45];
write(serialObj,dataframe1,"uint8");
response = read(serialObj,13,"uint8");
write(serialObj,dataframe2,"uint8");
response = read(serialObj,13,"uint8");
sys = [];
function sys=mdlTerminate(t,x,u,serialObj)
delete(serialObj);
sys = [];
Upon execution, I encountered the following error:
'''
Error:An error occurred while running the simulation and the simulation was terminated
Caused by:
Error in 'RS232_test/S-Function' while executing MATLAB S-function 'MySerialSend', flag = 3 (output), at time 0.0.
Undefined function 'write' for input arguments of type 'string'.
'''
I have searched extensively but couldn't find any similar errors. Could anyone provide some suggestions? If more information is needed, please let me know. Thank you very much!

採用された回答

Walter Roberson
Walter Roberson 2024 年 5 月 21 日 7:40
You do not initialize serialObj within the same scope as the persistent declaration. You end up passing empty serialObj everywhere. You set it inside of a function but the function does not return it to the level above.
  1 件のコメント
You-Cheng
You-Cheng 2024 年 5 月 21 日 8:48
編集済み: You-Cheng 2024 年 5 月 21 日 8:52
Hi, Walter, thanks for your answer!
After modifying the S-Function to:
% MySerialSend.m
function [sys,x0,str,ts,simStateCompliance] = GetMotorPos1(t,x,u,flag)
persistent serialObj
if isempty(serialObj)
serialObj = serialport("COM16",115200);
configureTerminator(serialObj,"CR/LF","CR/LF");
flush(serialObj);
end
switch flag,
case 0,
[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes(serialObj);
case 3,
sys=mdlOutputs(t,x,u,serialObj);
case {1,2,4}
sys=[];
case 9,
sys=mdlTerminate(t,x,u,serialObj);
otherwise
DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
end
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes(serialObj)
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 2;
sizes.NumInputs = 0;
sizes.DirFeedthrough = 0;
sizes.NumSampleTimes = 1; % at least one sample time is needed
sys = simsizes(sizes);
x0 = [];
str = [];
ts = [-1 0];
simStateCompliance = 'UnknownSimState';
function sys=mdlOutputs(t,x,u,serialObj)
dataframe1 = [0x53 0x07 0x01 0x01 0x64 0x60 0x00 0x56 0x45];
dataframe2 = [0x53 0x07 0x02 0x01 0x64 0x60 0x00 0x00 0x45];
write(serialObj,dataframe1,"uint8");
response = read(serialObj,13,"uint8");
write(serialObj,dataframe2,"uint8");
response = read(serialObj,13,"uint8");
sys = [];
function sys=mdlTerminate(t,x,u,serialObj)
delete(serialObj);
sys = [];
it worked successfully!
However, I still have a problem: during the simulation, the simulation time progress bar is not real-time. I set simulation time be 10sec, but actual execution time exceed 10sec. Could this be due to the inefficiency of the code? because I want real-time communication.

サインインしてコメントする。

その他の回答 (0 件)

製品


リリース

R2023b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by