首页 > 解决方案 > 使用 matlab fscanf() 或 fgetl() 读取串行端口会在实际值更改后数秒显示结果

问题描述

我正在使用 Arduino 的模拟引脚来测量电压并将其打印到带有serial.print(string). 这是有效的,它以不同长度的形式输出一个值xxxx.yyyy,我用内置的串行查看器检查了这一点。要阅读它,我将Matlabfscanf()or结合使用fgetl()。这显示了正确的东西,aaaa.bbbb但是有一种奇怪的延迟。当我改变电压时,读数会滞后 5-10 秒,但是当我将电压从 0 增加到 3 到 5 时,在此timeframe期间,例如 3 到 5 之间的 3 秒,读数也会发生变化。它与我更改电压的方式不同,但它确实获得了这些值,就好像它是 2 步输入一样,即使我手动更改它们的速度不是很快。

在阅读和研究时,我发现可能是波特率太低,所以我将其更改为 Arduino 的最大值 115200。我也更改了Matlab代码中的值。我还尝试了具有该功能的 Arduino 硬件支持包,readVoltage()但它的采样率太低。

串口设置:

s = serial('com3');
set(s, 'BaudRate', 115200); % set BaudRate to 115200
set(s, 'Parity', 'none'); % set Parity Bit to None
set(s, 'DataBits', 8); % set DataBits to 8
set(s, 'StopBit', 1); % set StopBit to 1
set(s,'Terminator','LF') % set terminating character to LF/new line
fopen(s);

阅读循环:

for i =1:am
    val(:,i) = string(fgetl(s));    %retrieve value of serial port, in the form aaaa.bbbb where a and b can vary in length
    if mod(i,10) == 0           %Display every 10 iterations
        volt1 = floor(val)*5/1023;          %Calculating actual voltage for A1, where floor(val) is first value
        volt2= (volt1-floor(val))*5/0.1023;         %getting only decimals for second voltage
        plot(volt1)         %plot the values
        hold on
        plot(volt2)
        hold off
        ylim([0 5])
        xlim([i-1000 i])        %make the plot chug along
        drawnow                 %Live
    end
    clc
    toc
end

没有错误消息,并且使用另一个串行端口,我没有明显的延迟。这也应该可以使用 Matlab,因为人们使用它可以获得 2-3kHz 的刷新率。

标签: matlabarduinoserial-communication

解决方案


问题是您plot在循环中使用的方式。这是非常低效的。

根据您的 Matlab 版本和串行链接上的开销,您可能能够加快clf循环开始时的调用速度,以防止大量图相互堆叠。

如果问题仍然存在,您可能想尝试animated lineaddpoints在循环中。

最后,您可能需要检查几件事:Matlab 的Arduino 连接(我自己从未尝试过,但我读过它提供了良好的性能)和串行端口上的延迟计时器(这可能会产生影响在低波特率)。


推荐阅读