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

Matlab串口读取Arduino多变量数据及绘图方法咨询

解决MATLAB串口读取多变量并绘图的方案

嘿,作为经常折腾MATLAB和Arduino串口通信的开发者,我来帮你把单变量读取的代码改成支持多变量的版本,还能实时绘制曲线!

核心思路

原来的单变量读取是直接抓取单个数值,现在要处理空格/逗号分隔的多变量行数据,关键步骤就是:

  • 读取整行带换行符的串口数据
  • 把字符串按分隔符拆分成单个数值字符串
  • 转换为数值数组后存储并实时绘图

修改后的完整代码

close all; clear all; clc;
fclose('all'); % 关闭所有残留的串口对象,避免占用

%% 1. 配置串口参数(必须和Arduino完全一致!)
port = 'COM3'; % 改成你的Arduino串口,Windows是COMx,Mac/Linux是/dev/tty.usbmodemxxx
baudRate = 9600; % 和Arduino里的Serial.begin(9600)保持一致

try
    s = serialport(port, baudRate);
    s.Terminator = 'CR/LF'; % 对应Arduino的Serial.println(),确保每次读完整一行
    flush(s); % 清空串口缓冲区的旧数据,避免一开始读残留内容
    
    %% 2. 初始化绘图和数据存储
    numVars = 6; % 假设你每次输出6个变量,根据实际情况修改
    dataHistory = zeros(0, numVars); % 存储所有历史数据
    figure; hold on; grid on;
    % 创建动态线条,每个变量一条曲线
    lines = animatedline(numVars);
    legendStr = cell(1, numVars);
    for i = 1:numVars
        lines(i).Color = hsv(numVars); % 给每条曲线分配不同颜色
        legendStr{i} = ['变量', num2str(i)];
    end
    legend(legendStr);
    xlabel('采样次数'); ylabel('数值');
    title('Arduino多变量实时曲线');
    
    %% 3. 循环读取并更新数据
    sampleCount = 0;
    disp('开始读取数据,按Ctrl+C终止程序');
    while true
        % 读取整行数据
        rawStr = fgets(s);
        if isempty(rawStr)
            continue; % 跳过空行
        end
        
        % 按空格或逗号分割字符串(同时支持两种分隔符)
        strArray = strsplit(rawStr, {' ', ','});
        % 移除空字符串(比如连续空格/逗号导致的无效元素)
        strArray = strArray(~cellfun(@isempty, strArray));
        
        % 检查分割后的数量是否符合预期,避免报错
        if length(strArray) ~= numVars
            disp(['警告:当前行数据数量不符,跳过:', rawStr]);
            continue;
        end
        
        % 转换为数值数组,捕获转换错误
        try
            currentData = str2double(strArray);
        catch ME
            disp(['数据转换失败:', ME.message]);
            continue;
        end
        
        % 存储数据并更新计数
        sampleCount = sampleCount + 1;
        dataHistory = [dataHistory; currentData];
        
        % 更新每条曲线
        for i = 1:numVars
            addpoints(lines(i), sampleCount, currentData(i));
        end
        drawnow; % 实时刷新绘图
        
    end
catch ME
    disp(['程序出错:', ME.message]);
finally
    % 确保程序结束时关闭串口,防止占用
    if exist('s', 'var') && isvalid(s)
        fclose(s);
        delete(s);
        disp('串口已关闭');
    end
end

关键修改点解释

  • 串口终止符设置:s.Terminator = 'CR/LF' 对应Arduino的Serial.println(),确保MATLAB每次读取完整的一行数据,而不是零散的字符片段。
  • 整行读取+分割:用fgets(s)读取整行,再用strsplit按空格/逗号拆分,完美解决多变量分隔的问题。
  • 数据校验:加入了空行跳过、数量匹配检查、转换错误捕获,避免程序因为脏数据直接崩溃。
  • 高效实时绘图:用animatedline比反复调用plot更高效,drawnow确保曲线实时刷新。

Arduino端配合注意事项

要确保Arduino的输出格式正确,每次输出一行,用空格/逗号分隔变量,最后加换行:

void loop() {
    // 模拟生成6个变量数据(替换成你的实际传感器数据)
    float val1 = random(0, 10) + 0.1;
    float val2 = random(0, 10) + 0.2;
    float val3 = random(0, 10) + 0.3;
    float val4 = random(0, 10) + 0.1;
    float val5 = random(0, 10) + 0.2;
    float val6 = random(0, 10) + 0.3;
    
    // 输出格式:用空格分隔,最后println换行
    Serial.print(val1); Serial.print(" ");
    Serial.print(val2); Serial.print(" ");
    Serial.print(val3); Serial.print(" ");
    Serial.print(val4); Serial.print(" ");
    Serial.print(val5); Serial.print(" ");
    Serial.println(val6);
    
    delay(100); // 固定时间间隔,比如100ms
}

小提示

  • 如果你不确定自己的串口端口,可以在MATLAB命令行输入serialportlist查看可用串口。
  • 如果曲线刷新卡顿,可以把drawnow改成drawnow limitrate,限制刷新频率,减轻CPU负担。

内容的提问来源于stack exchange,提问作者Hon Lam Franco Chan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:51:58