You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否将MATLAB工作区实时更新的全局变量用于Simulink?

问题描述

我用MATLAB编写程序,通过串口连接ESP32读取数据,提取角度(单位:度或弧度)和角速度(单位:度/秒或弧度/秒),分别存储为变量th和vth。ESP32发送的数据格式为E1, t, thx , th_y , th_z, vth_x, vth_y, vth_z \n,我通过readline函数循环读取每行字符串,并使用以下代码配置回调实现持续读取:

configureCallback(device, "terminator", @readSerialData)

为了将t、th、vth存入工作区,我声明了全局变量,通过回调函数实现数据实时覆盖更新,完整代码如下:

clc
clear
close
global splitdata t th vth
portavailable = serialportlist("available");

device = serialport("COM8",500000);

%data = read(device,47,"string")
%splitdata = splitlines(data)

configureCallback(device,"terminator", @readSerialData)

function readSerialData(src,~)
    global splitdata t th vth
    alinedata = readline(src);
    disp(alinedata);

    data = evalc('disp(alinedata)'); 
    splitdata = split(data,',');
    %disp(splitdata)

    t = str2double(splitdata{2})/1000;

    th(1) = str2double(splitdata{3});
    th(2) = str2double(splitdata{4});
    th(3) = str2double(splitdata{5});

    vth(1) = str2double(splitdata{6});
    vth(2) = str2double(splitdata{7});
    vth(3) = str2double(splitdata{8});
end

我尝试用Simulink的From Workspace块调用这些变量,但运行Simulink仿真时,MATLAB的回调停止,变量不再更新。请问这种方式可行吗?若不可行,应如何解决?


解决方案

这种直接通过全局变量+From Workspace块的方式不可行,核心原因是:Simulink仿真运行时会独占MATLAB的执行线程,而MATLAB的串口回调是基于单线程事件队列实现的——仿真过程中事件队列会被暂停,导致串口数据无法被实时处理和更新。

推荐两种解决方法,优先选择第一种:

方法1:使用Simulink原生串口模块直接读取数据

Simulink的Instrument Control Toolbox提供了专门的串口通信模块,无需依赖MATLAB脚本回调,可直接在模型内完成数据读取与解析:

  • 拖入Serial Receive模块,配置端口为COM8、波特率500000,终止符设置为\n
  • 使用String Split模块(或MATLAB Function模块)拆分收到的字符串,提取t、th各分量、vth各分量
  • 直接在Simulink模型中使用解析后的数据,无需依赖工作区变量

这种方式的优势是Simulink会独立处理串口数据的实时读取,与仿真线程完全兼容,不会出现阻塞问题,流程更简洁可靠。

方法2:通过数据存储区实现Simulink与MATLAB工作区的实时交互

如果必须保留MATLAB脚本的回调逻辑,可以借助Simulink的Data Store系列模块实现数据同步:

  1. 在MATLAB中准备数据存储区:
    • 在工作区创建数据存储对象:
      t_ds = Simulink.Signal; t_ds.DataType = 'double';
      th_ds = Simulink.Signal; th_ds.DataType = 'double'; th_ds.Dimensions = [1 3];
      vth_ds = Simulink.Signal; vth_ds.DataType = 'double'; vth_ds.Dimensions = [1 3];
      
    • 修改回调函数,去掉冗余的evalc操作,直接拆分字符串并将数据写入工作区,同时更新数据存储区:
      function readSerialData(src,~)
          alinedata = readline(src);
          splitdata = split(alinedata,',');
          
          % 更新工作区变量
          t_val = str2double(splitdata{2})/1000;
          th_val = [str2double(splitdata{3}), str2double(splitdata{4}), str2double(splitdata{5})];
          vth_val = [str2double(splitdata{6}), str2double(splitdata{7}), str2double(splitdata{8})];
          
          assignin('base','t', t_val);
          assignin('base','th', th_val);
          assignin('base','vth', vth_val);
          
          % 更新Simulink数据存储区
          set_param('你的模型名称/Data Store Memory_t','Value','t');
          set_param('你的模型名称/Data Store Memory_th','Value','th');
          set_param('你的模型名称/Data Store Memory_vth','Value','vth');
      end
      
  2. 在Simulink模型中配置数据存储:
    • 添加三个Data Store Memory模块,分别命名为Data Store Memory_t、Data Store Memory_th、Data Store Memory_vth,对应设置数据类型和维度
    • 使用Data Store Read模块读取数据,替代原来的From Workspace块

另外,原回调中的evalc('disp(alinedata)')完全多余,直接用alinedata拆分字符串即可,这部分优化能减少不必要的性能开销。


内容的提问来源于stack exchange,提问作者TRIMET JINDAIN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:35:44