Effacer les filtres
Effacer les filtres

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

10 vues (au cours des 30 derniers jours)
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!

Réponse acceptée

Walter Roberson
Walter Roberson le 21 Mai 2024
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 commentaire
You-Cheng
You-Cheng le 21 Mai 2024
Modifié(e) : You-Cheng le 21 Mai 2024
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.

Connectez-vous pour commenter.

Plus de réponses (0)

Community Treasure Hunt

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

Start Hunting!

Translated by